<commit_before>package transmit

import (
	"bufio"
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"hash/adler32"
	"io"
	"net"
	"sync"
	"sync/atomic"

	"github.com/midbel/uuid"
)

var ErrClosed = errors.New("closed")

var (
	ErrCorrupted = errors.New("packet corrupted")
	ErrUnknownId = errors.New("unknown packet id")
)

const (
	Size    = 22
	Padding = 512
)

const (
	Bind uint16 = iota
	Accept
	Reject
	Copy
	Abort
	Done
)

type Route struct {
	Id   string `json:"id"`
	Addr string `json:"addr"`
	Eth  string `json:"ifi"`
}

func Subscribe(a, n string) (net.Conn, error) {
	addr, err := net.ResolveUDPAddr("udp", a)
	if err != nil {
		return nil, err
	}
	i, err := net.InterfaceByName(n)
	if err != nil && len(n) > 0 {
		return nil, err
	}
	c, err := net.ListenMulticastUDP("udp", i, addr)
	if err != nil {
		return nil, err
	}
	return &subscriber{c}, nil
}

func Dispatch(a string) (net.Conn, error) {
	c, err := net.Dial("udp", a)
	if err != nil {
		return nil, err
	}
	return &subscriber{c}, nil
}

func Forward(a, s string) (net.Conn, error) {
	c, err := net.Dial("tcp", a)
	if err != nil {
		return nil, err
	}
	id, _ := uuid.UUID5(uuid.URL, []byte(s))

	f := &forwarder{
		Conn:   c,
		id:     id.Bytes(),
		reader: bufio.NewReaderSize(rand.Reader, 4096),
	}
	if _, err := f.Write([]byte{}); err != nil {
		f.Close()
		return nil, err
	}
	return f, nil
}

type Router struct {
	net.Listener

	routes map[string]*pool
}

func (r *Router) Accept() (net.Conn, net.Conn, error) {
	c, err := r.Listener.Accept()
	if err != nil {
		return nil, nil, err
	}
	id := make([]byte, Size)
	if _, err := io.ReadFull(c, id); err != nil {
		c.Close()
		return nil, nil, err
	}
	p, ok := r.routes[string(id[:uuid.Size])]
	if !ok {
		c.Close()
		return nil, nil, ErrUnknownId
	}
	w, err := p.Acquire()
	if err != nil {
		return nil, nil, err
	}
	return &forwarder{Conn: c, id: id[:uuid.Size]}, w, nil
}

func (r *Router) Close() error {
	err := r.Listener.Close()
	for _, p := range r.routes {
		if e := p.Close(); err == nil && e != nil {
			err = e
		}
	}
	return err
}

func NewRouter(a string, rs []Route) (*Router, error) {
	l, err := net.Listen("tcp", a)
	if err != nil {
		return nil, err
	}
	gs := make(map[string]*pool)
	for _, r := range rs {
		id, _ := uuid.UUID5(uuid.URL, []byte(r.Id))
		p := &pool{
			c: make(chan net.Conn, 5),
			a: r.Addr,
		}
		gs[string(id.Bytes())] = p
	}
	return &Router{Listener: l, routes: gs}, nil
}

type subscriber struct {
	net.Conn
}

func (s *subscriber) Read(b []byte) (int, error) {
	d := make([]byte, len(b))
	r, err := s.Conn.Read(d)
	if err != nil && r == 0 {
		return r, err
	}
	sum := make([]byte, 4)
	binary.BigEndian.PutUint32(sum, adler32.Checksum(d[:r]))

	return copy(b, append(d[:r], sum...)), err
}

func (s *subscriber) Write(b []byte) (int, error) {
	if len(b) <= Size {
		return len(b), nil
	}
	d, sum := b[Size:len(b)-adler32.Size], b[len(b)-adler32.Size:]
	if a := adler32.Checksum(d); a != binary.BigEndian.Uint32(sum) {
		return 0, ErrCorrupted
	}
	_, err := s.Conn.Write(d)
	return len(b), err
}

type forwarder struct {
	net.Conn

	id []byte

	sequence uint32
	padding  uint16

	reader io.Reader
}

func (f *forwarder) Read(b []byte) (int, error) {
	d := make([]byte, len(b))
	r, err := f.Conn.Read(d)
	if err != nil && r == 0 {
		return r, err
	}
	if !bytes.Equal(d[:uuid.Size], f.id) {
		return 0, ErrUnknownId
	}
	s := binary.BigEndian.Uint16(b[16:18])
	return copy(d, b[:Size+s]), err
}

func (f *forwarder) Write(b []byte) (int, error) {
	buf := new(bytes.Buffer)

	buf.Write(f.id)
	binary.Write(buf, binary.BigEndian, uint16(len(b)))
	binary.Write(buf, binary.BigEndian, atomic.AddUint32(&f.sequence, 1))
	buf.Write(b)

	if buf.Len() < int(f.padding) {
		io.CopyN(buf, f.reader, int64(f.padding))
	}

	_, err := io.Copy(f.Conn, buf)
	return len(b), err
}

type pool struct {
	a string
	c chan net.Conn

	closed bool
	mu     sync.Mutex
}

func (p *pool) Acquire() (net.Conn, error) {
	select {
	case c, ok := <-p.c:
		if !ok {
			return nil, ErrClosed
		}
		return c, nil
	default:
		return Dispatch(p.a)
	}
}

func (p *pool) Release(c net.Conn) error {
	if p.closed {
		return ErrClosed
	}
	select {
	case p.c <- c:
		return nil
	default:
		return c.Close()
	}
}

func (p *pool) Close() error {
	p.mu.Lock()
	defer p.mu.Unlock()
	if p.closed {
		return ErrClosed
	}
	var err error
	for c := range p.c {
		if e := c.Close(); err == nil && e != nil {
			err = e
		}
	}
	close(p.c)
	return err
}
<commit_msg>fix return value of Read/Write<commit_after>package transmit

import (
	"bufio"
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"hash/adler32"
	"io"
	"net"
	"sync"
	"sync/atomic"

	"github.com/midbel/uuid"
)

var ErrClosed = errors.New("closed")

var (
	ErrCorrupted = errors.New("packet corrupted")
	ErrUnknownId = errors.New("unknown packet id")
)

const (
	Size    = 22
	Padding = 512
)

const (
	Bind uint16 = iota
	Accept
	Reject
	Copy
	Abort
	Done
)

type Route struct {
	Id   string `json:"id"`
	Addr string `json:"addr"`
	Eth  string `json:"ifi"`
}

func Subscribe(a, n string) (net.Conn, error) {
	addr, err := net.ResolveUDPAddr("udp", a)
	if err != nil {
		return nil, err
	}
	i, err := net.InterfaceByName(n)
	if err != nil && len(n) > 0 {
		return nil, err
	}
	c, err := net.ListenMulticastUDP("udp", i, addr)
	if err != nil {
		return nil, err
	}
	return &subscriber{c}, nil
}

func Dispatch(a string) (net.Conn, error) {
	c, err := net.Dial("udp", a)
	if err != nil {
		return nil, err
	}
	return &subscriber{c}, nil
}

func Forward(a, s string) (net.Conn, error) {
	return newForwarder(a, s)
}

func Proxy(a, s string) (net.Conn, error) {
	f, err := newForwarder(a, s)
	if err != nil {
		return nil, err
	}
	f.id = nil
	return f, err
}

func newForwarder(a, s string) (*forwarder, error) {
	c, err := net.Dial("tcp", a)
	if err != nil {
		return nil, err
	}
	id, _ := uuid.UUID5(uuid.URL, []byte(s))

	f := &forwarder{
		Conn:   c,
		id:     id.Bytes(),
		padding: Padding,
		reader: bufio.NewReaderSize(rand.Reader, 4096),
	}
	if _, err := f.Write([]byte{}); err != nil {
		f.Close()
		return nil, err
	}
	return f, nil
}

type Router struct {
	net.Listener

	routes map[string]*pool
}

func (r *Router) Accept() (net.Conn, net.Conn, error) {
	c, err := r.Listener.Accept()
	if err != nil {
		return nil, nil, err
	}
	id := make([]byte, Size)
	if _, err := io.ReadFull(c, id); err != nil {
		c.Close()
		return nil, nil, err
	} else {
		id = id[:uuid.Size]
	}
	p, ok := r.routes[string(id)]
	if !ok {
		c.Close()
		return nil, nil, ErrUnknownId
	}
	w, err := p.Acquire()
	if err != nil {
		return nil, nil, err
	}
	return &forwarder{Conn: c, id: id}, w, nil
}

func (r *Router) Close() error {
	err := r.Listener.Close()
	for _, p := range r.routes {
		if e := p.Close(); err == nil && e != nil {
			err = e
		}
	}
	return err
}

func NewRouter(a string, rs []Route) (*Router, error) {
	l, err := net.Listen("tcp", a)
	if err != nil {
		return nil, err
	}
	gs := make(map[string]*pool)
	for _, r := range rs {
		id, _ := uuid.UUID5(uuid.URL, []byte(r.Id))
		p := &pool{
			c: make(chan net.Conn, 5),
			a: r.Addr,
		}
		gs[string(id.Bytes())] = p
	}
	return &Router{Listener: l, routes: gs}, nil
}

type subscriber struct {
	net.Conn
}

func (s *subscriber) Read(b []byte) (int, error) {
	d := make([]byte, len(b))
	r, err := s.Conn.Read(d)
	if err != nil && r == 0 {
		return r, err
	} else {
		d = d[:r]
	}
	sum := make([]byte, 4)
	binary.BigEndian.PutUint32(sum, adler32.Checksum(d))
	d = append(d, sum...)

	return copy(b, d), err
}

func (s *subscriber) Write(b []byte) (int, error) {
	d, sum := b[Size:len(b)-adler32.Size], b[len(b)-adler32.Size:]
	if a := adler32.Checksum(d); a != binary.BigEndian.Uint32(sum) {
		return len(b), ErrCorrupted
	}
	_, err := s.Conn.Write(d)
	return len(b), err
}

type forwarder struct {
	net.Conn

	id []byte

	sequence uint32
	padding  uint16

	reader io.Reader
}

func (f *forwarder) Read(b []byte) (int, error) {
	d := make([]byte, len(b))
	r, err := f.Conn.Read(d)
	if err != nil && r == 0 {
		return r, err
	} else {
		d = d[:r]
	}
	if !bytes.Equal(d[:uuid.Size], f.id) {
		return r, ErrUnknownId
	}
	s := binary.BigEndian.Uint16(d[16:18])
	return copy(b, d[:Size+s]), err
}

func (f *forwarder) Write(b []byte) (int, error) {
	buf := new(bytes.Buffer)

	if len(f.id) > 0 {
		buf.Write(f.id)
		binary.Write(buf, binary.BigEndian, uint16(len(b)))
		binary.Write(buf, binary.BigEndian, atomic.AddUint32(&f.sequence, 1))
	}
	buf.Write(b)

	if buf.Len() < int(f.padding) {
		io.CopyN(buf, f.reader, int64(f.padding))
	}

	_, err := io.Copy(f.Conn, buf)
	return len(b), err
}

