<commit_before>package edit

import (
	"io/ioutil"
	"path"
	"sort"
	"strings"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/util"
)

// A completer takes the current Node and an Editor and returns a list of
// candidates. the Node is always a leaf in the parsed AST.
type completer func(parse.Node, *Editor) []*candidate

var completers = []struct {
	name string
	completer
}{
	{"variable", complVariable},
	{"command name", complNewForm},
	{"command name", makeCompoundCompleter(complFormHead)},
	{"argument", complNewArg},
	{"argument", makeCompoundCompleter(complArg)},
}

func complVariable(n parse.Node, ed *Editor) []*candidate {
	primary, ok := n.(*parse.Primary)
	if !ok || primary.Type != parse.Variable {
		return nil
	}

	head := primary.Value

	// Collect matching variables.
	var varnames []string
	for varname := range eval.Builtin() {
		if strings.HasPrefix(varname, head) {
			varnames = append(varnames, varname)
		}
	}
	for varname := range ed.evaler.Global() {
		if strings.HasPrefix(varname, head) {
			varnames = append(varnames, varname)
		}
	}
	sort.Strings(varnames)

	// Build candidates.
	cands := []*candidate{}
	for _, varname := range varnames {
		cands = append(cands, &candidate{
			source: styled{varname[len(head):], styleForType[Variable]},
			menu:   styled{"$" + varname, ""}})
	}

	return cands
}