type pool struct {
	a string
	c chan net.Conn

	closed bool
	mu     sync.Mutex
}

func (p *pool) Acquire() (net.Conn, error) {
	select {
	case c, ok := <-p.c:
		if !ok {
			return nil, ErrClosed
		}
		return c, nil
	default:
		return Dispatch(p.a)
	}
}

func (p *pool) Release(c net.Conn) error {
	if p.closed {
		return ErrClosed
	}
	select {
	case p.c <- c:
		return nil
	default:
		return c.Close()
	}
}

func (p *pool) Close() error {
	p.mu.Lock()
	defer p.mu.Unlock()
	if p.closed {
		return ErrClosed
	}
	var err error
	for c := range p.c {
		if e := c.Close(); err == nil && e != nil {
			err = e
		}
	}
	close(p.c)
	return err
}
<|endoftext|>


<commit_before>//
//  trayicon.go
//
//  Created by Martino Facchin
//  Copyright (c) 2015 Arduino LLC
//
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//

// +build !arm

package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/facchinm/go-serial"
	"github.com/facchinm/systray"
	"github.com/facchinm/systray/example/icon"
	"github.com/skratchdot/open-golang/open"
	"runtime"
)

func setupSysTray() {
	runtime.LockOSThread()
	if *hibernate == true {
		systray.Run(setupSysTrayHibernate)
	} else {
		systray.Run(setupSysTrayReal)
	}
}

func addRebootTrayElement() {
	reboot_tray := systray.AddMenuItem("Reboot to update", "")

	go func() {
		<-reboot_tray.ClickedCh
		systray.Quit()
		log.Println("Restarting now...")
		restart("")
	}()
}

func setupSysTrayReal() {

	systray.SetIcon(icon.Data)
	mUrl := systray.AddMenuItem("Go to Arduino Create (staging)", "Arduino Create")
	mDebug := systray.AddMenuItem("Open debug console", "Debug console")
	menuVer := systray.AddMenuItem("Agent version "+version+"-"+git_revision, "")
	mPause := systray.AddMenuItem("Quit Plugin", "")
	//mQuit := systray.AddMenuItem("Quit Plugin", "")

	menuVer.Disable()

	go func() {
		<-mPause.ClickedCh
		ports, _ := serial.GetPortsList()
		for _, element := range ports {
			spClose(element)
		}
		systray.Quit()
		*hibernate = true
		restart("")
	}()

	// go func() {
	// 	<-mQuit.ClickedCh
	// 	systray.Quit()
	// 	exit()
	// }()

	go func() {
		<-mDebug.ClickedCh
		open.Run("http://localhost:8989")
		logAction("log on")
	}()

	// We can manipulate the systray in other goroutines
	go func() {
		<-mUrl.ClickedCh
		open.Run("http://create-staging.arduino.cc")
	}()
}

func setupSysTrayHibernate() {

	systray.SetIcon(icon.DataHibernate)
	mOpen := systray.AddMenuItem("Open Plugin", "")
	mQuit := systray.AddMenuItem("Kill Plugin", "")

	go func() {
		<-mOpen.ClickedCh
		*hibernate = false
		restart("")
	}()

	go func() {
		<-mQuit.ClickedCh
		systray.Quit()
		exit()
	}()
}
<commit_msg>solve tray buttons only clickable once<commit_after>//
//  trayicon.go
//
//  Created by Martino Facchin
//  Copyright (c) 2015 Arduino LLC
//
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//

// +build !arm

package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/facchinm/go-serial"
	"github.com/facchinm/systray"
	"github.com/facchinm/systray/example/icon"
	"github.com/skratchdot/open-golang/open"
	"runtime"
)

func setupSysTray() {
	runtime.LockOSThread()
	if *hibernate == true {
		systray.Run(setupSysTrayHibernate)
	} else {
		systray.Run(setupSysTrayReal)
	}
}

func addRebootTrayElement() {
	reboot_tray := systray.AddMenuItem("Reboot to update", "")

	go func() {
		<-reboot_tray.ClickedCh
		systray.Quit()
		log.Println("Restarting now...")
		restart("")
	}()
}

func setupSysTrayReal() {

	systray.SetIcon(icon.Data)
	mUrl := systray.AddMenuItem("Go to Arduino Create (staging)", "Arduino Create")
	mDebug := systray.AddMenuItem("Open debug console", "Debug console")
	menuVer := systray.AddMenuItem("Agent version "+version+"-"+git_revision, "")
	mPause := systray.AddMenuItem("Quit Plugin", "")
	//mQuit := systray.AddMenuItem("Quit Plugin", "")

	menuVer.Disable()

	go func() {
		<-mPause.ClickedCh
		ports, _ := serial.GetPortsList()
		for _, element := range ports {
			spClose(element)
		}
		systray.Quit()
		*hibernate = true
		restart("")
	}()

	// go func() {
	// 	<-mQuit.ClickedCh
	// 	systray.Quit()
	// 	exit()
	// }()

	go func() {
		for {
			<-mDebug.ClickedCh
			logAction("log on")
			open.Start("http://localhost:8989")
		}
	}()

	// We can manipulate the systray in other goroutines
	go func() {
		for {
			<-mUrl.ClickedCh
			open.Start("http://create-staging.arduino.cc")
		}
	}()
}

func setupSysTrayHibernate() {

	systray.SetIcon(icon.DataHibernate)
	mOpen := systray.AddMenuItem("Open Plugin", "")
	mQuit := systray.AddMenuItem("Kill Plugin", "")

	go func() {
		<-mOpen.ClickedCh
		*hibernate = false
		restart("")
	}()

	go func() {
		<-mQuit.ClickedCh
		systray.Quit()
		exit()
	}()
}
<|endoftext|>


<commit_before>//
//  trayicon.go
//
//  Created by Martino Facchin
//  Copyright (c) 2015 Arduino LLC
//
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//

// +build !cli

package main

import (
	"os"
	"path/filepath"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/arduino/arduino-create-agent/icon"
	"github.com/getlantern/systray"
	"github.com/go-ini/ini"
	"github.com/kardianos/osext"
	"github.com/skratchdot/open-golang/open"
	"go.bug.st/serial.v1"
)

func setupSysTray() {
	runtime.LockOSThread()
	if *hibernate == true {
		systray.Run(setupSysTrayHibernate)
	} else {
		systray.Run(setupSysTrayReal)
	}
}

func addRebootTrayElement() {
	reboot_tray := systray.AddMenuItem("Reboot to update", "")

	go func() {
		<-reboot_tray.ClickedCh
		systray.Quit()
		log.Println("Restarting now...")
		log.Println("Restart because addReebotTrayElement")
		restart("")
	}()
}

type ConfigIni struct {
	Name      string
	Localtion string
}

func getConfigs() []ConfigIni {
	// parse all configs in executable folder
	// config.ini must be there, so call it Default
	src, _ := osext.Executable()
	dest := filepath.Dir(src)

	var configs []ConfigIni

	filepath.Walk(dest, func(path string, f os.FileInfo, _ error) error {
		if !f.IsDir() {
			if filepath.Ext(path) == ".ini" {
				cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, filepath.Join(dest, f.Name()))
				if err != nil {
					return err
				}
				defaultSection, err := cfg.GetSection("")
				name := defaultSection.Key("name").String()
				if name == "" || err != nil {
					name = "Default config"
				}
				conf := ConfigIni{Name: name, Localtion: f.Name()}
				configs = append(configs, conf)
			}
		}
		return nil
	})
	return configs
}

func applyEnvironment(filename string) {
	src, _ := osext.Executable()
	dest := filepath.Dir(src)
	cfg, _ := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, filepath.Join(dest, filename))
	defaultSection, err := cfg.GetSection("env")
	if err != nil {
		return
	}
	for _, env := range defaultSection.KeyStrings() {
		val := defaultSection.Key(env).String()
		log.Info("Applying env setting: " + env + "=" + val)
		os.Setenv(env, val)
	}
}

func setupSysTrayReal() {

	systray.SetIcon(icon.GetIcon())
	mUrl := systray.AddMenuItem("Go to Arduino Create", "Arduino Create")
	mDebug := systray.AddMenuItem("Open debug console", "Debug console")
	menuVer := systray.AddMenuItem("Agent version "+version+"-"+git_revision, "")
	mPause := systray.AddMenuItem("Pause Plugin", "")
	var mConfigCheckbox []*systray.MenuItem

	configs := getConfigs()

	if len(configs) > 1 {
		for _, config := range configs {
			entry := systray.AddMenuItem(config.Name, "")
			mConfigCheckbox = append(mConfigCheckbox, entry)
			// decorate configs
			gliph := " ☐ "
			if *additionalConfig == config.Localtion {
				gliph = " 🗹 "
			}
			entry.SetTitle(gliph + config.Name)
		}
	} else {
		// apply env setting from first config immediately
		// applyEnvironment(configs[0].Localtion)
	}
	//mQuit := systray.AddMenuItem("Quit Plugin", "")

	menuVer.Disable()

	for i, _ := range mConfigCheckbox {
		go func(v int) {
			for {
				<-mConfigCheckbox[v].ClickedCh

				restart("", "-additional-config", configs[v].Localtion)
			}
		}(i)
	}

	go func() {
		<-mPause.ClickedCh
		ports, _ := serial.GetPortsList()
		for _, element := range ports {
			spClose(element)
		}
		systray.Quit()
		*hibernate = true
		log.Println("Restart becayse setup went wrong?")
		restart("")
	}()

	// go func() {
	// 	<-mQuit.ClickedCh
	// 	systray.Quit()
	// 	exit()
	// }()

	go func() {
		for {
			<-mDebug.ClickedCh
			logAction("log on")
			open.Start("http://127.0.0.1" + port)
		}
	}()

	// We can manipulate the systray in other goroutines
	go func() {
		for {
			<-mUrl.ClickedCh
			open.Start("http://create.arduino.cc")
		}
	}()
}

func setupSysTrayHibernate() {

	systray.SetIcon(icon.GetIconHiber())
	mOpen := systray.AddMenuItem("Open Plugin", "")
	mQuit := systray.AddMenuItem("Kill Plugin", "")

	go func() {
		<-mOpen.ClickedCh
		*hibernate = false
		log.Println("Restart for hubernation")
		systray.Quit()
		restart("")
	}()

	go func() {
		<-mQuit.ClickedCh
		systray.Quit()
		exit()
	}()
}

func quitSysTray() {
	systray.Quit()
}
<commit_msg>Remove dead code<commit_after>//
//  trayicon.go
//
//  Created by Martino Facchin
//  Copyright (c) 2015 Arduino LLC
//
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//

// +build !cli

package main

import (
	"os"
	"path/filepath"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/arduino/arduino-create-agent/icon"
	"github.com/getlantern/systray"
	"github.com/go-ini/ini"
	"github.com/kardianos/osext"
	"github.com/skratchdot/open-golang/open"
	"go.bug.st/serial.v1"
)

func setupSysTray() {
	runtime.LockOSThread()
	if *hibernate == true {
		systray.Run(setupSysTrayHibernate)
	} else {
		systray.Run(setupSysTrayReal)
	}
}

func addRebootTrayElement() {
	reboot_tray := systray.AddMenuItem("Reboot to update", "")

	go func() {
		<-reboot_tray.ClickedCh
		systray.Quit()
		log.Println("Restarting now...")
		log.Println("Restart because addReebotTrayElement")
		restart("")
	}()
}

type ConfigIni struct {
	Name      string
	Localtion string
}

func getConfigs() []ConfigIni {
	// parse all configs in executable folder
	// config.ini must be there, so call it Default
	src, _ := osext.Executable()
	dest := filepath.Dir(src)

	var configs []ConfigIni

	filepath.Walk(dest, func(path string, f os.FileInfo, _ error) error {
		if !f.IsDir() {
			if filepath.Ext(path) == ".ini" {
				cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, filepath.Join(dest, f.Name()))
				if err != nil {
					return err
				}
				defaultSection, err := cfg.GetSection("")
				name := defaultSection.Key("name").String()
				if name == "" || err != nil {
					name = "Default config"
				}
				conf := ConfigIni{Name: name, Localtion: f.Name()}
				configs = append(configs, conf)
			}
		}
		return nil
	})
	return configs
}

func setupSysTrayReal() {

	systray.SetIcon(icon.GetIcon())
	mUrl := systray.AddMenuItem("Go to Arduino Create", "Arduino Create")
	mDebug := systray.AddMenuItem("Open debug console", "Debug console")
	menuVer := systray.AddMenuItem("Agent version "+version+"-"+git_revision, "")
	mPause := systray.AddMenuItem("Pause Plugin", "")
	var mConfigCheckbox []*systray.MenuItem

	configs := getConfigs()

	if len(configs) > 1 {
		for _, config := range configs {
			entry := systray.AddMenuItem(config.Name, "")
			mConfigCheckbox = append(mConfigCheckbox, entry)
			// decorate configs
			gliph := " ☐ "
			if *additionalConfig == config.Localtion {
				gliph = " 🗹 "
			}
			entry.SetTitle(gliph + config.Name)
		}
	}
	//mQuit := systray.AddMenuItem("Quit Plugin", "")

	menuVer.Disable()

	for i, _ := range mConfigCheckbox {
		go func(v int) {
			for {
				<-mConfigCheckbox[v].ClickedCh

				restart("", "-additional-config", configs[v].Localtion)
			}
		}(i)
	}

	go func() {
		<-mPause.ClickedCh
		ports, _ := serial.GetPortsList()
		for _, element := range ports {
			spClose(element)
		}
		systray.Quit()
		*hibernate = true
		log.Println("Restart becayse setup went wrong?")
		restart("")
	}()

	// go func() {
	// 	<-mQuit.ClickedCh
	// 	systray.Quit()
	// 	exit()
	// }()

	go func() {
		for {
			<-mDebug.ClickedCh
			logAction("log on")
			open.Start("http://127.0.0.1" + port)
		}
	}()

	// We can manipulate the systray in other goroutines
	go func() {
		for {
			<-mUrl.ClickedCh
			open.Start("http://create.arduino.cc")
		}
	}()
}

func setupSysTrayHibernate() {

	systray.SetIcon(icon.GetIconHiber())
	mOpen := systray.AddMenuItem("Open Plugin", "")
	mQuit := systray.AddMenuItem("Kill Plugin", "")

	go func() {
		<-mOpen.ClickedCh
		*hibernate = false
		log.Println("Restart for hubernation")
		systray.Quit()
		restart("")
	}()

	go func() {
		<-mQuit.ClickedCh
		systray.Quit()
		exit()
	}()
}

func quitSysTray() {
	systray.Quit()
}
<|endoftext|>


<commit_before>package trounoir

import (
	"container/list"
	"github.com/boltdb/bolt"
	"sync"
)

type trounoir struct {
	WriterBuffer *ringBuffer
	ReaderBuffer *ringBuffer
	Bolts        []*bolt.DB
	MemBuffer    []*bucketBuffer
}

func New(bolt_cluster []string, db_name string) {

}

type bucketBuffer struct {
	sync.Mutex
	data      map[string][]byte
	keyQueque *list.List
}

func (bb *bucketBuffer) remove(key string) {
	bb.Lock()
	delete(bb.data, key)
	bb.Unlock()
	go func(k string) {
		var next *list.Element
		for e := bb.keyQueque.Front(); e != nil; e = next {
			next = e.Next()
			if k == e.Value.(string) {
				bb.keyQueque.Remove(e)
			}
		}
	}(key)
}

func (bb *bucketBuffer) add(key string, b []byte) {
	bb.Lock()

	bb.Unlock()
}

type ringBuffer struct {
	inputChannel  <-chan int
	outputChannel chan int
}

func newRingBuffer(inputChannel <-chan int, outputChannel chan int) *ringBuffer {
	return &ringBuffer{inputChannel, outputChannel}
}

func (r *ringBuffer) run() {
	for v := range r.inputChannel {
		select {
		case r.outputChannel <- v:
		default:
			<-r.outputChannel
			r.outputChannel <- v
		}
	}
}
<commit_msg>add buffer with bug<commit_after>package trounoir

import (
	"container/list"
	"github.com/boltdb/bolt"
	"strings"
	"sync"
)

const (
	MAX_MEM_BUFFER_KEY = 2000
)

// collection of db
type trounoir struct {
	InputChannel    chan *item
	OutputChannel   chan *item
	Bolts           []*bolt.DB
	MemBuffer       map[string]*bucketBuffer
	NumMemBufferKey int
	keyQueque       *list.List
}

func New(bolt_cluster []string, db_name string) *trounoir {
	tr := &trounoir{}
	tr.InputChannel = make(chan *item)
	tr.OutputChannel = make(chan *item, len(bolt_cluster))
	return tr
}

type bucketBuffer struct {
	sync.Mutex
	data map[string][]byte
}

func (bb *bucketBuffer) remove(key string) {
	bb.Lock()
	delete(bb.data, key)
	bb.Unlock()
}

// add a key to bucket
func (tr *trounoir) add(bucket string, key string, b []byte) {
	bb := tr.MemBuffer[bucket]
	bb.Lock()
	tr.InputChannel <- &item{bucket, key, b}
	bb.data[key] = b
	tr.keyQueque.PushFront(bucket + " " + key)
	if tr.NumMemBufferKey > MAX_MEM_BUFFER_KEY {
		last_bucket_key := tr.keyQueque.Back()
		i := strings.Index(last_bucket_key.Value.(string), " ")
		b2 := last_bucket_key.Value.(string)[:i]
		k2 := last_bucket_key.Value.(string)[i+1:]
		tr.keyQueque.Remove(last_bucket_key)
		delete(tr.MemBuffer[b2].data, k2)
	} else {
		tr.NumMemBufferKey++
	}
	bb.Unlock()
}

type item struct {
	bucket string
	key    string
	b      []byte
}

func (tr *trounoir) process() {
	for i := range tr.Bolts {
		out := <-tr.OutputChannel
		tr.Bolts[i].Update(func(tx *bolt.Tx) error {
			b := tx.Bucket([]byte(out.bucket))
			return b.Put([]byte(out.key), out.b)
		})
	}
}
<|endoftext|>


<commit_before>/* Common data file features. */
package file

import (
	"errors"
	"fmt"
	"github.com/HouzuoGuo/tiedot/gommap"
	"log"
	"os"
)

const FILE_GROWTH_INCREMENTAL = uint64(16777216)

type File struct {
	Name                   string   // File path and name
	Fh                     *os.File // File handle (in operating system)
	UsedSize, Size, Growth uint64
	Buf                    gommap.MMap // Mapped file buffer
}

// Open the file, or create it if non-existing.
func Open(name string, growth uint64) (file *File, err error) {
	if growth < 1 {
		err = errors.New(fmt.Sprintf("Growth size (%d) is too small (opening %s)", growth, name))
	}
	file = &File{Name: name, Growth: growth}
	// Open file (get a handle) and determine its size
	if file.Fh, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0600); err != nil {
		return
	}
	fsize, err := file.Fh.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	file.Size = uint64(fsize)
	if file.Size == 0 {
		// Grow the file if it appears too small
		file.CheckSizeAndEnsure(file.Growth)
		return
	}
	// Map the file into memory buffer
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	// Bi-sect file buffer to find out how much space in the file is actively in-use
	for low, mid, high := uint64(0), file.Size/2, file.Size; ; {
		switch {
		case high-mid == 1:
			if file.Buf[mid] == 0 {
				if file.Buf[mid-1] == 0 {
					file.UsedSize = mid - 1
				} else {
					file.UsedSize = mid
				}
				return
			}
			file.UsedSize = high
			return
		case file.Buf[mid] == 0:
			high = mid
			mid = low + (mid-low)/2
		default:
			low = mid
			mid = mid + (high-mid)/2
		}
	}
	log.Printf("%s has %d bytes out of %d bytes in-use", name, file.UsedSize, file.Size)
	return
}

// Return true only if the file has enough room for more data.
func (file *File) CheckSize(more uint64) bool {
	return file.UsedSize+more <= file.Size
}

// Ensure that the file has enough room for more data. Grow the file if necessary.
func (file *File) CheckSizeAndEnsure(more uint64) {
	if file.UsedSize+more <= file.Size {
		return
	}
	// Unmap file buffer
	var err error
	if file.Buf != nil {
		if err = file.Buf.Unmap(); err != nil {
			panic(err)
		}
	}
	if _, err = file.Fh.Seek(0, os.SEEK_END); err != nil {
		panic(err)
	}
	// Grow file size (incrementally)
	zeroBuf := make([]byte, FILE_GROWTH_INCREMENTAL)
	for i := uint64(0); i < file.Growth; i += FILE_GROWTH_INCREMENTAL {
		var slice []byte
		if i+FILE_GROWTH_INCREMENTAL > file.Growth {
			slice = zeroBuf[0 : i+FILE_GROWTH_INCREMENTAL-file.Growth]
		} else {
			slice = zeroBuf
		}
		if _, err = file.Fh.Write(slice); err != nil {
			panic(err)
		}
	}
	if err = file.Fh.Sync(); err != nil {
		panic(err)
	}
	// Re-map the (now larger) file buffer
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		panic(err)
	}
	file.Size += file.Growth
	log.Printf("File %s has grown %d bytes\n", file.Name, file.Growth)
	file.CheckSizeAndEnsure(more)
}

// Synchronize file buffer with underlying storage device.
func (file *File) Flush() error {
	return file.Buf.Flush()
}

// Close the file.
func (file *File) Close() (err error) {
	if err = file.Buf.Unmap(); err != nil {
		return
	}
	return file.Fh.Close()
}
<commit_msg>a more accurate way to find beginning of unused file space<commit_after>/* Common data file features. */
package file