func complNewForm(n parse.Node, ed *Editor) []*candidate {
	if _, ok := n.(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	if _, ok := n.Parent().(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	return nil
}

// XXX Semantics of candidate is pretty broken here.
func makeCompoundCompleter(
	f func(*parse.Compound, string, *Editor) []*candidate) completer {
	return func(n parse.Node, ed *Editor) []*candidate {
		pn, ok := n.(*parse.Primary)
		if !ok {
			return nil
		}
		cn, head := simpleCompound(pn)
		if cn == nil {
			return nil
		}
		cands := f(cn, head, ed)
		for _, cand := range cands {
			// Deal with quoting by trying to continue the quoting of the last
			// primary.
			newSource, q := parse.QuoteAs(cand.source.text, pn.Type)
			for _, quoting := range parse.QuotingStyles {
				if pn.Type == quoting.Type &&
					!strings.HasSuffix(pn.SourceText(), string(quoting.Quoter)) {
					// The last primary has unclosed quoting.
					if q == quoting.Type {
						// The completed text was quoted using the same style;
						// elide the leading quoter.
						newSource = newSource[len(quoting.Quoter):]
					} else {
						// The completed text was quoted using a different
						// style. Prepend a quoter to close the existing text.
						newSource = quoting.Quoter + newSource
					}
				}
			}

			cand.source.text = newSource + cand.sourceSuffix
		}
		return cands
	}
}

func complFormHead(cn *parse.Compound, head string, ed *Editor) []*candidate {
	if isFormHead(cn) {
		return complFormHeadInner(head, ed)
	}
	return nil
}

func complFormHeadInner(head string, ed *Editor) []*candidate {
	if util.DontSearch(head) {
		return complArgInner(head, ed, true)
	}

	cands := []*candidate{}

	foundCommand := func(s string) {
		if strings.HasPrefix(s, head) {
			cands = append(cands, &candidate{
				source: styled{s[len(head):], styleForGoodCommand},
				menu:   styled{s, ""},
			})
		}
	}
	for special := range isBuiltinSpecial {
		foundCommand(special)
	}
	for variable := range eval.Builtin() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for variable := range ed.evaler.Global() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for command := range ed.isExternal {
		foundCommand(command)
	}
	return cands
}

func complNewArg(n parse.Node, ed *Editor) []*candidate {
	sn, ok := n.(*parse.Sep)
	if !ok {
		return nil
	}
	if _, ok := sn.Parent().(*parse.Form); !ok {
		return nil
	}
	return complArgInner("", ed, false)
}

func complArg(cn *parse.Compound, head string, ed *Editor) []*candidate {
	return complArgInner(head, ed, false)
}

// TODO: getStyle does redundant stats.
func complArgInner(head string, ed *Editor, formHead bool) []*candidate {
	dir, fileprefix := path.Split(head)
	if dir == "" {
		dir = "."
	}

	infos, err := ioutil.ReadDir(dir)
	cands := []*candidate{}

	if err != nil {
		ed.addTip("cannot list directory %s: %v", dir, err)
		return cands
	}

	// Make candidates out of elements that match the file component.
	for _, info := range infos {
		name := info.Name()
		// Irrevelant file.
		if !strings.HasPrefix(name, fileprefix) {
			continue
		}
		// Hide dot files unless file starts with a dot.
		if !dotfile(fileprefix) && dotfile(name) {
			continue
		}
		// Only accept searchable directories and executable files if
		// completing head.
		if formHead && !(info.IsDir() || (info.Mode()&0111) != 0) {
			continue
		}

		// Full filename for .getStyle.
		full := head + name[len(fileprefix):]

		var suffix string
		if info.IsDir() {
			suffix = "/"
		} else {
			suffix = " "
		}

		cands = append(cands, &candidate{
			source:       styled{name[len(fileprefix):], ""},
			menu:         styled{name, defaultLsColor.getStyle(full)},
			sourceSuffix: suffix,
		})
	}

	return cands
}

func dotfile(fname string) bool {
	return strings.HasPrefix(fname, ".")
}
<commit_msg>edit: Fix bogus '' completion.<commit_after>package edit

import (
	"io/ioutil"
	"path"
	"sort"
	"strings"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/util"
)

// A completer takes the current Node and an Editor and returns a list of
// candidates. the Node is always a leaf in the parsed AST.
type completer func(parse.Node, *Editor) []*candidate

var completers = []struct {
	name string
	completer
}{
	{"variable", complVariable},
	{"command name", complNewForm},
	{"command name", makeCompoundCompleter(complFormHead)},
	{"argument", complNewArg},
	{"argument", makeCompoundCompleter(complArg)},
}

func complVariable(n parse.Node, ed *Editor) []*candidate {
	primary, ok := n.(*parse.Primary)
	if !ok || primary.Type != parse.Variable {
		return nil
	}

	head := primary.Value

	// Collect matching variables.
	var varnames []string
	for varname := range eval.Builtin() {
		if strings.HasPrefix(varname, head) {
			varnames = append(varnames, varname)
		}
	}
	for varname := range ed.evaler.Global() {
		if strings.HasPrefix(varname, head) {
			varnames = append(varnames, varname)
		}
	}
	sort.Strings(varnames)

	// Build candidates.
	cands := []*candidate{}
	for _, varname := range varnames {
		cands = append(cands, &candidate{
			source: styled{varname[len(head):], styleForType[Variable]},
			menu:   styled{"$" + varname, ""}})
	}

	return cands
}

func complNewForm(n parse.Node, ed *Editor) []*candidate {
	if _, ok := n.(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	if _, ok := n.Parent().(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	return nil
}

// XXX Semantics of candidate is pretty broken here.
func makeCompoundCompleter(
	f func(*parse.Compound, string, *Editor) []*candidate) completer {
	return func(n parse.Node, ed *Editor) []*candidate {
		pn, ok := n.(*parse.Primary)
		if !ok {
			return nil
		}
		cn, head := simpleCompound(pn)
		if cn == nil {
			return nil
		}
		cands := f(cn, head, ed)
		for _, cand := range cands {
			// Deal with quoting by trying to continue the quoting of the last
			// primary.
			newSource, q := parse.QuoteAs(cand.source.text, pn.Type)
			for _, quoting := range parse.QuotingStyles {
				if pn.Type == quoting.Type &&
					!strings.HasSuffix(pn.SourceText(), string(quoting.Quoter)) {
					// The last primary has unclosed quoting.
					if q == quoting.Type {
						// The completed text was quoted using the same style;
						// elide the leading quoter.
						newSource = newSource[len(quoting.Quoter):]
					} else {
						// The completed text was quoted using a different
						// style. Prepend a quoter to close the existing text.
						newSource = quoting.Quoter + newSource
					}
				}
			}

			// Don't add bogus '' if the candidate has an empty source.
			// XXX Might be wrong.
			if newSource == "''" {
				newSource = ""
			}
			cand.source.text = newSource + cand.sourceSuffix
		}
		return cands
	}
}

func complFormHead(cn *parse.Compound, head string, ed *Editor) []*candidate {
	if isFormHead(cn) {
		return complFormHeadInner(head, ed)
	}
	return nil
}

func complFormHeadInner(head string, ed *Editor) []*candidate {
	if util.DontSearch(head) {
		return complArgInner(head, ed, true)
	}

	cands := []*candidate{}

	foundCommand := func(s string) {
		if strings.HasPrefix(s, head) {
			cands = append(cands, &candidate{
				source: styled{s[len(head):], styleForGoodCommand},
				menu:   styled{s, ""},
			})
		}
	}
	for special := range isBuiltinSpecial {
		foundCommand(special)
	}
	for variable := range eval.Builtin() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for variable := range ed.evaler.Global() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for command := range ed.isExternal {
		foundCommand(command)
	}
	return cands
}

func complNewArg(n parse.Node, ed *Editor) []*candidate {
	sn, ok := n.(*parse.Sep)
	if !ok {
		return nil
	}
	if _, ok := sn.Parent().(*parse.Form); !ok {
		return nil
	}
	return complArgInner("", ed, false)
}

func complArg(cn *parse.Compound, head string, ed *Editor) []*candidate {
	return complArgInner(head, ed, false)
}

// TODO: getStyle does redundant stats.
func complArgInner(head string, ed *Editor, formHead bool) []*candidate {
	dir, fileprefix := path.Split(head)
	if dir == "" {
		dir = "."
	}

	infos, err := ioutil.ReadDir(dir)
	cands := []*candidate{}

	if err != nil {
		ed.addTip("cannot list directory %s: %v", dir, err)
		return cands
	}

	// Make candidates out of elements that match the file component.
	for _, info := range infos {
		name := info.Name()
		// Irrevelant file.
		if !strings.HasPrefix(name, fileprefix) {
			continue
		}
		// Hide dot files unless file starts with a dot.
		if !dotfile(fileprefix) && dotfile(name) {
			continue
		}
		// Only accept searchable directories and executable files if
		// completing head.
		if formHead && !(info.IsDir() || (info.Mode()&0111) != 0) {
			continue
		}

		// Full filename for .getStyle.
		full := head + name[len(fileprefix):]

		var suffix string
		if info.IsDir() {
			suffix = "/"
		} else {
			suffix = " "
		}

		cands = append(cands, &candidate{
			source:       styled{name[len(fileprefix):], ""},
			menu:         styled{name, defaultLsColor.getStyle(full)},
			sourceSuffix: suffix,
		})
	}

	return cands
}

func dotfile(fname string) bool {
	return strings.HasPrefix(fname, ".")
}
<|endoftext|>


<commit_before>package emitter

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
	"gopkg.in/vmihailenco/msgpack.v1"
)

const (
	event              = 2
	binaryEvent        = 5
	redisPoolMaxIdle   = 80
	redisPoolMaxActive = 12000 // max number of connections
)

// Options ...
type Options struct {
	Host     string
	Password string
	Key      string
}

//Emitter ... Socket.io Emitter
type Emitter struct {
	_opts  Options
	_key   string
	_flags map[string]string
	_rooms map[string]bool
	_pool  *redis.Pool
}

// New ... Creates new Emitter using options
func New(opts Options) Emitter {
	emitter := Emitter{_opts: opts}

	initRedisConnPool(&emitter, opts)

	if opts.Key != "" {
		emitter._key = fmt.Sprintf("%s#emitter", opts.Key)
	} else {
		emitter._key = "socket.io#emitter"
	}

	emitter._rooms = make(map[string]bool)
	emitter._flags = make(map[string]string)

	return emitter
}

// In ... Limit emission to a certain `room`.`
func (emitter Emitter) In(room string) Emitter {
	if _, ok := emitter._rooms[room]; ok == false {
		emitter._rooms[room] = true
	}
	return emitter
}

// To ... Limit emission to a certain `room`.
func (emitter Emitter) To(room string) Emitter {
	return emitter.In(room)
}

// Of ... To Limit emission to certain `namespace`.
func (emitter Emitter) Of(nsp string) Emitter {
	emitter._flags["nsp"] = nsp
	return emitter
}

// Emit ... Send the packet.
func (emitter Emitter) Emit(args ...interface{}) bool {
	packet := make(map[string]interface{})
	extras := make(map[string]interface{})

	if ok := emitter.hasBin(args); ok {
		packet["type"] = binaryEvent
	} else {
		packet["type"] = event
	}

	packet["data"] = args

	if value, ok := emitter._flags["nsp"]; ok {
		packet["nsp"] = value
		delete(emitter._flags, "nsp")
	} else {
		packet["nsp"] = "/"
	}

	if ok := len(emitter._rooms); ok > 0 {
		//TODO:Cast??
		extras["rooms"] = getKeys(emitter._rooms)
	} else {
		extras["rooms"] = make([]string, 0, 0)
	}

	if ok := len(emitter._flags); ok > 0 {
		extras["flags"] = emitter._flags
	} else {
		extras["flags"] = make(map[string]string)
	}

	//TODO: Goroutines
	//Pack & Publish
	b, err := msgpack.Marshal([]interface{}{packet, extras})
	if err != nil {
		panic(err)
	} else {
		publish(emitter, emitter._key, b)
	}

	emitter._rooms = make(map[string]bool)
	emitter._flags = make(map[string]string)

	return true
}

func (emitter Emitter) hasBin(args ...interface{}) bool {
	//NOT implemented yet!
	return true
}

func initRedisConnPool(emitter *Emitter, opts Options) {
	if opts.Host == "" {
		panic("Missing redis `host`")
	}

	emitter._pool = newPool(opts)
}

func newPool(opts Options) *redis.Pool {
	return &redis.Pool{
		MaxIdle:   redisPoolMaxIdle,
		MaxActive: redisPoolMaxActive,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", opts.Host)
			if err != nil {
				return nil, err
			}

			if opts.Password != "" {
				if _, err := c.Do("AUTH", opts.Password); err != nil {
					c.Close()
					return nil, err
				}
				return c, err
			}

			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}

}

func publish(emitter Emitter, channel string, value interface{}) {
	c := emitter._pool.Get()
	defer c.Close()
	c.Do("PUBLISH", channel, value)

}

func getKeys(m map[string]bool) []string {
	keys := make([]string, 0, len(m))

	for key := range m {
		keys = append(keys, key)
	}

	return keys
}

// Print emitter details
func dump(emitter Emitter, args ...interface{}) {
	fmt.Println("Emit params : ", args)
	fmt.Println("Emitter key: ", emitter._key)
	fmt.Println("Emitter flags: ", emitter._flags)
	fmt.Println("Emitter rooms: ", emitter._rooms)
}
<commit_msg>Update emitter.go<commit_after>package emitter

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
	"gopkg.in/vmihailenco/msgpack.v1"
)

const (
	event              = 2
	binaryEvent        = 5
	redisPoolMaxIdle   = 80
	redisPoolMaxActive = 12000 // max number of connections
)

// Options ...
type Options struct {
	Host     string
	Password string
	Key      string
}

//Emitter ... Socket.io Emitter
type Emitter struct {
	_opts  Options
	_key   string
	_flags map[string]string
	_rooms map[string]bool
	_pool  *redis.Pool
}

// New ... Creates new Emitter using options
func New(opts Options) Emitter {
	emitter := Emitter{_opts: opts}

	initRedisConnPool(&emitter, opts)

	if opts.Key != "" {
		emitter._key = fmt.Sprintf("%s#emitter", opts.Key)
	} else {
		emitter._key = "socket.io#emitter"
	}

	emitter._rooms = make(map[string]bool)
	emitter._flags = make(map[string]string)

	return emitter
}

// In ... Limit emission to a certain `room`.`
func (emitter Emitter) In(room string) Emitter {
	if _, ok := emitter._rooms[room]; ok == false {
		emitter._rooms[room] = true
	}
	return emitter
}

// To ... Limit emission to a certain `room`.
func (emitter Emitter) To(room string) Emitter {
	return emitter.In(room)
}

// Of ... To Limit emission to certain `namespace`.
func (emitter Emitter) Of(nsp string) Emitter {
	emitter._flags["nsp"] = nsp
	return emitter
}

// Emit ... Send the packet.
func (emitter Emitter) Emit(args ...interface{}) bool {
	packet := make(map[string]interface{})
	extras := make(map[string]interface{})

	if ok := emitter.hasBin(args); ok {
		packet["type"] = binaryEvent
	} else {
		packet["type"] = event
	}

	packet["data"] = args

	if value, ok := emitter._flags["nsp"]; ok {
		packet["nsp"] = value
		delete(emitter._flags, "nsp")
	} else {
		packet["nsp"] = "/"
	}

	if ok := len(emitter._rooms); ok > 0 {
		extras["rooms"] = getKeys(emitter._rooms)
	} else {
		extras["rooms"] = make([]string, 0, 0)
	}

	if ok := len(emitter._flags); ok > 0 {
		extras["flags"] = emitter._flags
	} else {
		extras["flags"] = make(map[string]string)
	}

	//Pack & Publish
	b, err := msgpack.Marshal([]interface{}{packet, extras})
	if err != nil {
		panic(err)
	} else {
		publish(emitter, emitter._key, b)
	}

	emitter._rooms = make(map[string]bool)
	emitter._flags = make(map[string]string)

	return true
}

func (emitter Emitter) hasBin(args ...interface{}) bool {
	//NOT implemented yet!
	return true
}

func initRedisConnPool(emitter *Emitter, opts Options) {
	if opts.Host == "" {
		panic("Missing redis `host`")
	}

	emitter._pool = newPool(opts)
}

func newPool(opts Options) *redis.Pool {
	return &redis.Pool{
		MaxIdle:   redisPoolMaxIdle,
		MaxActive: redisPoolMaxActive,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", opts.Host)
			if err != nil {
				return nil, err
			}

			if opts.Password != "" {
				if _, err := c.Do("AUTH", opts.Password); err != nil {
					c.Close()
					return nil, err
				}
				return c, err
			}

			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}

}

func publish(emitter Emitter, channel string, value interface{}) {
	c := emitter._pool.Get()
	defer c.Close()
	c.Do("PUBLISH", channel, value)

}

func getKeys(m map[string]bool) []string {
	keys := make([]string, 0, len(m))

	for key := range m {
		keys = append(keys, key)
	}

	return keys
}

// Print emitter details
func dump(emitter Emitter, args ...interface{}) {
	fmt.Println("Emit params : ", args)
	fmt.Println("Emitter key: ", emitter._key)
	fmt.Println("Emitter flags: ", emitter._flags)
	fmt.Println("Emitter rooms: ", emitter._rooms)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"
	"time"

	"../../goble"
)

func main() {
	verbose := flag.Bool("verbose", false, "dump all events")
	advertise := flag.Int("advertise", 0, "Duration of advertising - 0: does not advertise")
	dups := flag.Bool("allow-duplicates", false, "allow duplicates when scanning")
	ibeacon := flag.Int("ibeacon", 0, "Duration of IBeacon advertising - 0: does not advertise")
	scan := flag.Int("scan", 10, "Duration of scanning - 0: does not scan")
	uuid := flag.String("uuid", "", "device uuid (for ibeacon uuid,major,minor,power)")
	connect := flag.Bool("connect", false, "connect to device")
	disconnect := flag.Bool("disconnect", false, "disconnect from device")
	rssi := flag.Bool("rssi", false, "update rssi for device")
	remove := flag.Bool("remove", false, "Remove all services")
	discover := flag.Bool("discover", false, "Discover services")

	flag.Parse()

	ble := goble.New()

	ble.SetVerbose(*verbose)

	log.Println("Init...")
	ble.Init()

	if *advertise > 0 {
		uuids := []goble.UUID{}

		if len(*uuid) > 0 {
			uuids = append(uuids, goble.MakeUUID(*uuid))
		}

		time.Sleep(1 * time.Second)
		log.Println("Start Advertising...")
		ble.StartAdvertising("gobble", uuids)

		time.Sleep(time.Duration(*advertise) * time.Second)
		log.Println("Stop Advertising...")
		ble.StopAdvertising()
	}

	if *ibeacon > 0 {
		parts := strings.Split(*uuid, ",")
		id := parts[0]

		var major, minor uint16
		var measuredPower int8

		if len(parts) > 1 {
			fmt.Sscanf(parts[1], "%d", &major)
		}
		if len(parts) > 2 {
			fmt.Sscanf(parts[2], "%d", &minor)
		}
		if len(parts) > 2 {
			fmt.Sscanf(parts[3], "%d", &measuredPower)
		}

		time.Sleep(1 * time.Second)
		log.Println("Start Advertising IBeacon...")
		ble.StartAdvertisingIBeacon(goble.MakeUUID(id), major, minor, measuredPower)

		time.Sleep(time.Duration(*ibeacon) * time.Second)
		log.Println("Stop Advertising...")
		ble.StopAdvertising()
	}

	if *scan > 0 {
		time.Sleep(1 * time.Second)
		log.Println("Start Scanning...")
		ble.StartScanning(nil, *dups)

		time.Sleep(time.Duration(*scan) * time.Second)
		log.Println("Stop Scanning...")
		ble.StopScanning()
	}

	if *connect {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("Connect", uuid)
		ble.Connect(uuid)
		time.Sleep(5 * time.Second)
	}

	if *rssi {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("UpdateRssi", uuid)
		ble.UpdateRssi(uuid)
		time.Sleep(5 * time.Second)
	}

	if *discover {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("DiscoverServices", uuid)
		ble.DiscoverServices(uuid, nil)
		time.Sleep(5 * time.Second)
	}

	if *disconnect {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("Disconnect", uuid)
		ble.Disconnect(uuid)
		time.Sleep(5 * time.Second)
	}

	if *remove {
		time.Sleep(1 * time.Second)
		log.Println("Remove all services")
		ble.RemoveServices()
		time.Sleep(5 * time.Second)
	}

	time.Sleep(5 * time.Second)
	log.Println("Goodbye!")
}
<commit_msg>Changed durations to flag.Duration / time.Duration<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"
	"time"

	"../../goble"
)

func main() {
	verbose := flag.Bool("verbose", false, "dump all events")
	advertise := flag.Duration("advertise", 0, "Duration of advertising - 0: does not advertise")
	dups := flag.Bool("allow-duplicates", false, "allow duplicates when scanning")
	ibeacon := flag.Duration("ibeacon", 0, "Duration of IBeacon advertising - 0: does not advertise")
	scan := flag.Duration("scan", 10, "Duration of scanning - 0: does not scan")
	uuid := flag.String("uuid", "", "device uuid (for ibeacon uuid,major,minor,power)")
	connect := flag.Bool("connect", false, "connect to device")
	disconnect := flag.Bool("disconnect", false, "disconnect from device")
	rssi := flag.Bool("rssi", false, "update rssi for device")
	remove := flag.Bool("remove", false, "Remove all services")
	discover := flag.Bool("discover", false, "Discover services")

	flag.Parse()

	ble := goble.New()

	ble.SetVerbose(*verbose)

	log.Println("Init...")
	ble.Init()

	if *advertise > 0 {
		uuids := []goble.UUID{}

		if len(*uuid) > 0 {
			uuids = append(uuids, goble.MakeUUID(*uuid))
		}

		time.Sleep(1 * time.Second)
		log.Println("Start Advertising...")
		ble.StartAdvertising("gobble", uuids)

		time.Sleep(*advertise)
		log.Println("Stop Advertising...")
		ble.StopAdvertising()
	}

	if *ibeacon > 0 {
		parts := strings.Split(*uuid, ",")
		id := parts[0]

		var major, minor uint16
		var measuredPower int8

		if len(parts) > 1 {
			fmt.Sscanf(parts[1], "%d", &major)
		}
		if len(parts) > 2 {
			fmt.Sscanf(parts[2], "%d", &minor)
		}
		if len(parts) > 2 {
			fmt.Sscanf(parts[3], "%d", &measuredPower)
		}

		time.Sleep(1 * time.Second)
		log.Println("Start Advertising IBeacon...")
		ble.StartAdvertisingIBeacon(goble.MakeUUID(id), major, minor, measuredPower)

		time.Sleep(*ibeacon)
		log.Println("Stop Advertising...")
		ble.StopAdvertising()
	}

	if *scan > 0 {
		time.Sleep(1 * time.Second)
		log.Println("Start Scanning...")
		ble.StartScanning(nil, *dups)

		time.Sleep(*scan)
		log.Println("Stop Scanning...")
		ble.StopScanning()
	}

	if *connect {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("Connect", uuid)
		ble.Connect(uuid)
		time.Sleep(5 * time.Second)
	}

	if *rssi {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("UpdateRssi", uuid)
		ble.UpdateRssi(uuid)
		time.Sleep(5 * time.Second)
	}

	if *discover {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("DiscoverServices", uuid)
		ble.DiscoverServices(uuid, nil)
		time.Sleep(5 * time.Second)
	}

	if *disconnect {
		time.Sleep(1 * time.Second)
		uuid := goble.MakeUUID(*uuid)
		log.Println("Disconnect", uuid)
		ble.Disconnect(uuid)
		time.Sleep(5 * time.Second)
	}

	if *remove {
		time.Sleep(1 * time.Second)
		log.Println("Remove all services")
		ble.RemoveServices()
		time.Sleep(5 * time.Second)
	}

	time.Sleep(5 * time.Second)
	log.Println("Goodbye!")
}
<|endoftext|>


<commit_before>package sqlrow_test

import (
	"database/sql"
	"log"

	"github.com/jjeffery/sqlrow"
)

var db *sql.DB

func ExamplePrepare() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	_, err = stmt.Exec(db, row)
}