import (
	"errors"
	"fmt"
	"github.com/HouzuoGuo/tiedot/gommap"
	"log"
	"os"
)

const FILE_GROWTH_INCREMENTAL = uint64(16777216)

type File struct {
	Name                   string   // File path and name
	Fh                     *os.File // File handle (in operating system)
	UsedSize, Size, Growth uint64
	Buf                    gommap.MMap // Mapped file buffer
}

// Return true if the buffer begins with ten consecutive 0s.
func ConsecutiveTwenty0s(buf gommap.MMap) bool {
	for i := 0; i < 20; i++ {
		if buf[i] != 0 {
			return false
		}
	}
	return true
}

// Open the file, or create it if non-existing.
func Open(name string, growth uint64) (file *File, err error) {
	if growth < 1 {
		err = errors.New(fmt.Sprintf("Growth size (%d) is too small (opening %s)", growth, name))
	}
	file = &File{Name: name, Growth: growth}
	// Open file (get a handle) and determine its size
	if file.Fh, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0600); err != nil {
		return
	}
	fsize, err := file.Fh.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	file.Size = uint64(fsize)
	if file.Size == 0 {
		// Grow the file if it appears too small
		file.CheckSizeAndEnsure(file.Growth)
		return
	}
	// Map the file into memory buffer
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	// Bi-sect file buffer to find out how much space in the file is actively in-use
	for low, mid, high := uint64(0), file.Size/2, file.Size; ; {
		switch {
		case high-mid == 1:
			if ConsecutiveTwenty0s(file.Buf[mid:]) {
				if ConsecutiveTwenty0s(file.Buf[mid-1:]) {
					file.UsedSize = mid - 1
				} else {
					file.UsedSize = mid
				}
				return
			}
			file.UsedSize = high
			return
		case ConsecutiveTwenty0s(file.Buf[mid:]):
			high = mid
			mid = low + (mid-low)/2
		default:
			low = mid
			mid = mid + (high-mid)/2
		}
	}
	log.Printf("%s has %d bytes out of %d bytes in-use", name, file.UsedSize, file.Size)
	return
}

// Return true only if the file has enough room for more data.
func (file *File) CheckSize(more uint64) bool {
	return file.UsedSize+more <= file.Size
}

// Ensure that the file has enough room for more data. Grow the file if necessary.
func (file *File) CheckSizeAndEnsure(more uint64) {
	if file.UsedSize+more <= file.Size {
		return
	}
	// Unmap file buffer
	var err error
	if file.Buf != nil {
		if err = file.Buf.Unmap(); err != nil {
			panic(err)
		}
	}
	if _, err = file.Fh.Seek(0, os.SEEK_END); err != nil {
		panic(err)
	}
	// Grow file size (incrementally)
	zeroBuf := make([]byte, FILE_GROWTH_INCREMENTAL)
	for i := uint64(0); i < file.Growth; i += FILE_GROWTH_INCREMENTAL {
		var slice []byte
		if i+FILE_GROWTH_INCREMENTAL > file.Growth {
			slice = zeroBuf[0 : i+FILE_GROWTH_INCREMENTAL-file.Growth]
		} else {
			slice = zeroBuf
		}
		if _, err = file.Fh.Write(slice); err != nil {
			panic(err)
		}
	}
	if err = file.Fh.Sync(); err != nil {
		panic(err)
	}
	// Re-map the (now larger) file buffer
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		panic(err)
	}
	file.Size += file.Growth
	log.Printf("File %s has grown %d bytes\n", file.Name, file.Growth)
	file.CheckSizeAndEnsure(more)
}

// Synchronize file buffer with underlying storage device.
func (file *File) Flush() error {
	return file.Buf.Flush()
}

// Close the file.
func (file *File) Close() (err error) {
	if err = file.Buf.Unmap(); err != nil {
		return
	}
	return file.Fh.Close()
}
<|endoftext|>


<commit_before>package flint

import (
	"github.com/codegangsta/cli"

	"fmt"
	"os"
	"runtime"
)

func NewApp() *cli.App {
	app := cli.NewApp()
	app.Name = "flint"
	app.Usage = "Check a project for common sources of contributor friction"
	app.Version = "0.0.4"
	app.Flags = []cli.Flag{
		cli.BoolFlag{"skip-readme", "skip check for README", ""},
		cli.BoolFlag{"skip-contributing", "skip check for contributing guide", ""},
		cli.BoolFlag{"skip-license", "skip check for license", ""},
		cli.BoolFlag{"skip-bootstrap", "skip check for bootstrap script", ""},
		cli.BoolFlag{"skip-test-script", "skip check for test script", ""},
		cli.BoolFlag{"skip-scripts", "skip check for all scripts", ""},
		cli.BoolFlag{"no-color", "skip coloring the terminal output", ""},
		cli.StringFlag{
			Name:  "github, g",
			Value: "",
			Usage: "GitHub repository as owner/repo",
		},
		cli.StringFlag{
			Name:   "token, t",
			Value:  "",
			EnvVar: "FLINT_TOKEN",
			Usage:  "GitHub API access token",
		},
	}
	app.Action = func(c *cli.Context) {
		run(c)
	}

	return app
}

type runFunc func(*cli.Context)

var run = func(c *cli.Context) {
	project := newProject(c)
	flags := newFlagsFromContext(c)
	linter := &Linter{}
	summary, err := linter.Run(project, flags)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
		return
	}
	if summary != nil {
		color := !c.Bool("no-color")
		// Windows doesn't support colors
		if runtime.GOOS == "windows" {
			color = false
		}
		summary.Print(os.Stderr, color)
		os.Exit(summary.Severity())
	}
}

func newProject(c *cli.Context) Project {
	github := c.String("github")
	if len(github) > 0 {
		project := &RemoteProject{FullName: github}
		fetcher := newGitHubFetcher(c)
		err := project.Fetch(fetcher)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		return project
	} else {
		path, _ := os.Getwd()
		if len(c.Args()) > 0 {
			path = c.Args()[0]
		}
		return &LocalProject{Path: path}
	}
}

func newFlagsFromContext(c *cli.Context) *Flags {
	runBootstrap := !c.Bool("skip-bootstrap")
	runTestScript := !c.Bool("skip-test-script")
	if c.Bool("skip-scripts") {
		runBootstrap = false
		runTestScript = false
	}

	flags := &Flags{
		RunReadme:       !c.Bool("skip-readme"),
		RunContributing: !c.Bool("skip-contributing"),
		RunLicense:      !c.Bool("skip-license"),
		RunBootstrap:    runBootstrap,
		RunTestScript:   runTestScript,
	}
	return flags
}

var newGitHubFetcher = func(c *cli.Context) RemoteRepositoryFetcher {
	token := c.String("token")
	if len(token) > 0 {
		return NewGitHubFetcherWithToken(token)
	} else {
		return NewGitHubFetcher()
	}
}
<commit_msg>Fix compile error "too few values in struct initializer"<commit_after>package flint

import (
	"github.com/codegangsta/cli"

	"fmt"
	"os"
	"runtime"
)

func NewApp() *cli.App {
	app := cli.NewApp()
	app.Name = "flint"
	app.Usage = "Check a project for common sources of contributor friction"
	app.Version = "0.0.4"
	app.Flags = []cli.Flag{
		cli.BoolFlag{"skip-readme", "skip check for README", "", nil},
		cli.BoolFlag{"skip-contributing", "skip check for contributing guide", "", nil},
		cli.BoolFlag{"skip-license", "skip check for license", "", nil},
		cli.BoolFlag{"skip-bootstrap", "skip check for bootstrap script", "", nil},
		cli.BoolFlag{"skip-test-script", "skip check for test script", "", nil},
		cli.BoolFlag{"skip-scripts", "skip check for all scripts", "", nil},
		cli.BoolFlag{"no-color", "skip coloring the terminal output", "", nil},
		cli.StringFlag{
			Name:  "github, g",
			Value: "",
			Usage: "GitHub repository as owner/repo",
		},
		cli.StringFlag{
			Name:   "token, t",
			Value:  "",
			EnvVar: "FLINT_TOKEN",
			Usage:  "GitHub API access token",
		},
	}
	app.Action = func(c *cli.Context) {
		run(c)
	}

	return app
}

type runFunc func(*cli.Context)

var run = func(c *cli.Context) {
	project := newProject(c)
	flags := newFlagsFromContext(c)
	linter := &Linter{}
	summary, err := linter.Run(project, flags)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
		return
	}
	if summary != nil {
		color := !c.Bool("no-color")
		// Windows doesn't support colors
		if runtime.GOOS == "windows" {
			color = false
		}
		summary.Print(os.Stderr, color)
		os.Exit(summary.Severity())
	}
}

func newProject(c *cli.Context) Project {
	github := c.String("github")
	if len(github) > 0 {
		project := &RemoteProject{FullName: github}
		fetcher := newGitHubFetcher(c)
		err := project.Fetch(fetcher)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		return project
	} else {
		path, _ := os.Getwd()
		if len(c.Args()) > 0 {
			path = c.Args()[0]
		}
		return &LocalProject{Path: path}
	}
}

func newFlagsFromContext(c *cli.Context) *Flags {
	runBootstrap := !c.Bool("skip-bootstrap")
	runTestScript := !c.Bool("skip-test-script")
	if c.Bool("skip-scripts") {
		runBootstrap = false
		runTestScript = false
	}

	flags := &Flags{
		RunReadme:       !c.Bool("skip-readme"),
		RunContributing: !c.Bool("skip-contributing"),
		RunLicense:      !c.Bool("skip-license"),
		RunBootstrap:    runBootstrap,
		RunTestScript:   runTestScript,
	}
	return flags
}

var newGitHubFetcher = func(c *cli.Context) RemoteRepositoryFetcher {
	token := c.String("token")
	if len(token) > 0 {
		return NewGitHubFetcherWithToken(token)
	} else {
		return NewGitHubFetcher()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.88"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.55", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<commit_msg>fnlb: 0.0.89 release [skip ci]<commit_after>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.89"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.56", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"strings"

	"github.com/appc/spec/schema/types"
	"github.com/blablacar/dgr/dgr/common"
	"github.com/n0rad/go-erlog/errs"
	"github.com/n0rad/go-erlog/logs"
	"gopkg.in/yaml.v2"
)

const pathTestsTarget = "/tests-target"
const pathTestsResult = "/tests-result"
const mountAcname = "test-result"
const statusSuffix = "_status"
const fileEndOfTests = "end-of-tests"

func (aci *Aci) Test() error {
	defer aci.giveBackUserRightsToTarget()
	hashAcis, err := aci.Install()
	if err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Testing")

	ImportInternalTesterIfNeeded(aci.manifest)

	logs.WithF(aci.fields).Info("Building test aci")
	hashTestAci, err := aci.buildTestAci()
	if err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Running test aci")
	if err := aci.runTestAci(hashTestAci, hashAcis); err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Checking result")
	if err := aci.checkResult(); err != nil {
		return err
	}
	return nil
}

func (aci *Aci) checkResult() error {
	files, err := ioutil.ReadDir(aci.target + pathTestsResult)
	if err != nil {
		return errs.WithEF(err, aci.fields, "Cannot read test result directory")
	}
	testFound := false
	getToTheEnd := false
	for _, f := range files {
		if f.Name() == fileEndOfTests {
			getToTheEnd = true
			continue
		}
		testFields := aci.fields.WithField("file", f.Name())
		fullPath := aci.target + pathTestsResult + "/" + f.Name()
		content, err := ioutil.ReadFile(fullPath)
		if err != nil {
			return errs.WithEF(err, testFields, "Cannot read result file")
		}
		if !strings.HasSuffix(f.Name(), statusSuffix) {
			if testFound == false && string(content) != "1..0\n" {
				testFound = true
			}
			continue
		}
		if string(content) != "0\n" {
			return errs.WithEF(err, testFields, "Failed test")
		}
	}
	if !getToTheEnd {
		return errs.WithF(aci.fields, "Something goes wrong while running tests")
	}

	if Args.NoTestFail && !testFound {
		return errs.WithEF(err, aci.fields, "No tests found")
	}
	return nil
}

func (aci *Aci) runTestAci(testerHash string, hashAcis []string) error {
	os.MkdirAll(aci.target+pathTestsResult, 0777)

	defer aci.cleanupTest(testerHash, hashAcis)
	if err := Home.Rkt.Run([]string{"--set-env=" + common.EnvLogLevel + "=" + logs.GetLevel().String(),
		"--net=default",
		"--mds-register=false",
		"--uuid-file-save=" + aci.target + pathTesterUuid,
		"--volume=" + mountAcname + ",kind=host,source=" + aci.target + pathTestsResult,
		testerHash,
		"--exec", "/test",
	}); err != nil {
		return errs.WithEF(err, aci.fields, "Run of test aci failed")
	}
	return nil
}

func (aci *Aci) cleanupTest(testerHash string, hashAcis []string) {
	if !Args.KeepBuilder {
		if _, _, err := Home.Rkt.RmFromFile(aci.target + pathTesterUuid); err != nil {
			logs.WithEF(err, aci.fields).Warn("Failed to remove test container")
		}
	}

	for _, hash := range hashAcis {
		if err := Home.Rkt.ImageRm(hash); err != nil {
			logs.WithEF(err, aci.fields.WithField("hash", hash)).Warn("Failed to remove container image")
		}
	}

	if err := Home.Rkt.ImageRm(testerHash); err != nil {
		logs.WithEF(err, aci.fields.WithField("hash", testerHash)).Warn("Failed to remove test container image")
	}
}

func (aci *Aci) buildTestAci() (string, error) {
	manifest, err := common.ExtractManifestFromAci(aci.target + common.PathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields.WithField("file", aci.target+common.PathImageAci), "Failed to extract manifest from aci")
	}

	name := prefixTest + manifest.Name.String()
	if version, ok := manifest.Labels.Get("version"); ok {
		name += ":" + version
	}

	fullname := common.NewACFullName(name)
	resultMountName, _ := types.NewACName(mountAcname)

	isolators := aci.manifest.Tester.Aci.App.Isolators

	if len(isolators) == 0 {
		isolators = aci.manifest.Aci.App.Isolators
	}

	aciManifest := &common.AciManifest{
		Builder: aci.manifest.Tester.Builder,
		Aci: common.AciDefinition{
			App: common.DgrApp{
				Exec:              aci.manifest.Aci.App.Exec,
				MountPoints:       []types.MountPoint{{Path: pathTestsResult, Name: *resultMountName}},
				WorkingDirectory:  aci.manifest.Aci.App.WorkingDirectory,
				User:              aci.manifest.Aci.App.User,
				Group:             aci.manifest.Aci.App.Group,
				SupplementaryGIDs: aci.manifest.Aci.App.SupplementaryGIDs,
				Environment:       aci.manifest.Aci.App.Environment,
				Ports:             aci.manifest.Aci.App.Ports,
				Isolators:         isolators,
			},
			Dependencies:  append(aci.manifest.Tester.Aci.Dependencies, *common.NewACFullName(name[len(prefixTest):])),
			Annotations:   aci.manifest.Aci.Annotations,
			PathWhitelist: aci.manifest.Aci.PathWhitelist,
		},
		NameAndVersion: *fullname,
	}

	content, err := yaml.Marshal(aciManifest)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to marshall manifest for test aci")
	}

	testAci, err := NewAciWithManifest(aci.path, aci.args, string(content), aci.checkWg)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to prepare test's build aci")
	}

	testAci.FullyResolveDep = false // this is required to run local tests without discovery
	testAci.target = aci.target + pathTestsTarget

	if err := testAci.CleanAndBuild(); err != nil {
		return "", errs.WithEF(err, aci.fields, "Build of test aci failed")
	}
	hash, err := Home.Rkt.Fetch(aci.target + pathTestsTarget + pathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "fetch of test aci failed")
	}
	return hash, nil
}
<commit_msg>Add environment variable when running dgr test<commit_after>package main

import (
	"io/ioutil"
	"os"
	"strings"

	"github.com/appc/spec/schema/types"
	"github.com/blablacar/dgr/dgr/common"
	"github.com/n0rad/go-erlog/errs"
	"github.com/n0rad/go-erlog/logs"
	"gopkg.in/yaml.v2"
)

const pathTestsTarget = "/tests-target"
const pathTestsResult = "/tests-result"
const mountAcname = "test-result"
const statusSuffix = "_status"
const fileEndOfTests = "end-of-tests"

func (aci *Aci) Test() error {
	defer aci.giveBackUserRightsToTarget()
	hashAcis, err := aci.Install()
	if err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Testing")

	ImportInternalTesterIfNeeded(aci.manifest)

	logs.WithF(aci.fields).Info("Building test aci")
	hashTestAci, err := aci.buildTestAci()
	if err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Running test aci")
	if err := aci.runTestAci(hashTestAci, hashAcis); err != nil {
		return err
	}

	logs.WithF(aci.fields).Info("Checking result")
	if err := aci.checkResult(); err != nil {
		return err
	}
	return nil
}

func (aci *Aci) checkResult() error {
	files, err := ioutil.ReadDir(aci.target + pathTestsResult)
	if err != nil {
		return errs.WithEF(err, aci.fields, "Cannot read test result directory")
	}
	testFound := false
	getToTheEnd := false
	for _, f := range files {
		if f.Name() == fileEndOfTests {
			getToTheEnd = true
			continue
		}
		testFields := aci.fields.WithField("file", f.Name())
		fullPath := aci.target + pathTestsResult + "/" + f.Name()
		content, err := ioutil.ReadFile(fullPath)
		if err != nil {
			return errs.WithEF(err, testFields, "Cannot read result file")
		}
		if !strings.HasSuffix(f.Name(), statusSuffix) {
			if testFound == false && string(content) != "1..0\n" {
				testFound = true
			}
			continue
		}
		if string(content) != "0\n" {
			return errs.WithEF(err, testFields, "Failed test")
		}
	}
	if !getToTheEnd {
		return errs.WithF(aci.fields, "Something goes wrong while running tests")
	}

	if Args.NoTestFail && !testFound {
		return errs.WithEF(err, aci.fields, "No tests found")
	}
	return nil
}

func (aci *Aci) runTestAci(testerHash string, hashAcis []string) error {
	os.MkdirAll(aci.target+pathTestsResult, 0777)

	defer aci.cleanupTest(testerHash, hashAcis)
	if err := Home.Rkt.Run([]string{"--set-env=" + common.EnvLogLevel + "=" + logs.GetLevel().String(),
		"--set-env=TESTER=TRUE",
		"--net=default",
		"--mds-register=false",
		"--uuid-file-save=" + aci.target + pathTesterUuid,
		"--volume=" + mountAcname + ",kind=host,source=" + aci.target + pathTestsResult,
		testerHash,
		"--exec", "/test",
	}); err != nil {
		return errs.WithEF(err, aci.fields, "Run of test aci failed")
	}
	return nil
}

func (aci *Aci) cleanupTest(testerHash string, hashAcis []string) {
	if !Args.KeepBuilder {
		if _, _, err := Home.Rkt.RmFromFile(aci.target + pathTesterUuid); err != nil {
			logs.WithEF(err, aci.fields).Warn("Failed to remove test container")
		}
	}

	for _, hash := range hashAcis {
		if err := Home.Rkt.ImageRm(hash); err != nil {
			logs.WithEF(err, aci.fields.WithField("hash", hash)).Warn("Failed to remove container image")
		}
	}

	if err := Home.Rkt.ImageRm(testerHash); err != nil {
		logs.WithEF(err, aci.fields.WithField("hash", testerHash)).Warn("Failed to remove test container image")
	}
}

func (aci *Aci) buildTestAci() (string, error) {
	manifest, err := common.ExtractManifestFromAci(aci.target + common.PathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields.WithField("file", aci.target+common.PathImageAci), "Failed to extract manifest from aci")
	}

	name := prefixTest + manifest.Name.String()
	if version, ok := manifest.Labels.Get("version"); ok {
		name += ":" + version
	}

	fullname := common.NewACFullName(name)
	resultMountName, _ := types.NewACName(mountAcname)

	isolators := aci.manifest.Tester.Aci.App.Isolators

	if len(isolators) == 0 {
		isolators = aci.manifest.Aci.App.Isolators
	}

	aciManifest := &common.AciManifest{
		Builder: aci.manifest.Tester.Builder,
		Aci: common.AciDefinition{
			App: common.DgrApp{
				Exec:              aci.manifest.Aci.App.Exec,
				MountPoints:       []types.MountPoint{{Path: pathTestsResult, Name: *resultMountName}},
				WorkingDirectory:  aci.manifest.Aci.App.WorkingDirectory,
				User:              aci.manifest.Aci.App.User,
				Group:             aci.manifest.Aci.App.Group,
				SupplementaryGIDs: aci.manifest.Aci.App.SupplementaryGIDs,
				Environment:       aci.manifest.Aci.App.Environment,
				Ports:             aci.manifest.Aci.App.Ports,
				Isolators:         isolators,
			},
			Dependencies:  append(aci.manifest.Tester.Aci.Dependencies, *common.NewACFullName(name[len(prefixTest):])),
			Annotations:   aci.manifest.Aci.Annotations,
			PathWhitelist: aci.manifest.Aci.PathWhitelist,
		},
		NameAndVersion: *fullname,
	}

	content, err := yaml.Marshal(aciManifest)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to marshall manifest for test aci")
	}

	testAci, err := NewAciWithManifest(aci.path, aci.args, string(content), aci.checkWg)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "Failed to prepare test's build aci")
	}

	testAci.FullyResolveDep = false // this is required to run local tests without discovery
	testAci.target = aci.target + pathTestsTarget

	if err := testAci.CleanAndBuild(); err != nil {
		return "", errs.WithEF(err, aci.fields, "Build of test aci failed")
	}
	hash, err := Home.Rkt.Fetch(aci.target + pathTestsTarget + pathImageAci)
	if err != nil {
		return "", errs.WithEF(err, aci.fields, "fetch of test aci failed")
	}
	return hash, nil
}
<|endoftext|>