func ExampleSchema_Prepare() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	stmt, err := mssql.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	_, err = stmt.Exec(db, row)
}

func ExampleStmt_Exec_insert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	_, err = stmt.Exec(db, row)
}

func ExampleStmt_Exec_update() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `update users set {} where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		ID:         42,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	_, err = stmt.Exec(db, row)
}

func ExampleStmt_Exec_delete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `delete from users where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		ID:         42,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	_, err = stmt.Exec(db, row)
}

func ExampleStmt_Select_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `select {} from users where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	// find user with ID=42
	var row UserRow
	n, err := stmt.Select(db, &row, 42)
	if err != nil {
		log.Fatal(err)
	}
	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleStmt_Select_multipleRows() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `
		select {alias u}
		from users u
		inner join user_search_terms t on t.user_id = u.id
		where t.search_term like ?
		limit ? offset ?`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	// find users with search terms
	var rows []UserRow
	n, err := stmt.Select(db, &rows, "smith%", 0, 100)
	if err != nil {
		log.Fatal(err)
	}
	if n > 0 {
		for i, row := range rows {
			log.Printf("row %d: %v", i, row)
		}
	} else {
		log.Printf("not found")
	}
}

func ExampleInsert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	err := sqlrow.Insert(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	// row.ID will contain the new ID for the row
	log.Printf("Row inserted, ID=%d", row.ID)
}

func ExampleSchema_Insert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	err := mssql.Insert(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	// row.ID will contain the new ID for the row
	log.Printf("Row inserted, ID=%d", row.ID)
}

func ExampleUpdate() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := sqlrow.Update(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows updated = %d", n)
}

func ExampleSchema_Update() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := mssql.Update(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows updated = %d", n)
}

func ExampleDelete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := sqlrow.Delete(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows deleted = %d", n)
}

func ExampleSchema_Delete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := mssql.Delete(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows deleted = %d", n)
}

func ExampleDialectFor() {
	// Set the default dialect for PostgreSQL.
	sqlrow.Default.Dialect = sqlrow.DialectFor("postgres")
}

func ExampleSelect_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// find user with ID=42
	var row UserRow
	n, err := sqlrow.Select(db, &row, `select {} from users where ID=?`, 42)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleSchema_Select_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	// find user with ID=42
	var row UserRow
	n, err := mssql.Select(db, &row, `select {} from [Users] where ID=?`, 42)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleSchema_Select_multipleRows() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	// find users with search terms
	var rows []UserRow
	n, err := mssql.Select(db, &rows, `
		select {alias u}
		from [Users] u
		inner join [UserSearchTerms] t on t.UserID = u.ID
		where t.SearchTerm like ?
		limit ? offset ?`, "smith%", 0, 100)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		for i, row := range rows {
			log.Printf("row %d: %v", i, row)
		}
	} else {
		log.Printf("not found")
	}
}
<commit_msg>Fix golint IneffAssign warnings in examples.<commit_after>package sqlrow_test

import (
	"database/sql"
	"log"

	"github.com/jjeffery/sqlrow"
)

var db *sql.DB

func ExamplePrepare() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}

	_, err = stmt.Exec(db, row)

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

func ExampleSchema_Prepare() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	stmt, err := mssql.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}

	_, err = stmt.Exec(db, row)

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

func ExampleStmt_Exec_insert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `insert into users({}) values({})`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}

	_, err = stmt.Exec(db, row)

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

func ExampleStmt_Exec_update() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `update users set {} where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		ID:         42,
		GivenName:  "John",
		FamilyName: "Citizen",
	}

	_, err = stmt.Exec(db, row)

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