<commit_before>package main

func grantPermissions(printOnly bool, verbose bool) {
	idx := 0
	// map for storing the SQL statements by name
	queryMap := make(map[string]string)
	// slice storing the required statement order so foreign keys can
	// resolve successfully
	queries := make([]string, 100)

	queryMap["grantServiceUserSchemaSoma"] = `grant select, insert, update, delete on all tables in schema soma to soma_svc;`
	queries[idx] = "grantServiceUserSchemaSoma"
	idx++

	queryMap["grantServiceUserSequencesSoma"] = `grant usage, select on all sequences in schema soma to soma_svc;`
	queries[idx] = "grantServiceUserSequencesSoma"
	idx++

	queryMap["grantServiceUserSchemaRoot"] = `grant select on all tables in schema root ro soma_svc;`
	queries[idx] = "grantServiceUserSequencesSoma"
	idx++

	queryMap["grantServiceUserSchemaInventory"] = `grant select, insert, update, delete on all tables in schema inventory to soma_svc;`
	queries[idx] = "grantServiceUserSchemaInventory"
	idx++

	queryMap["grantServiceUserSequencesInventory"] = `grant usage, select on all sequences in schema inventory to soma_svc;`
	queries[idx] = "grantServiceUserSequencesInventory"
	idx++

	queryMap["grantServiceUserSchemaAuth"] = `grant select, insert, update, delete on all tables in schema auth to soma_svc;`
	queries[idx] = "grantServiceUserSchemaAuth"
	idx++

	queryMap["grantServiceUserSequencesAuth"] = `grant usage, select on all sequences in schema auth to soma_svc;`
	queries[idx] = "grantServiceUserSequencesAuth"
	idx++

	queryMap["grantInventoryUserSchemaInventory"] = `grant select, insert, update, delete on all tables in schema inventory to soma_inv;`
	queries[idx] = "grantInventoryUserSchemaInventory"
	idx++

	queryMap["grantServiceUserSchemaPublic"] = `grant select on all tables in schema public to soma_svc;`
	queries[idx] = "grantServiceUserSchemaPublic"
	idx++

	queryMap["grantServiceUserSequencesPublic"] = `grant usage, select on all sequences in schema public to soma_svc;`
	queries[idx] = "grantServiceUserSequencesPublic"
	idx++

	performDatabaseTask(printOnly, verbose, queries[:idx], queryMap)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Fix permissions on schema root<commit_after>package main

func grantPermissions(printOnly bool, verbose bool) {
	idx := 0
	// map for storing the SQL statements by name
	queryMap := make(map[string]string)
	// slice storing the required statement order so foreign keys can
	// resolve successfully
	queries := make([]string, 100)

	queryMap["grantServiceUserSchemaSoma"] = `grant select, insert, update, delete on all tables in schema soma to soma_svc;`
	queries[idx] = "grantServiceUserSchemaSoma"
	idx++

	queryMap["grantServiceUserSequencesSoma"] = `grant usage, select on all sequences in schema soma to soma_svc;`
	queries[idx] = "grantServiceUserSequencesSoma"
	idx++

	queryMap["grantServiceUserSchemaRoot"] = `grant select on all tables in schema root ro soma_svc;`
	queries[idx] = "grantServiceUserSchemaRoot"
	idx++

	queryMap["grantServiceUserSchemaInventory"] = `grant select, insert, update, delete on all tables in schema inventory to soma_svc;`
	queries[idx] = "grantServiceUserSchemaInventory"
	idx++

	queryMap["grantServiceUserSequencesInventory"] = `grant usage, select on all sequences in schema inventory to soma_svc;`
	queries[idx] = "grantServiceUserSequencesInventory"
	idx++

	queryMap["grantServiceUserSchemaAuth"] = `grant select, insert, update, delete on all tables in schema auth to soma_svc;`
	queries[idx] = "grantServiceUserSchemaAuth"
	idx++

	queryMap["grantServiceUserSequencesAuth"] = `grant usage, select on all sequences in schema auth to soma_svc;`
	queries[idx] = "grantServiceUserSequencesAuth"
	idx++

	queryMap["grantInventoryUserSchemaInventory"] = `grant select, insert, update, delete on all tables in schema inventory to soma_inv;`
	queries[idx] = "grantInventoryUserSchemaInventory"
	idx++

	queryMap["grantServiceUserSchemaPublic"] = `grant select on all tables in schema public to soma_svc;`
	queries[idx] = "grantServiceUserSchemaPublic"
	idx++

	queryMap["grantServiceUserSequencesPublic"] = `grant usage, select on all sequences in schema public to soma_svc;`
	queries[idx] = "grantServiceUserSequencesPublic"
	idx++

	performDatabaseTask(printOnly, verbose, queries[:idx], queryMap)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 builder

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

	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/util"
)

func (t *TargetBuilder) Load(extraJtagCmd string) error {

	err := t.PrepBuild()

	if err != nil {
		return err
	}

	if t.LoaderBuilder != nil {
		err = t.AppBuilder.Load(1, extraJtagCmd)
		if err == nil {
			err = t.LoaderBuilder.Load(0, extraJtagCmd)
		}
	} else {
		err = t.AppBuilder.Load(0, extraJtagCmd)
	}

	return err
}

func Load(binBaseName string, bspPkg *pkg.BspPackage,
	extraEnvSettings map[string]string) error {

	if bspPkg.DownloadScript == "" {
		return util.FmtNewtError("No download script for BSP %s\n",
			bspPkg.Name())
	}

	bspPath := bspPkg.BasePath()
	downloadScript := filepath.Join(bspPath, bspPkg.DownloadScript)

	sortedKeys := make([]string, 0, len(extraEnvSettings))
	for k, _ := range extraEnvSettings {
		sortedKeys = append(sortedKeys, k)
	}
	sort.Strings(sortedKeys)

	envSettings := ""
	for _, key := range sortedKeys {
		envSettings += fmt.Sprintf("%s=\"%s\" ", key, extraEnvSettings[key])
	}

	envSettings += fmt.Sprintf("BSP_PATH=\"%s\" ", bspPath)
	envSettings += fmt.Sprintf("BIN_BASENAME=\"%s\" ", binBaseName)

	// bspPath, binBaseName are passed in command line for backwards
	// compatibility
	downloadCmd := fmt.Sprintf("%s %s %s %s", envSettings, downloadScript,
		bspPath, binBaseName)

	util.StatusMessage(util.VERBOSITY_VERBOSE, "Load command: %s\n",
		downloadCmd)
	rsp, err := util.ShellCommand(downloadCmd)
	if err != nil {
		util.StatusMessage(util.VERBOSITY_DEFAULT, "%s", rsp)
		return err
	}
	util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")

	return nil
}

func (b *Builder) Load(imageSlot int, extraJtagCmd string) error {
	if b.appPkg == nil {
		return util.NewNewtError("app package not specified")
	}

	/* Populate the package list and feature sets. */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	envSettings := map[string]string{
		"IMAGE_SLOT": strconv.Itoa(imageSlot),
		"FEATURES":   b.FeatureString(),
	}
	if extraJtagCmd != "" {
		envSettings["EXTRA_JTAG_CMD"] = extraJtagCmd
	}

	features := b.cfg.Features()

	if _, ok := features["BOOT_LOADER"]; ok {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading bootloader\n")
	} else {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading %s image into slot %d\n", b.buildName, imageSlot+1)
	}

	if err := Load(b.AppBinBasePath(), b.targetBuilder.bspPkg,
		envSettings); err != nil {

		return err
	}

	util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")

	return nil
}

func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool) error {
	//var additional_libs []string
	err := t.PrepBuild()

	if err != nil {
		return err
	}

	if t.LoaderBuilder == nil {
		return t.AppBuilder.Debug(extraJtagCmd, reset)
	}
	return t.LoaderBuilder.Debug(extraJtagCmd, reset)
}

func (b *Builder) Debug(extraJtagCmd string, reset bool) error {
	if b.appPkg == nil {
		return util.NewNewtError("app package not specified")
	}

	/*
	 * Populate the package list and feature sets.
	 */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	bspPath := b.bspPkg.BasePath()
	binBaseName := b.AppBinBasePath()
	featureString := b.FeatureString()

	envSettings := []string{
		fmt.Sprintf("BSP_PATH=%s", bspPath),
		fmt.Sprintf("BIN_BASENAME=%s", binBaseName),
		fmt.Sprintf("FEATURES=\"%s\"", featureString),
	}
	if extraJtagCmd != "" {
		envSettings = append(envSettings,
			fmt.Sprintf("EXTRA_JTAG_CMD=%s", extraJtagCmd))
	}
	if reset == true {
		envSettings = append(envSettings, fmt.Sprintf("RESET=true"))
	}
	debugScript := filepath.Join(bspPath, b.targetBuilder.bspPkg.DebugScript)

	os.Chdir(project.GetProject().Path())

	// bspPath, binBaseName are passed in command line for backwards
	// compatibility
	cmdLine := []string{debugScript, bspPath, binBaseName}

	fmt.Printf("%s\n", cmdLine)
	return util.ShellInteractiveCommand(cmdLine, envSettings)
}
<commit_msg>newt; not having download script is ok. Don't error out.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 builder

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

	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/util"
)

func (t *TargetBuilder) Load(extraJtagCmd string) error {

	err := t.PrepBuild()

	if err != nil {
		return err
	}

	if t.LoaderBuilder != nil {
		err = t.AppBuilder.Load(1, extraJtagCmd)
		if err == nil {
			err = t.LoaderBuilder.Load(0, extraJtagCmd)
		}
	} else {
		err = t.AppBuilder.Load(0, extraJtagCmd)
	}

	return err
}

func Load(binBaseName string, bspPkg *pkg.BspPackage,
	extraEnvSettings map[string]string) error {

	if bspPkg.DownloadScript == "" {
		return nil
	}

	bspPath := bspPkg.BasePath()
	downloadScript := filepath.Join(bspPath, bspPkg.DownloadScript)

	sortedKeys := make([]string, 0, len(extraEnvSettings))
	for k, _ := range extraEnvSettings {
		sortedKeys = append(sortedKeys, k)
	}
	sort.Strings(sortedKeys)

	envSettings := ""
	for _, key := range sortedKeys {
		envSettings += fmt.Sprintf("%s=\"%s\" ", key, extraEnvSettings[key])
	}

	envSettings += fmt.Sprintf("BSP_PATH=\"%s\" ", bspPath)
	envSettings += fmt.Sprintf("BIN_BASENAME=\"%s\" ", binBaseName)

	// bspPath, binBaseName are passed in command line for backwards
	// compatibility
	downloadCmd := fmt.Sprintf("%s %s %s %s", envSettings, downloadScript,
		bspPath, binBaseName)

	util.StatusMessage(util.VERBOSITY_VERBOSE, "Load command: %s\n",
		downloadCmd)
	rsp, err := util.ShellCommand(downloadCmd)
	if err != nil {
		util.StatusMessage(util.VERBOSITY_DEFAULT, "%s", rsp)
		return err
	}
	util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")

	return nil
}

func (b *Builder) Load(imageSlot int, extraJtagCmd string) error {
	if b.appPkg == nil {
		return util.NewNewtError("app package not specified")
	}

	/* Populate the package list and feature sets. */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	envSettings := map[string]string{
		"IMAGE_SLOT": strconv.Itoa(imageSlot),
		"FEATURES":   b.FeatureString(),
	}
	if extraJtagCmd != "" {
		envSettings["EXTRA_JTAG_CMD"] = extraJtagCmd
	}

	features := b.cfg.Features()

	if _, ok := features["BOOT_LOADER"]; ok {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading bootloader\n")
	} else {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading %s image into slot %d\n", b.buildName, imageSlot+1)
	}

	if err := Load(b.AppBinBasePath(), b.targetBuilder.bspPkg,
		envSettings); err != nil {

		return err
	}

	util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")

	return nil
}

func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool) error {
	//var additional_libs []string
	err := t.PrepBuild()

	if err != nil {
		return err
	}

	if t.LoaderBuilder == nil {
		return t.AppBuilder.Debug(extraJtagCmd, reset)
	}
	return t.LoaderBuilder.Debug(extraJtagCmd, reset)
}

func (b *Builder) Debug(extraJtagCmd string, reset bool) error {
	if b.appPkg == nil {
		return util.NewNewtError("app package not specified")
	}

	/*
	 * Populate the package list and feature sets.
	 */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	bspPath := b.bspPkg.BasePath()
	binBaseName := b.AppBinBasePath()
	featureString := b.FeatureString()

	envSettings := []string{
		fmt.Sprintf("BSP_PATH=%s", bspPath),
		fmt.Sprintf("BIN_BASENAME=%s", binBaseName),
		fmt.Sprintf("FEATURES=\"%s\"", featureString),
	}
	if extraJtagCmd != "" {
		envSettings = append(envSettings,
			fmt.Sprintf("EXTRA_JTAG_CMD=%s", extraJtagCmd))
	}
	if reset == true {
		envSettings = append(envSettings, fmt.Sprintf("RESET=true"))
	}
	debugScript := filepath.Join(bspPath, b.targetBuilder.bspPkg.DebugScript)

	os.Chdir(project.GetProject().Path())

	// bspPath, binBaseName are passed in command line for backwards
	// compatibility
	cmdLine := []string{debugScript, bspPath, binBaseName}

	fmt.Printf("%s\n", cmdLine)
	return util.ShellInteractiveCommand(cmdLine, envSettings)
}
<|endoftext|>


<commit_before>package graval

import (
	"io"
	"os"
	"time"
)

// For each client that connects to the server, a new FTPDriver is required.
// Create an implementation if this interface and provide it to FTPServer.
type FTPDriverFactory interface {
	NewDriver() (FTPDriver, error)
}

// You will create an implementation of this interface that speaks to your
// chosen persistence layer. graval will create a new instance of your
// driver for each client that connects and delegate to it as required.
type FTPDriver interface {
	// params  - username, password
	// returns - true if the provided details are valid
	Authenticate(string, string) bool

	// params  - a file path
	// returns - an int with the number of bytes in the file or -1 if the file
	//           doesn't exist
	Bytes(string) int64

	// params  - a file path
	// returns - a time indicating when the requested path was last modified
	//         - an ok flag if the file doesn't exist or the user lacks
	//           permissions
	ModifiedTime(string) (time.Time, bool)

	// params  - path
	// returns - true if the current user is permitted to change to the
	//           requested path
	ChangeDir(string) bool

	// params  - path
	// returns - a collection of items describing the contents of the requested
	//           path
	DirContents(string) ([]os.FileInfo, bool)

	// params  - path
	// returns - true if the directory was deleted
	DeleteDir(string) bool

	// params  - path
	// returns - true if the file was deleted
	DeleteFile(string) bool

	// params  - from_path, to_path
	// returns - true if the file was renamed
	Rename(string, string) bool

	// params  - path
	// returns - true if the new directory was created
	MakeDir(string) bool

	// params  - path, position
	// returns - a string containing the file data to send to the client
	GetFile(string, int64) (io.ReadCloser, bool)

	// params  - desination path, an io.Reader containing the file data
	// returns - true if the data was successfully persisted
	PutFile(string, io.Reader) bool
}
<commit_msg>Named parameters for driver interface<commit_after>package graval

import (
	"io"
	"os"
	"time"
)

// For each client that connects to the server, a new FTPDriver is required.
// Create an implementation if this interface and provide it to FTPServer.
type FTPDriverFactory interface {
	NewDriver() (FTPDriver, error)
}

// You will create an implementation of this interface that speaks to your
// chosen persistence layer. graval will create a new instance of your
// driver for each client that connects and delegate to it as required.
type FTPDriver interface {
	// params  - username, password
	// returns - true if the provided details are valid
	Authenticate(username string, password string) bool

	// params  - a file path
	// returns - an int with the number of bytes in the file or -1 if the file
	//           doesn't exist
	Bytes(path string) int64

	// params  - a file path
	// returns - a time indicating when the requested path was last modified
	//         - an ok flag if the file doesn't exist or the user lacks
	//           permissions
	ModifiedTime(path string) (time.Time, bool)

	// params  - path
	// returns - true if the current user is permitted to change to the
	//           requested path
	ChangeDir(path string) bool

	// params  - path
	// returns - a collection of items describing the contents of the requested
	//           path
	DirContents(path string) ([]os.FileInfo, bool)

	// params  - path
	// returns - true if the directory was deleted
	DeleteDir(path string) bool

	// params  - path
	// returns - true if the file was deleted
	DeleteFile(path string) bool

	// params  - from_path, to_path
	// returns - true if the file was renamed
	Rename(from_path string, to_path string) bool

	// params  - path
	// returns - true if the new directory was created
	MakeDir(path string) bool

	// params  - path, position
	// returns - a string containing the file data to send to the client
	GetFile(path string, position int64) (io.ReadCloser, bool)

	// params  - desination path, an io.Reader containing the file data
	// returns - true if the data was successfully persisted
	PutFile(path string, reader io.Reader) bool
}
<|endoftext|>


<commit_before>package funcs

import (
	"sync"

	"github.com/hairyhenderson/gomplate/aws"
)

var (
	af     *Funcs
	afInit sync.Once
)

// AWSNS - the aws namespace
func AWSNS() *Funcs {
	afInit.Do(func() {
		af = &Funcs{
			awsopts: aws.GetClientOptions(),
		}
	})
	return af
}

// AWSFuncs -
func AWSFuncs(f map[string]interface{}) {
	f["aws"] = AWSNS

	// global aliases - for backwards compatibility
	f["ec2meta"] = AWSNS().EC2Meta
	f["ec2dynamic"] = AWSNS().EC2Dynamic
	f["ec2tag"] = AWSNS().EC2Tag
	f["ec2region"] = AWSNS().EC2Region
}

// Funcs -
type Funcs struct {
	meta     *aws.Ec2Meta
	info     *aws.Ec2Info
	kms      *aws.KMS
	metaInit sync.Once
	infoInit sync.Once
	kmsInit  sync.Once
	awsopts  aws.ClientOptions
}

// EC2Region -
func (a *Funcs) EC2Region(def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Region(def...)
}

// EC2Meta -
func (a *Funcs) EC2Meta(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Meta(key, def...)
}

// EC2Dynamic -
func (a *Funcs) EC2Dynamic(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Dynamic(key, def...)
}

// EC2Tag -
func (a *Funcs) EC2Tag(tag string, def ...string) (string, error) {
	a.infoInit.Do(a.initInfo)
	return a.info.Tag(tag, def...)
}

// KMSEncrypt -
func (a *Funcs) KMSEncrypt(keyID, plaintext string) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Encrypt(keyID, plaintext)
}

// KMSDecrypt -
func (a *Funcs) KMSDecrypt(ciphertext string) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Decrypt(ciphertext)
}

func (a *Funcs) initMeta() {
	if a.meta == nil {
		a.meta = aws.NewEc2Meta(a.awsopts)
	}
}

func (a *Funcs) initInfo() {
	if a.info == nil {
		a.info = aws.NewEc2Info(a.awsopts)
	}
}

func (a *Funcs) initKMS() {
	if a.kms == nil {
		a.kms = aws.NewKMS(a.awsopts)
	}
}
<commit_msg>convert input args using gomplate's ToString<commit_after>package funcs

import (
	"sync"

	"github.com/hairyhenderson/gomplate/aws"
	"github.com/hairyhenderson/gomplate/conv"
)

var (
	af     *Funcs
	afInit sync.Once
)

// AWSNS - the aws namespace
func AWSNS() *Funcs {
	afInit.Do(func() {
		af = &Funcs{
			awsopts: aws.GetClientOptions(),
		}
	})
	return af
}

// AWSFuncs -
func AWSFuncs(f map[string]interface{}) {
	f["aws"] = AWSNS

	// global aliases - for backwards compatibility
	f["ec2meta"] = AWSNS().EC2Meta
	f["ec2dynamic"] = AWSNS().EC2Dynamic
	f["ec2tag"] = AWSNS().EC2Tag
	f["ec2region"] = AWSNS().EC2Region
}

// Funcs -
type Funcs struct {
	meta     *aws.Ec2Meta
	info     *aws.Ec2Info
	kms      *aws.KMS
	metaInit sync.Once
	infoInit sync.Once
	kmsInit  sync.Once
	awsopts  aws.ClientOptions
}

// EC2Region -
func (a *Funcs) EC2Region(def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Region(def...)
}

// EC2Meta -
func (a *Funcs) EC2Meta(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Meta(key, def...)
}

// EC2Dynamic -
func (a *Funcs) EC2Dynamic(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Dynamic(key, def...)
}

// EC2Tag -
func (a *Funcs) EC2Tag(tag string, def ...string) (string, error) {
	a.infoInit.Do(a.initInfo)
	return a.info.Tag(tag, def...)
}

// KMSEncrypt -
func (a *Funcs) KMSEncrypt(keyID, plaintext interface{}) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Encrypt(conv.ToString(keyID), conv.ToString(plaintext))
}

// KMSDecrypt -
func (a *Funcs) KMSDecrypt(ciphertext interface{}) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Decrypt(conv.ToString(ciphertext))
}

func (a *Funcs) initMeta() {
	if a.meta == nil {
		a.meta = aws.NewEc2Meta(a.awsopts)
	}
}