func ExampleStmt_Exec_delete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `delete from users where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	row := UserRow{
		ID:         42,
		GivenName:  "John",
		FamilyName: "Citizen",
	}

	_, err = stmt.Exec(db, row)

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

func ExampleStmt_Select_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `select {} from users where {}`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	// find user with ID=42
	var row UserRow
	n, err := stmt.Select(db, &row, 42)
	if err != nil {
		log.Fatal(err)
	}
	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleStmt_Select_multipleRows() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	stmt, err := sqlrow.Prepare(UserRow{}, `
		select {alias u}
		from users u
		inner join user_search_terms t on t.user_id = u.id
		where t.search_term like ?
		limit ? offset ?`)
	if err != nil {
		log.Fatal(err)
	}

	// ... later on ...

	// find users with search terms
	var rows []UserRow
	n, err := stmt.Select(db, &rows, "smith%", 0, 100)
	if err != nil {
		log.Fatal(err)
	}
	if n > 0 {
		for i, row := range rows {
			log.Printf("row %d: %v", i, row)
		}
	} else {
		log.Printf("not found")
	}
}

func ExampleInsert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	err := sqlrow.Insert(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	// row.ID will contain the new ID for the row
	log.Printf("Row inserted, ID=%d", row.ID)
}

func ExampleSchema_Insert() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	err := mssql.Insert(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	// row.ID will contain the new ID for the row
	log.Printf("Row inserted, ID=%d", row.ID)
}

func ExampleUpdate() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := sqlrow.Update(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows updated = %d", n)
}

func ExampleSchema_Update() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := mssql.Update(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows updated = %d", n)
}

func ExampleDelete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := sqlrow.Delete(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows deleted = %d", n)
}

func ExampleSchema_Delete() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	row := UserRow{
		ID:         43,
		GivenName:  "John",
		FamilyName: "Citizen",
	}
	n, err := mssql.Delete(db, &row, "users")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Number of rows deleted = %d", n)
}

func ExampleDialectFor() {
	// Set the default dialect for PostgreSQL.
	sqlrow.Default.Dialect = sqlrow.DialectFor("postgres")
}

func ExampleSelect_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// find user with ID=42
	var row UserRow
	n, err := sqlrow.Select(db, &row, `select {} from users where ID=?`, 42)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleSchema_Select_oneRow() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	// find user with ID=42
	var row UserRow
	n, err := mssql.Select(db, &row, `select {} from [Users] where ID=?`, 42)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		log.Printf("found: %v", row)
	} else {
		log.Printf("not found")
	}
}

func ExampleSchema_Select_multipleRows() {
	type UserRow struct {
		ID         int `sql:"primary key autoincrement"`
		GivenName  string
		FamilyName string
	}

	// Schema for an MSSQL database, where column names
	// are the same as the Go struct field names.
	mssql := sqlrow.Schema{
		Dialect:    sqlrow.DialectFor("mssql"),
		Convention: sqlrow.ConventionSame,
	}

	// find users with search terms
	var rows []UserRow
	n, err := mssql.Select(db, &rows, `
		select {alias u}
		from [Users] u
		inner join [UserSearchTerms] t on t.UserID = u.ID
		where t.SearchTerm like ?
		limit ? offset ?`, "smith%", 0, 100)
	if err != nil {
		log.Fatal(err)
	}

	if n > 0 {
		for i, row := range rows {
			log.Printf("row %d: %v", i, row)
		}
	} else {
		log.Printf("not found")
	}
}
<|endoftext|>


<commit_before>package github

import (
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/rs/zerolog/log"
)

// EventHandler handles http events for Github integration
type EventHandler interface {
	Handle(*gin.Context)
	HandlePushEvent(PushEvent)
}

type eventHandlerImpl struct {
	eventsChannel                chan PushEvent
	prometheusInboundEventTotals *prometheus.CounterVec
}

// NewGithubEventHandler returns a github.EventHandler to handle incoming webhook events
func NewGithubEventHandler(eventsChannel chan PushEvent, prometheusInboundEventTotals *prometheus.CounterVec) EventHandler {
	return &eventHandlerImpl{
		eventsChannel:                eventsChannel,
		prometheusInboundEventTotals: prometheusInboundEventTotals,
	}
}

func (h *eventHandlerImpl) Handle(c *gin.Context) {

	// https://developer.github.com/webhooks/
	eventType := c.GetHeader("X-GitHub-Event")
	h.prometheusInboundEventTotals.With(prometheus.Labels{"event": eventType, "source": "github"}).Inc()

	body, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Github webhook failed")
		c.String(http.StatusInternalServerError, "Reading body from Github webhook failed")
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Github webhook failed")
		c.String(http.StatusInternalServerError, "Deserializing body from Github webhook failed")
		return
	}

	log.Debug().
		Str("method", c.Request.Method).
		Str("url", c.Request.URL.String()).
		Interface("headers", c.Request.Header).
		Interface("body", b).
		Msgf("Received webhook event of type '%v' from GitHub...", eventType)

	switch eventType {
	case "push": // Any Git push to a Repository, including editing tags or branches. Commits via API actions that update references are also counted. This is the default event.

		// unmarshal json body
		var pushEvent PushEvent
		err := json.Unmarshal(body, &pushEvent)
		if err != nil {
			log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body to GithubPushEvent failed")
			return
		}

		h.HandlePushEvent(pushEvent)

	case
		"commit_comment",              // Any time a Commit is commented on.
		"create",                      // Any time a Branch or Tag is created.
		"delete",                      // Any time a Branch or Tag is deleted.
		"deployment",                  // Any time a Repository has a new deployment created from the API.
		"deployment_status",           // Any time a deployment for a Repository has a status update from the API.
		"fork",                        // Any time a Repository is forked.
		"gollum",                      // Any time a Wiki page is updated.
		"installation",                // Any time a GitHub App is installed or uninstalled.
		"installation_repositories",   // Any time a repository is added or removed from an installation.
		"issue_comment",               // Any time a comment on an issue is created, edited, or deleted.
		"issues",                      // Any time an Issue is assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened.
		"label",                       // Any time a Label is created, edited, or deleted.
		"marketplace_purchase",        // Any time a user purchases, cancels, or changes their GitHub Marketplace plan.
		"member",                      // Any time a User is added or removed as a collaborator to a Repository, or has their permissions modified.
		"membership",                  // Any time a User is added or removed from a team. Organization hooks only.
		"milestone",                   // Any time a Milestone is created, closed, opened, edited, or deleted.
		"organization",                // Any time a user is added, removed, or invited to an Organization. Organization hooks only.
		"org_block",                   // Any time an organization blocks or unblocks a user. Organization hooks only.
		"page_build",                  // Any time a Pages site is built or results in a failed build.
		"project_card",                // Any time a Project Card is created, edited, moved, converted to an issue, or deleted.
		"project_column",              // Any time a Project Column is created, edited, moved, or deleted.
		"project",                     // Any time a Project is created, edited, closed, reopened, or deleted.
		"public",                      // Any time a Repository changes from private to public.
		"pull_request_review_comment", // Any time a comment on a pull request's unified diff is created, edited, or deleted (in the Files Changed tab).
		"pull_request_review",         // Any time a pull request review is submitted, edited, or dismissed.
		"pull_request",                // Any time a pull request is assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, or synchronized (updated due to a new push in the branch that the pull request is tracking). Also any time a pull request review is requested, or a review request is removed.
		"repository",                  // Any time a Repository is created, deleted (organization hooks only), made public, or made private.
		"release",                     // Any time a Release is published in a Repository.
		"status",                      // Any time a Repository has a status update from the API
		"team",                        // Any time a team is created, deleted, modified, or added to or removed from a repository. Organization hooks only
		"team_add",                    // Any time a team is added or modified on a Repository.
		"watch",                       // Any time a User stars a Repository.
		"integration_installation_repositories": // ?
		log.Debug().Str("event", eventType).Msgf("Not implemented Github webhook event of type '%v'", eventType)

	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Github webhook event of type '%v'", eventType)
	}

	c.String(http.StatusOK, "Aye aye!")
}

func (h *eventHandlerImpl) HandlePushEvent(pushEvent PushEvent) {

	log.Debug().Interface("pushEvent", pushEvent).Msgf("Deserialized GitHub push event for repository %v", pushEvent.Repository.FullName)

	// test making api calls for github app in the background
	h.eventsChannel <- pushEvent
}
<commit_msg>fix casing for header name<commit_after>package github

import (
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/rs/zerolog/log"
)

// EventHandler handles http events for Github integration
type EventHandler interface {
	Handle(*gin.Context)
	HandlePushEvent(PushEvent)
}

type eventHandlerImpl struct {
	eventsChannel                chan PushEvent
	prometheusInboundEventTotals *prometheus.CounterVec
}

// NewGithubEventHandler returns a github.EventHandler to handle incoming webhook events
func NewGithubEventHandler(eventsChannel chan PushEvent, prometheusInboundEventTotals *prometheus.CounterVec) EventHandler {
	return &eventHandlerImpl{
		eventsChannel:                eventsChannel,
		prometheusInboundEventTotals: prometheusInboundEventTotals,
	}
}

func (h *eventHandlerImpl) Handle(c *gin.Context) {

	// https://developer.github.com/webhooks/
	eventType := c.GetHeader("X-Github-Event")
	h.prometheusInboundEventTotals.With(prometheus.Labels{"event": eventType, "source": "github"}).Inc()

	body, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Github webhook failed")
		c.String(http.StatusInternalServerError, "Reading body from Github webhook failed")
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Github webhook failed")
		c.String(http.StatusInternalServerError, "Deserializing body from Github webhook failed")
		return
	}

	log.Debug().
		Str("method", c.Request.Method).
		Str("url", c.Request.URL.String()).
		Interface("headers", c.Request.Header).
		Interface("body", b).
		Msgf("Received webhook event of type '%v' from GitHub...", eventType)

	switch eventType {
	case "push": // Any Git push to a Repository, including editing tags or branches. Commits via API actions that update references are also counted. This is the default event.

		// unmarshal json body
		var pushEvent PushEvent
		err := json.Unmarshal(body, &pushEvent)
		if err != nil {
			log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body to GithubPushEvent failed")
			return
		}

		h.HandlePushEvent(pushEvent)

	case
		"commit_comment",              // Any time a Commit is commented on.
		"create",                      // Any time a Branch or Tag is created.
		"delete",                      // Any time a Branch or Tag is deleted.
		"deployment",                  // Any time a Repository has a new deployment created from the API.
		"deployment_status",           // Any time a deployment for a Repository has a status update from the API.
		"fork",                        // Any time a Repository is forked.
		"gollum",                      // Any time a Wiki page is updated.
		"installation",                // Any time a GitHub App is installed or uninstalled.
		"installation_repositories",   // Any time a repository is added or removed from an installation.
		"issue_comment",               // Any time a comment on an issue is created, edited, or deleted.
		"issues",                      // Any time an Issue is assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened.
		"label",                       // Any time a Label is created, edited, or deleted.
		"marketplace_purchase",        // Any time a user purchases, cancels, or changes their GitHub Marketplace plan.
		"member",                      // Any time a User is added or removed as a collaborator to a Repository, or has their permissions modified.
		"membership",                  // Any time a User is added or removed from a team. Organization hooks only.
		"milestone",                   // Any time a Milestone is created, closed, opened, edited, or deleted.
		"organization",                // Any time a user is added, removed, or invited to an Organization. Organization hooks only.
		"org_block",                   // Any time an organization blocks or unblocks a user. Organization hooks only.
		"page_build",                  // Any time a Pages site is built or results in a failed build.
		"project_card",                // Any time a Project Card is created, edited, moved, converted to an issue, or deleted.
		"project_column",              // Any time a Project Column is created, edited, moved, or deleted.
		"project",                     // Any time a Project is created, edited, closed, reopened, or deleted.
		"public",                      // Any time a Repository changes from private to public.
		"pull_request_review_comment", // Any time a comment on a pull request's unified diff is created, edited, or deleted (in the Files Changed tab).
		"pull_request_review",         // Any time a pull request review is submitted, edited, or dismissed.
		"pull_request",                // Any time a pull request is assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, or synchronized (updated due to a new push in the branch that the pull request is tracking). Also any time a pull request review is requested, or a review request is removed.
		"repository",                  // Any time a Repository is created, deleted (organization hooks only), made public, or made private.
		"release",                     // Any time a Release is published in a Repository.
		"status",                      // Any time a Repository has a status update from the API
		"team",                        // Any time a team is created, deleted, modified, or added to or removed from a repository. Organization hooks only
		"team_add",                    // Any time a team is added or modified on a Repository.
		"watch",                       // Any time a User stars a Repository.
		"integration_installation_repositories": // ?
		log.Debug().Str("event", eventType).Msgf("Not implemented Github webhook event of type '%v'", eventType)

	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Github webhook event of type '%v'", eventType)
	}

	c.String(http.StatusOK, "Aye aye!")
}

func (h *eventHandlerImpl) HandlePushEvent(pushEvent PushEvent) {

	log.Debug().Interface("pushEvent", pushEvent).Msgf("Deserialized GitHub push event for repository %v", pushEvent.Repository.FullName)

	// test making api calls for github app in the background
	h.eventsChannel <- pushEvent
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/prometheus/client_golang/prometheus"
)

func init() {
	RegisterExporter("node", newExporterNode)
}

var (
	nodeLabels    = []string{"node"}
	nodeLabelKeys = []string{"name"}

	nodeGaugeVec = map[string]*prometheus.GaugeVec{
		"running":         newGaugeVec("running", "number of running nodes", nodeLabels),
		"mem_used":        newGaugeVec("node_mem_used", "Memory used in bytes", nodeLabels),
		"mem_limit":       newGaugeVec("node_mem_limit", "Point at which the memory alarm will go off", nodeLabels),
		"mem_alarm":       newGaugeVec("node_mem_alarm", "Whether the memory alarm has gone off", nodeLabels),
		"disk_free":       newGaugeVec("node_disk_free", "Disk free space in bytes.", nodeLabels),
		"disk_free_alarm": newGaugeVec("node_disk_free_alarm", "Whether the disk alarm has gone off.", nodeLabels),
		"disk_free_limit": newGaugeVec("node_disk_free_limit", "Point at which the disk alarm will go off.", nodeLabels),
		"fd_used":         newGaugeVec("fd_used", "Used File descriptors", nodeLabels),
		"fd_total":        newGaugeVec("fd_total", "File descriptors available", nodeLabels),
		"sockets_used":    newGaugeVec("sockets_used", "File descriptors used as sockets.", nodeLabels),
		"sockets_total":   newGaugeVec("sockets_total", "File descriptors available for use as sockets", nodeLabels),
		"partitions_len":  newGaugeVec("partitions", "Current Number of network partitions. 0 is ok. If the cluster is splitted the value is at least 2", nodeLabels),
	}
)

type exporterNode struct {
	nodeMetricsGauge map[string]*prometheus.GaugeVec
}

func newExporterNode() Exporter {
	return exporterNode{
		nodeMetricsGauge: nodeGaugeVec,
	}
}

func (e exporterNode) String() string {
	return "Exporter node"
}

func (e exporterNode) Collect(ch chan<- prometheus.Metric) error {
	nodeData, err := getStatsInfo(config, "nodes", nodeLabelKeys)

	if err != nil {
		return err
	}

	for _, gauge := range e.nodeMetricsGauge {
		gauge.Reset()
	}

	for key, gauge := range e.nodeMetricsGauge {
		for _, node := range nodeData {
			if value, ok := node.metrics[key]; ok {
				gauge.WithLabelValues(node.labels["name"]).Set(value)
			}
		}
	}

	for _, gauge := range e.nodeMetricsGauge {
		gauge.Collect(ch)
	}
	return nil
}

func (e exporterNode) Describe(ch chan<- *prometheus.Desc) {
	for _, nodeMetric := range e.nodeMetricsGauge {
		nodeMetric.Describe(ch)
	}

}
<commit_msg>Add uptime metric<commit_after>package main

import (
	"github.com/prometheus/client_golang/prometheus"
)

func init() {
	RegisterExporter("node", newExporterNode)
}

var (
	nodeLabels    = []string{"node"}
	nodeLabelKeys = []string{"name"}

	nodeGaugeVec = map[string]*prometheus.GaugeVec{
		"uptime":          newGaugeVec("uptime", "Uptime in milliseconds", nodeLabels),
		"running":         newGaugeVec("running", "number of running nodes", nodeLabels),
		"mem_used":        newGaugeVec("node_mem_used", "Memory used in bytes", nodeLabels),
		"mem_limit":       newGaugeVec("node_mem_limit", "Point at which the memory alarm will go off", nodeLabels),
		"mem_alarm":       newGaugeVec("node_mem_alarm", "Whether the memory alarm has gone off", nodeLabels),
		"disk_free":       newGaugeVec("node_disk_free", "Disk free space in bytes.", nodeLabels),
		"disk_free_alarm": newGaugeVec("node_disk_free_alarm", "Whether the disk alarm has gone off.", nodeLabels),
		"disk_free_limit": newGaugeVec("node_disk_free_limit", "Point at which the disk alarm will go off.", nodeLabels),
		"fd_used":         newGaugeVec("fd_used", "Used File descriptors", nodeLabels),
		"fd_total":        newGaugeVec("fd_total", "File descriptors available", nodeLabels),
		"sockets_used":    newGaugeVec("sockets_used", "File descriptors used as sockets.", nodeLabels),
		"sockets_total":   newGaugeVec("sockets_total", "File descriptors available for use as sockets", nodeLabels),
		"partitions_len":  newGaugeVec("partitions", "Current Number of network partitions. 0 is ok. If the cluster is splitted the value is at least 2", nodeLabels),
	}
)

type exporterNode struct {
	nodeMetricsGauge map[string]*prometheus.GaugeVec
}

func newExporterNode() Exporter {
	return exporterNode{
		nodeMetricsGauge: nodeGaugeVec,
	}
}

func (e exporterNode) String() string {
	return "Exporter node"
}

func (e exporterNode) Collect(ch chan<- prometheus.Metric) error {
	nodeData, err := getStatsInfo(config, "nodes", nodeLabelKeys)

	if err != nil {
		return err
	}

	for _, gauge := range e.nodeMetricsGauge {
		gauge.Reset()
	}

	for key, gauge := range e.nodeMetricsGauge {
		for _, node := range nodeData {
			if value, ok := node.metrics[key]; ok {
				gauge.WithLabelValues(node.labels["name"]).Set(value)
			}
		}
	}

	for _, gauge := range e.nodeMetricsGauge {
		gauge.Collect(ch)
	}
	return nil
}

func (e exporterNode) Describe(ch chan<- *prometheus.Desc) {
	for _, nodeMetric := range e.nodeMetricsGauge {
		nodeMetric.Describe(ch)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 common

import (
	"fmt"
	"strconv"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/watch"
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
	"k8s.io/kubernetes/pkg/client/conditions"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

var _ = framework.KubeDescribe("InitContainer [NodeConformance]", func() {
	f := framework.NewDefaultFramework("init-container")
	var podClient *framework.PodClient
	BeforeEach(func() {
		podClient = f.PodClient()
	})

	It("should invoke init containers on a RestartNever pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				RestartPolicy: v1.RestartPolicyNever,
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:    "run1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")
		wr := watch.NewRecorder(w)
		event, err := watch.Until(framework.PodStartTimeout, wr, conditions.PodCompleted)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodSucceeded))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionTrue))

		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		for _, status := range endPod.Status.InitContainerStatuses {
			Expect(status.Ready).To(BeTrue())
			Expect(status.State.Terminated).NotTo(BeNil())
			Expect(status.State.Terminated.ExitCode).To(BeZero())
		}
	})

	It("should invoke init containers on a RestartAlways pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:  "run1",
						Image: imageutils.GetPauseImageName(),
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(30*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")
		wr := watch.NewRecorder(w)
		event, err := watch.Until(framework.PodStartTimeout, wr, conditions.PodRunning)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodRunning))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionTrue))

		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		for _, status := range endPod.Status.InitContainerStatuses {
			Expect(status.Ready).To(BeTrue())
			Expect(status.State.Terminated).NotTo(BeNil())
			Expect(status.State.Terminated.ExitCode).To(BeZero())
		}
	})

	It("should not start app containers if init containers fail on a RestartAlways pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/false"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:  "run1",
						Image: imageutils.GetPauseImageName(),
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(30*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")

		wr := watch.NewRecorder(w)
		event, err := watch.Until(
			framework.PodStartTimeout, wr,
			// check for the first container to fail at least once
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					for _, status := range t.Status.ContainerStatuses {
						if status.State.Waiting == nil {
							return false, fmt.Errorf("container %q should not be out of waiting: %#v", status.Name, status)
						}
						if status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("container %q should have reason PodInitializing: %#v", status.Name, status)
						}
					}
					if len(t.Status.InitContainerStatuses) != 2 {
						return false, nil
					}
					status := t.Status.InitContainerStatuses[1]
					if status.State.Waiting == nil {
						return false, fmt.Errorf("second init container should not be out of waiting: %#v", status)
					}
					if status.State.Waiting.Reason != "PodInitializing" {
						return false, fmt.Errorf("second init container should have reason PodInitializing: %#v", status)
					}
					status = t.Status.InitContainerStatuses[0]
					if status.State.Terminated != nil && status.State.Terminated.ExitCode == 0 {
						return false, fmt.Errorf("first init container should have exitCode != 0: %#v", status)
					}
					// continue until we see an attempt to restart the pod
					return status.LastTerminationState.Terminated != nil, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
			// verify we get two restarts
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					status := t.Status.InitContainerStatuses[0]
					if status.RestartCount < 3 {
						return false, nil
					}
					framework.Logf("init container has failed twice: %#v", t)
					// TODO: more conditions
					return true, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
		)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodPending))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionFalse))
		Expect(init.Reason).To(Equal("ContainersNotInitialized"))
		Expect(init.Message).To(Equal("containers with incomplete status: [init1 init2]"))
		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
	})

	It("should not start app containers and fail the pod if init containers fail on a RestartNever pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				RestartPolicy: v1.RestartPolicyNever,
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/false"},
					},
				},
				Containers: []v1.Container{
					{
						Name:    "run1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(30*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)

		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")

		wr := watch.NewRecorder(w)
		event, err := watch.Until(
			framework.PodStartTimeout, wr,
			// check for the second container to fail at least once
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					for _, status := range t.Status.ContainerStatuses {
						if status.State.Waiting == nil {
							return false, fmt.Errorf("container %q should not be out of waiting: %#v", status.Name, status)
						}
						if status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("container %q should have reason PodInitializing: %#v", status.Name, status)
						}
					}
					if len(t.Status.InitContainerStatuses) != 2 {
						return false, nil
					}
					status := t.Status.InitContainerStatuses[0]
					if status.State.Terminated == nil {
						if status.State.Waiting != nil && status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("second init container should have reason PodInitializing: %#v", status)
						}
						return false, nil
					}
					if status.State.Terminated != nil && status.State.Terminated.ExitCode != 0 {
						return false, fmt.Errorf("first init container should have exitCode != 0: %#v", status)
					}
					status = t.Status.InitContainerStatuses[1]
					if status.State.Terminated == nil {
						return false, nil
					}
					if status.State.Terminated.ExitCode == 0 {
						return false, fmt.Errorf("second init container should have failed: %#v", status)
					}
					return true, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
			conditions.PodCompleted,
		)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)

		Expect(endPod.Status.Phase).To(Equal(v1.PodFailed))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionFalse))
		Expect(init.Reason).To(Equal("ContainersNotInitialized"))
		Expect(init.Message).To(Equal("containers with incomplete status: [init2]"))
		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		Expect(endPod.Status.ContainerStatuses[0].State.Waiting).ToNot(BeNil())
	})
})
<commit_msg>Sets higher memory limit for init_container tests<commit_after>/*
Copyright 2016 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 common

import (
	"fmt"
	"strconv"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/watch"
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
	"k8s.io/kubernetes/pkg/client/conditions"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

var _ = framework.KubeDescribe("InitContainer [NodeConformance]", func() {
	f := framework.NewDefaultFramework("init-container")
	var podClient *framework.PodClient
	BeforeEach(func() {
		podClient = f.PodClient()
	})

	It("should invoke init containers on a RestartNever pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				RestartPolicy: v1.RestartPolicyNever,
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:    "run1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")
		wr := watch.NewRecorder(w)
		event, err := watch.Until(framework.PodStartTimeout, wr, conditions.PodCompleted)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodSucceeded))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionTrue))

		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		for _, status := range endPod.Status.InitContainerStatuses {
			Expect(status.Ready).To(BeTrue())
			Expect(status.State.Terminated).NotTo(BeNil())
			Expect(status.State.Terminated.ExitCode).To(BeZero())
		}
	})

	It("should invoke init containers on a RestartAlways pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:  "run1",
						Image: imageutils.GetPauseImageName(),
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(50*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")
		wr := watch.NewRecorder(w)
		event, err := watch.Until(framework.PodStartTimeout, wr, conditions.PodRunning)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodRunning))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionTrue))

		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		for _, status := range endPod.Status.InitContainerStatuses {
			Expect(status.Ready).To(BeTrue())
			Expect(status.State.Terminated).NotTo(BeNil())
			Expect(status.State.Terminated.ExitCode).To(BeZero())
		}
	})

	It("should not start app containers if init containers fail on a RestartAlways pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())

		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/false"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
				},
				Containers: []v1.Container{
					{
						Name:  "run1",
						Image: imageutils.GetPauseImageName(),
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(50*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)
		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")

		wr := watch.NewRecorder(w)
		event, err := watch.Until(
			framework.PodStartTimeout, wr,
			// check for the first container to fail at least once
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					for _, status := range t.Status.ContainerStatuses {
						if status.State.Waiting == nil {
							return false, fmt.Errorf("container %q should not be out of waiting: %#v", status.Name, status)
						}
						if status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("container %q should have reason PodInitializing: %#v", status.Name, status)
						}
					}
					if len(t.Status.InitContainerStatuses) != 2 {
						return false, nil
					}
					status := t.Status.InitContainerStatuses[1]
					if status.State.Waiting == nil {
						return false, fmt.Errorf("second init container should not be out of waiting: %#v", status)
					}
					if status.State.Waiting.Reason != "PodInitializing" {
						return false, fmt.Errorf("second init container should have reason PodInitializing: %#v", status)
					}
					status = t.Status.InitContainerStatuses[0]
					if status.State.Terminated != nil && status.State.Terminated.ExitCode == 0 {
						return false, fmt.Errorf("first init container should have exitCode != 0: %#v", status)
					}
					// continue until we see an attempt to restart the pod
					return status.LastTerminationState.Terminated != nil, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
			// verify we get two restarts
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					status := t.Status.InitContainerStatuses[0]
					if status.RestartCount < 3 {
						return false, nil
					}
					framework.Logf("init container has failed twice: %#v", t)
					// TODO: more conditions
					return true, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
		)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)
		Expect(endPod.Status.Phase).To(Equal(v1.PodPending))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionFalse))
		Expect(init.Reason).To(Equal("ContainersNotInitialized"))
		Expect(init.Message).To(Equal("containers with incomplete status: [init1 init2]"))
		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
	})

	It("should not start app containers and fail the pod if init containers fail on a RestartNever pod", func() {
		By("creating the pod")
		name := "pod-init-" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		pod := &v1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
				Labels: map[string]string{
					"name": "foo",
					"time": value,
				},
			},
			Spec: v1.PodSpec{
				RestartPolicy: v1.RestartPolicyNever,
				InitContainers: []v1.Container{
					{
						Name:    "init1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
					},
					{
						Name:    "init2",
						Image:   busyboxImage,
						Command: []string{"/bin/false"},
					},
				},
				Containers: []v1.Container{
					{
						Name:    "run1",
						Image:   busyboxImage,
						Command: []string{"/bin/true"},
						Resources: v1.ResourceRequirements{
							Limits: v1.ResourceList{
								v1.ResourceCPU:    *resource.NewMilliQuantity(100, resource.DecimalSI),
								v1.ResourceMemory: *resource.NewQuantity(50*1024*1024, resource.DecimalSI),
							},
						},
					},
				},
			},
		}
		framework.Logf("PodSpec: initContainers in spec.initContainers")
		startedPod := podClient.Create(pod)

		w, err := podClient.Watch(metav1.SingleObject(startedPod.ObjectMeta))
		Expect(err).NotTo(HaveOccurred(), "error watching a pod")

		wr := watch.NewRecorder(w)
		event, err := watch.Until(
			framework.PodStartTimeout, wr,
			// check for the second container to fail at least once
			func(evt watch.Event) (bool, error) {
				switch t := evt.Object.(type) {
				case *v1.Pod:
					for _, status := range t.Status.ContainerStatuses {
						if status.State.Waiting == nil {
							return false, fmt.Errorf("container %q should not be out of waiting: %#v", status.Name, status)
						}
						if status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("container %q should have reason PodInitializing: %#v", status.Name, status)
						}
					}
					if len(t.Status.InitContainerStatuses) != 2 {
						return false, nil
					}
					status := t.Status.InitContainerStatuses[0]
					if status.State.Terminated == nil {
						if status.State.Waiting != nil && status.State.Waiting.Reason != "PodInitializing" {
							return false, fmt.Errorf("second init container should have reason PodInitializing: %#v", status)
						}
						return false, nil
					}
					if status.State.Terminated != nil && status.State.Terminated.ExitCode != 0 {
						return false, fmt.Errorf("first init container should have exitCode != 0: %#v", status)
					}
					status = t.Status.InitContainerStatuses[1]
					if status.State.Terminated == nil {
						return false, nil
					}
					if status.State.Terminated.ExitCode == 0 {
						return false, fmt.Errorf("second init container should have failed: %#v", status)
					}
					return true, nil
				default:
					return false, fmt.Errorf("unexpected object: %#v", t)
				}
			},
			conditions.PodCompleted,
		)
		Expect(err).To(BeNil())
		framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant)
		endPod := event.Object.(*v1.Pod)

		Expect(endPod.Status.Phase).To(Equal(v1.PodFailed))
		_, init := podutil.GetPodCondition(&endPod.Status, v1.PodInitialized)
		Expect(init).NotTo(BeNil())
		Expect(init.Status).To(Equal(v1.ConditionFalse))
		Expect(init.Reason).To(Equal("ContainersNotInitialized"))
		Expect(init.Message).To(Equal("containers with incomplete status: [init2]"))
		Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2))
		Expect(endPod.Status.ContainerStatuses[0].State.Waiting).ToNot(BeNil())
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"k8s.io/apimachinery/pkg/util/wait"

	"github.com/pkg/errors"

	"k8s.io/minikube/pkg/kapi"
	"k8s.io/minikube/pkg/minikube/tunnel"
	"k8s.io/minikube/pkg/util/retry"
)

func validateTunnelCmd(ctx context.Context, t *testing.T, profile string) {
	ctx, cancel := context.WithTimeout(ctx, Minutes(20))
	defer cancel()

	if runtime.GOOS != "windows" {
		// Otherwise minikube fails waiting for a password.
		if err := exec.Command("sudo", "-n", "route").Run(); err != nil {
			t.Skipf("password required to execute 'route', skipping testTunnel: %v", err)
		}
	}

	client, err := kapi.Client(profile)
	if err != nil {
		t.Fatalf("client: %v", err)
	}

	// Pre-Cleanup
	if err := tunnel.NewManager().CleanupNotRunningTunnels(); err != nil {
		t.Errorf("CleanupNotRunningTunnels: %v", err)
	}

	// Start the tunnel
	args := []string{"-p", profile, "tunnel", "--alsologtostderr", "-v=1"}
	ss, err := Start(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("%s failed: %v", args, err)
	}
	defer ss.Stop(t)

	// Start the "nginx" pod.
	rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "apply", "-f", filepath.Join(*testdataDir, "testsvc.yaml")))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Args, err)
	}
	if _, err := PodWait(ctx, t, profile, "default", "run=nginx-svc", Minutes(4)); err != nil {
		t.Fatalf("wait: %v", err)
	}

	if err := kapi.WaitForService(client, "default", "nginx-svc", true, 1*time.Second, Minutes(2)); err != nil {
		t.Fatal(errors.Wrap(err, "Error waiting for nginx service to be up"))
	}

	// Wait until the nginx-svc has a loadbalancer ingress IP
	nginxIP := ""
	err = wait.PollImmediate(1*time.Second, Minutes(3), func() (bool, error) {
		rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "get", "svc", "nginx-svc", "-o", "jsonpath={.status.loadBalancer.ingress[0].ip}"))
		if err != nil {
			return false, err
		}
		if len(rr.Stdout.String()) > 0 {
			nginxIP = rr.Stdout.String()
			return true, nil
		}
		return false, nil
	})
	if err != nil {
		t.Errorf("nginx-svc svc.status.loadBalancer.ingress never got an IP")

		rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "get", "svc", "nginx-svc"))
		if err != nil {
			t.Errorf("%s failed: %v", rr.Args, err)
		}
		t.Logf("kubectl get svc nginx-svc:\n%s", rr.Stdout)
	}

	got := []byte{}
	fetch := func() error {
		h := &http.Client{Timeout: time.Second * 10}
		resp, err := h.Get(fmt.Sprintf("http://%s", nginxIP))
		if err != nil {
			return &retry.RetriableError{Err: err}
		}
		if resp.Body == nil {
			return &retry.RetriableError{Err: fmt.Errorf("no body")}
		}
		defer resp.Body.Close()
		got, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return &retry.RetriableError{Err: err}
		}
		return nil
	}
	if err = retry.Expo(fetch, time.Millisecond*500, Minutes(2), 13); err != nil {
		t.Errorf("failed to contact nginx at %s: %v", nginxIP, err)
	}

	want := "Welcome to nginx!"
	if !strings.Contains(string(got), want) {
		t.Errorf("body = %q, want *%s*", got, want)
	}
}
<commit_msg>improve logs for fn_tunnel_cmd<commit_after>/*
Copyright 2018 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"k8s.io/apimachinery/pkg/util/wait"

	"github.com/pkg/errors"

	"k8s.io/minikube/pkg/kapi"
	"k8s.io/minikube/pkg/minikube/tunnel"
	"k8s.io/minikube/pkg/util/retry"
)

func validateTunnelCmd(ctx context.Context, t *testing.T, profile string) {
	ctx, cancel := context.WithTimeout(ctx, Minutes(20))
	defer cancel()

	if runtime.GOOS != "windows" {
		// Otherwise minikube fails waiting for a password.
		if err := exec.Command("sudo", "-n", "route").Run(); err != nil {
			t.Skipf("password required to execute 'route', skipping testTunnel: %v", err)
		}
	}

	client, err := kapi.Client(profile)
	if err != nil {
		t.Fatalf("failed to get kubernetes client for %q: %v", profile, err)
	}

	// Pre-Cleanup
	if err := tunnel.NewManager().CleanupNotRunningTunnels(); err != nil {
		t.Errorf("CleanupNotRunningTunnels: %v", err)
	}

	// Start the tunnel
	args := []string{"-p", profile, "tunnel", "--alsologtostderr", "-v=1"}
	ss, err := Start(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to start a tunnel: args %q: %v", args, err)
	}
	defer ss.Stop(t)

	// Start the "nginx" pod.
	rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "apply", "-f", filepath.Join(*testdataDir, "testsvc.yaml")))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Args, err)
	}
	if _, err := PodWait(ctx, t, profile, "default", "run=nginx-svc", Minutes(4)); err != nil {
		t.Fatalf("wait: %v", err)
	}

	if err := kapi.WaitForService(client, "default", "nginx-svc", true, 1*time.Second, Minutes(2)); err != nil {
		t.Fatal(errors.Wrap(err, "Error waiting for nginx service to be up"))
	}

	// Wait until the nginx-svc has a loadbalancer ingress IP
	nginxIP := ""
	err = wait.PollImmediate(1*time.Second, Minutes(3), func() (bool, error) {
		rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "get", "svc", "nginx-svc", "-o", "jsonpath={.status.loadBalancer.ingress[0].ip}"))
		if err != nil {
			return false, err
		}
		if len(rr.Stdout.String()) > 0 {
			nginxIP = rr.Stdout.String()
			return true, nil
		}
		return false, nil
	})
	if err != nil {
		t.Errorf("nginx-svc svc.status.loadBalancer.ingress never got an IP")

		rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "get", "svc", "nginx-svc"))
		if err != nil {
			t.Errorf("%s failed: %v", rr.Args, err)
		}
		t.Logf("failed to kubectl get svc nginx-svc:\n%s", rr.Stdout)
	}

	got := []byte{}
	fetch := func() error {
		h := &http.Client{Timeout: time.Second * 10}
		resp, err := h.Get(fmt.Sprintf("http://%s", nginxIP))
		if err != nil {
			return &retry.RetriableError{Err: err}
		}
		if resp.Body == nil {
			return &retry.RetriableError{Err: fmt.Errorf("no body")}
		}
		defer resp.Body.Close()
		got, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return &retry.RetriableError{Err: err}
		}
		return nil
	}
	if err = retry.Expo(fetch, time.Millisecond*500, Minutes(2), 13); err != nil {
		t.Errorf("failed to hit nginx at %q: %v", nginxIP, err)
	}

	want := "Welcome to nginx!"
	if !strings.Contains(string(got), want) {
		t.Errorf("expected body to contain %q, but got *%q*", want, got)
	}
}
<|endoftext|>


<commit_before>package rabbitmq

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/compose/transporter/client"

	"github.com/streadway/amqp"
)

const (
	// DefaultURI is the default endpoint of RabbitMQ on the local machine.
	// Primarily used when initializing a new Client without a specific URI.
	DefaultURI = "amqp://guest:guest@localhost:5672/"
)

var (
	_ client.Client = &Client{}
)

// ClientOptionFunc is a function that configures a Client.
// It is used in NewClient.
type ClientOptionFunc func(*Client) error

// Client wraps the underlying connection to a RabbitMQ cluster.
type Client struct {
	uri       string
	tlsConfig *tls.Config
	conn      *amqp.Connection
}

// NewClient creates a new client to work with RabbitMQ.
//
// The caller can configure the new client by passing configuration options
// to the func.
//
// Example:
//
//   client, err := NewClient(
//     WithURI("mongodb://localhost:27017"))
//
// If no URI is configured, it uses DefaultURI.
//
// An error is also returned when a configuration option is invalid
func NewClient(options ...ClientOptionFunc) (*Client, error) {
	// Set up the client
	c := &Client{
		uri:       DefaultURI,
		tlsConfig: nil,
	}

	// Run the options on it
	for _, option := range options {
		if err := option(c); err != nil {
			return nil, err
		}
	}
	return c, nil
}

// WithURI defines the full connection string for the RabbitMQ connection
func WithURI(uri string) ClientOptionFunc {
	return func(c *Client) error {
		if _, err := amqp.ParseURI(uri); err != nil {
			return client.InvalidURIError{URI: uri, Err: err.Error()}
		}
		c.uri = uri
		return nil
	}
}

// WithSSL configures the database connection to connect via TLS.
func WithSSL(ssl bool) ClientOptionFunc {
	return func(c *Client) error {
		if ssl {
			tlsConfig := &tls.Config{InsecureSkipVerify: true}
			tlsConfig.RootCAs = x509.NewCertPool()
			c.tlsConfig = tlsConfig
		}
		return nil
	}
}

// WithCACerts configures the RootCAs for the underlying TLS connection
func WithCACerts(certs []string) ClientOptionFunc {
	return func(c *Client) error {
		if len(certs) > 0 {
			roots := x509.NewCertPool()
			for _, cert := range certs {
				if _, err := os.Stat(cert); err == nil {
					filepath.Abs(cert)
					c, err := ioutil.ReadFile(cert)
					if err != nil {
						return err
					}
					cert = string(c)
				}
				if ok := roots.AppendCertsFromPEM([]byte(cert)); !ok {
					return client.ErrInvalidCert
				}
			}
			if c.tlsConfig != nil {
				c.tlsConfig.RootCAs = roots
			} else {
				c.tlsConfig = &tls.Config{RootCAs: roots}
			}
			c.tlsConfig.InsecureSkipVerify = false
		}
		return nil
	}
}

// Connect satisfies the client.Client interface.
func (c *Client) Connect() (client.Session, error) {
	if c.conn == nil {
		if err := c.initConnection(); err != nil {
			return nil, err
		}
	}
	ch, err := c.conn.Channel()
	return &Session{c.conn, ch}, err
}

func (c *Client) initConnection() error {
	if c.tlsConfig != nil {
		conn, err := amqp.DialTLS(c.uri, c.tlsConfig)
		if err != nil {
			return client.ConnectError{Reason: err.Error()}
		}
		c.conn = conn
		return nil
	}
	conn, err := amqp.Dial(c.uri)
	if err != nil {
		return client.ConnectError{Reason: err.Error()}
	}
	c.conn = conn
	return nil
}

// Close implements necessary calls to cleanup the underlying connection.
func (c *Client) Close() {
	c.conn.Close()
}
<commit_msg>cache rabbitmq channel in client (#437)<commit_after>package rabbitmq

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/compose/transporter/client"

	"github.com/streadway/amqp"
)

const (
	// DefaultURI is the default endpoint of RabbitMQ on the local machine.
	// Primarily used when initializing a new Client without a specific URI.
	DefaultURI = "amqp://guest:guest@localhost:5672/"
)

var (
	_ client.Client = &Client{}
)

// ClientOptionFunc is a function that configures a Client.
// It is used in NewClient.
type ClientOptionFunc func(*Client) error

// Client wraps the underlying connection to a RabbitMQ cluster.
type Client struct {
	uri       string
	tlsConfig *tls.Config
	conn      *amqp.Connection
	ch        *amqp.Channel
}

// NewClient creates a new client to work with RabbitMQ.
//
// The caller can configure the new client by passing configuration options
// to the func.
//
// Example:
//
//   client, err := NewClient(
//     WithURI("mongodb://localhost:27017"))
//
// If no URI is configured, it uses DefaultURI.
//
// An error is also returned when a configuration option is invalid
func NewClient(options ...ClientOptionFunc) (*Client, error) {
	// Set up the client
	c := &Client{
		uri:       DefaultURI,
		tlsConfig: nil,
	}

	// Run the options on it
	for _, option := range options {
		if err := option(c); err != nil {
			return nil, err
		}
	}
	return c, nil
}

// WithURI defines the full connection string for the RabbitMQ connection
func WithURI(uri string) ClientOptionFunc {
	return func(c *Client) error {
		if _, err := amqp.ParseURI(uri); err != nil {
			return client.InvalidURIError{URI: uri, Err: err.Error()}
		}
		c.uri = uri
		return nil
	}
}

// WithSSL configures the database connection to connect via TLS.
func WithSSL(ssl bool) ClientOptionFunc {
	return func(c *Client) error {
		if ssl {
			tlsConfig := &tls.Config{InsecureSkipVerify: true}
			tlsConfig.RootCAs = x509.NewCertPool()
			c.tlsConfig = tlsConfig
		}
		return nil
	}
}

// WithCACerts configures the RootCAs for the underlying TLS connection
func WithCACerts(certs []string) ClientOptionFunc {
	return func(c *Client) error {
		if len(certs) > 0 {
			roots := x509.NewCertPool()
			for _, cert := range certs {
				if _, err := os.Stat(cert); err == nil {
					filepath.Abs(cert)
					c, err := ioutil.ReadFile(cert)
					if err != nil {
						return err
					}
					cert = string(c)
				}
				if ok := roots.AppendCertsFromPEM([]byte(cert)); !ok {
					return client.ErrInvalidCert
				}
			}
			if c.tlsConfig != nil {
				c.tlsConfig.RootCAs = roots
			} else {
				c.tlsConfig = &tls.Config{RootCAs: roots}
			}
			c.tlsConfig.InsecureSkipVerify = false
		}
		return nil
	}
}

// Connect satisfies the client.Client interface.
func (c *Client) Connect() (client.Session, error) {
	if c.conn == nil {
		if err := c.initConnection(); err != nil {
			return nil, err
		}
	}
	return &Session{c.conn, c.ch}, nil
}

func (c *Client) initConnection() error {
	if c.tlsConfig != nil {
		conn, err := amqp.DialTLS(c.uri, c.tlsConfig)
		if err != nil {
			return client.ConnectError{Reason: err.Error()}
		}
		c.conn = conn
		return nil
	}
	conn, err := amqp.Dial(c.uri)
	if err != nil {
		return client.ConnectError{Reason: err.Error()}
	}
	if c.ch, err = conn.Channel(); err != nil {
		return client.ConnectError{Reason: err.Error()}
	}
	c.conn = conn
	return nil
}

// Close implements necessary calls to cleanup the underlying connection.
func (c *Client) Close() {
	c.conn.Close()
}
<|endoftext|>