func (a *Funcs) initInfo() {
	if a.info == nil {
		a.info = aws.NewEc2Info(a.awsopts)
	}
}

func (a *Funcs) initKMS() {
	if a.kms == nil {
		a.kms = aws.NewKMS(a.awsopts)
	}
}
<|endoftext|>


<commit_before>package funcs

import (
	"sync"

	"github.com/hairyhenderson/gomplate/aws"
)

var (
	af     *Funcs
	afInit sync.Once
)

// AWSNS - the aws namespace
func AWSNS() *Funcs {
	afInit.Do(func() {
		af = &Funcs{
			awsopts: aws.GetClientOptions(),
		}
	})
	return af
}

// AWSFuncs -
func AWSFuncs(f map[string]interface{}) {
	f["aws"] = AWSNS

	// global aliases - for backwards compatibility
	f["ec2meta"] = AWSNS().EC2Meta
	f["ec2dynamic"] = AWSNS().EC2Dynamic
	f["ec2tag"] = AWSNS().EC2Tag
	f["ec2region"] = AWSNS().EC2Region
	f["kmsencrypt"] = AWSNS().KMSEncrypt
	f["kmsdecrypt"] = AWSNS().KMSDecrypt
}

// Funcs -
type Funcs struct {
	meta     *aws.Ec2Meta
	info     *aws.Ec2Info
	kms      *aws.KMS
	metaInit sync.Once
	infoInit sync.Once
	kmsInit  sync.Once
	awsopts  aws.ClientOptions
}

// EC2Region -
func (a *Funcs) EC2Region(def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Region(def...)
}

// EC2Meta -
func (a *Funcs) EC2Meta(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Meta(key, def...)
}

// EC2Dynamic -
func (a *Funcs) EC2Dynamic(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Dynamic(key, def...)
}

// EC2Tag -
func (a *Funcs) EC2Tag(tag string, def ...string) (string, error) {
	a.infoInit.Do(a.initInfo)
	return a.info.Tag(tag, def...)
}

// KMSEncrypt -
func (a *Funcs) KMSEncrypt() {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Ciphertext()
}

// KMSDecrypt -
func (a *Funcs) KMSDecrypt() {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Cleartext()
}

func (a *Funcs) initMeta() {
	if a.meta == nil {
		a.meta = aws.NewEc2Meta(a.awsopts)
	}
}

func (a *Funcs) initInfo() {
	if a.info == nil {
		a.info = aws.NewEc2Info(a.awsopts)
	}
}

func (a *Funcs) initKMS() {
	if a.kms == nil {
		a.kms = aws.NewKMS(a.awsopts)
	}
}
<commit_msg>complete encrypt/decrypt methods<commit_after>package funcs

import (
	"sync"

	"github.com/hairyhenderson/gomplate/aws"
)

var (
	af     *Funcs
	afInit sync.Once
)

// AWSNS - the aws namespace
func AWSNS() *Funcs {
	afInit.Do(func() {
		af = &Funcs{
			awsopts: aws.GetClientOptions(),
		}
	})
	return af
}

// AWSFuncs -
func AWSFuncs(f map[string]interface{}) {
	f["aws"] = AWSNS

	// global aliases - for backwards compatibility
	f["ec2meta"] = AWSNS().EC2Meta
	f["ec2dynamic"] = AWSNS().EC2Dynamic
	f["ec2tag"] = AWSNS().EC2Tag
	f["ec2region"] = AWSNS().EC2Region
	f["kmsencrypt"] = AWSNS().KMSEncrypt
	f["kmsdecrypt"] = AWSNS().KMSDecrypt
}

// Funcs -
type Funcs struct {
	meta     *aws.Ec2Meta
	info     *aws.Ec2Info
	kms      *aws.KMS
	metaInit sync.Once
	infoInit sync.Once
	kmsInit  sync.Once
	awsopts  aws.ClientOptions
}

// EC2Region -
func (a *Funcs) EC2Region(def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Region(def...)
}

// EC2Meta -
func (a *Funcs) EC2Meta(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Meta(key, def...)
}

// EC2Dynamic -
func (a *Funcs) EC2Dynamic(key string, def ...string) (string, error) {
	a.metaInit.Do(a.initMeta)
	return a.meta.Dynamic(key, def...)
}

// EC2Tag -
func (a *Funcs) EC2Tag(tag string, def ...string) (string, error) {
	a.infoInit.Do(a.initInfo)
	return a.info.Tag(tag, def...)
}

// KMSEncrypt -
func (a *Funcs) KMSEncrypt(keyID string, plaintext string) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Ciphertext()
}

// KMSDecrypt -
func (a *Funcs) KMSDecrypt(ciphertext string) (string, error) {
	a.kmsInit.Do(a.initKMS)
	return a.kms.Cleartext()
}

func (a *Funcs) initMeta() {
	if a.meta == nil {
		a.meta = aws.NewEc2Meta(a.awsopts)
	}
}

func (a *Funcs) initInfo() {
	if a.info == nil {
		a.info = aws.NewEc2Info(a.awsopts)
	}
}

func (a *Funcs) initKMS() {
	if a.kms == nil {
		a.kms = aws.NewKMS(a.awsopts)
	}
}
<|endoftext|>


<commit_before>package nomad

import (
	"errors"
	"fmt"
	"testing"

	"github.com/hashicorp/nomad/testutil"
)

func TestLeader_LeftServer(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s2.Shutdown()

	s3 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s3.Shutdown()
	servers := []*Server{s1, s2, s3}
	testJoin(t, s1, s2, s3)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 3, nil
		}, func(err error) {
			t.Fatalf("should have 3 peers")
		})
	}

	// Kill any server
	servers[0].Shutdown()

	testutil.WaitForResult(func() (bool, error) {
		// Force remove the non-leader (transition to left state)
		name := fmt.Sprintf("%s.%s",
			servers[0].config.NodeName, servers[0].config.Region)
		if err := servers[1].RemoveFailedNode(name); err != nil {
			t.Fatalf("err: %v", err)
		}

		for _, s := range servers[1:] {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers))
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})
}

func TestLeader_LeftLeader(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s2.Shutdown()

	s3 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s3.Shutdown()
	servers := []*Server{s1, s2, s3}
	testJoin(t, s1, s2, s3)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 3, nil
		}, func(err error) {
			t.Fatalf("should have 3 peers")
		})
	}

	// Kill the leader!
	var leader *Server
	for _, s := range servers {
		if s.IsLeader() {
			leader = s
			break
		}
	}
	if leader == nil {
		t.Fatalf("Should have a leader")
	}
	leader.Leave()
	leader.Shutdown()

	for _, s := range servers {
		if s == leader {
			continue
		}
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers))
		}, func(err error) {
			t.Fatalf("should have 2 peers: %v", err)
		})
	}
}

func TestLeader_MultiBootstrap(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, nil)
	defer s2.Shutdown()
	servers := []*Server{s1, s2}
	testJoin(t, s1, s2)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers := s.Members()
			return len(peers) == 2, nil
		}, func(err error) {
			t.Fatalf("should have 2 peers")
		})
	}

	// Ensure we don't have multiple raft peers
	for _, s := range servers {
		peers, _ := s.raftPeers.Peers()
		if len(peers) != 1 {
			t.Fatalf("should only have 1 raft peer!")
		}
	}
}
<commit_msg>nomad: test leader enables plan queue<commit_after>package nomad

import (
	"errors"
	"fmt"
	"testing"
	"time"

	"github.com/hashicorp/nomad/testutil"
)

func TestLeader_LeftServer(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s2.Shutdown()

	s3 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s3.Shutdown()
	servers := []*Server{s1, s2, s3}
	testJoin(t, s1, s2, s3)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 3, nil
		}, func(err error) {
			t.Fatalf("should have 3 peers")
		})
	}

	// Kill any server
	servers[0].Shutdown()

	testutil.WaitForResult(func() (bool, error) {
		// Force remove the non-leader (transition to left state)
		name := fmt.Sprintf("%s.%s",
			servers[0].config.NodeName, servers[0].config.Region)
		if err := servers[1].RemoveFailedNode(name); err != nil {
			t.Fatalf("err: %v", err)
		}

		for _, s := range servers[1:] {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers))
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})
}

func TestLeader_LeftLeader(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s2.Shutdown()

	s3 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s3.Shutdown()
	servers := []*Server{s1, s2, s3}
	testJoin(t, s1, s2, s3)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 3, nil
		}, func(err error) {
			t.Fatalf("should have 3 peers")
		})
	}

	// Kill the leader!
	var leader *Server
	for _, s := range servers {
		if s.IsLeader() {
			leader = s
			break
		}
	}
	if leader == nil {
		t.Fatalf("Should have a leader")
	}
	leader.Leave()
	leader.Shutdown()

	for _, s := range servers {
		if s == leader {
			continue
		}
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers))
		}, func(err error) {
			t.Fatalf("should have 2 peers: %v", err)
		})
	}
}

func TestLeader_MultiBootstrap(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, nil)
	defer s2.Shutdown()
	servers := []*Server{s1, s2}
	testJoin(t, s1, s2)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers := s.Members()
			return len(peers) == 2, nil
		}, func(err error) {
			t.Fatalf("should have 2 peers")
		})
	}

	// Ensure we don't have multiple raft peers
	for _, s := range servers {
		peers, _ := s.raftPeers.Peers()
		if len(peers) != 1 {
			t.Fatalf("should only have 1 raft peer!")
		}
	}
}

func TestLeader_PlanQueue_Reset(t *testing.T) {
	s1 := testServer(t, nil)
	defer s1.Shutdown()

	s2 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s2.Shutdown()

	s3 := testServer(t, func(c *Config) {
		c.DevDisableBootstrap = true
	})
	defer s3.Shutdown()
	servers := []*Server{s1, s2, s3}
	testJoin(t, s1, s2, s3)

	for _, s := range servers {
		testutil.WaitForResult(func() (bool, error) {
			peers, _ := s.raftPeers.Peers()
			return len(peers) == 3, nil
		}, func(err error) {
			t.Fatalf("should have 3 peers")
		})
	}

	var leader *Server
	for _, s := range servers {
		if s.IsLeader() {
			leader = s
			break
		}
	}
	if leader == nil {
		t.Fatalf("Should have a leader")
	}

	if !leader.planQueue.Enabled() {
		t.Fatalf("should enable plan queue")
	}

	// Kill the leader
	leader.Shutdown()
	time.Sleep(100 * time.Millisecond)

	// Wait for a new leader
	leader = nil
	testutil.WaitForResult(func() (bool, error) {
		for _, s := range servers {
			if s.IsLeader() {
				leader = s
				return true, nil
			}
		}
		return false, nil
	}, func(err error) {
		t.Fatalf("should have leader")
	})

	// Check that the new leader has a pending GC expiration
	testutil.WaitForResult(func() (bool, error) {
		return leader.planQueue.Enabled(), nil
	}, func(err error) {
		t.Fatalf("should enable plan queue")
	})
}
<|endoftext|>