<commit_before>package main

import (
	"fmt"
	"os"
	"path"
	"gopkg.in/alecthomas/kingpin.v2"
	"io"
	"log"
	"runtime/pprof"
	"github.com/tcw/saxer/histBuffer"
	"github.com/tcw/saxer/nodeBuffer"
	"github.com/tcw/saxer/nodePath"
	"bytes"
)

var (
	pathExp = kingpin.Arg("pathExp", "Sax Path Expression").Required().String()
	filename = kingpin.Arg("xml-file", "file").Required().String()
	cpuProfile = kingpin.Flag("profile", "Profile parser").Short('c').Bool()
)

type StartElement struct {
	buffer   []byte
	position int
}

func main() {
	kingpin.Version("0.0.1")
	kingpin.Parse()

	//go tool pprof --pdf saxer cpu.pprof > callgraph.pdf
	//evince callgraph.pdf
	if *cpuProfile {
		f, err := os.Create("cpu.pprof")
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		fmt.Println("profiling!")
		defer pprof.StopCPUProfile()
	}

	absFilename, err := abs(*filename)
	if err != nil {
		panic(err.Error())
	}
	SaxFile(absFilename)
}

func NewStartElement(bufferSize int) StartElement {
	return StartElement{buffer: make([]byte, bufferSize), position: 0}
}

func SaxFile(filename string) {
	file, err := os.Open(filename)
	if err != nil {
		panic(err.Error())
	}
	defer file.Close()
	emitter := make(chan string)
	go emitterHandler(emitter)
	SaxReader(file, 1024*4, 1024*4, *pathExp,emitter)
}

func emitterHandler(emitter chan string)  {
	for{
		fmt.Println(<-emitter)
	}
}

func SaxReader(reader io.Reader, bufferSize int, tmpNodeBufferSize int, pathQuery string,emitter chan string) {
	startElement := NewStartElement(tmpNodeBufferSize)
	buffer := make([]byte, bufferSize)
	inEscapeMode := false
	history := histBuffer.NewHistoryBuffer(tmpNodeBufferSize)
	nodeBuffer := nodeBuffer.NewNodeBuffer(1024 * 1024,emitter)
	nodePath := nodePath.NewNodePath(1000, pathQuery)
	isRecoding := false
	var lineNumber uint64 = 0
	for {
		n, err := reader.Read(buffer)
		if n != 0 && err != nil {
			panic("Error while reading xml")
		}
		if n == 0 {
			break
		}
		elemStart := -1
		elemStop := -1
		for index := 0; index < n; index++ {
			value := buffer[index]
			if isRecoding {
				nodeBuffer.Add(value)
			}
			if inEscapeMode {
				history.Add(value)
				if value == byte('>') {
					if history.HasLast([]byte{'-', '-', '>'}) {
						inEscapeMode = false
						continue
					}
					if history.HasLast([]byte{']', ']', '>'}) {
						inEscapeMode = false
						continue
					}
				}
				continue
			}
			if value == 0x0A {
				lineNumber++
			}
			if value == byte('<') {
				elemStart = index
			}
			if value == byte('>') {
				elemStop = index
			}
			if ((elemStart != -1 && index != 0 && elemStart == index - 1) && value == byte('!')) ||
			(index == 0 && startElement.position == 1 && value == byte('!')) {
				inEscapeMode = true
				startElement.position = 0
				elemStart = -1
			}else if elemStart != -1 && elemStop != -1 && startElement.position == 0 {
				if elemStart > elemStop {
					panic(fmt.Sprintf("Parsing error at line %d, possible syntax error", lineNumber))
				}
				isRecoding = ElementType(buffer[elemStart:elemStop], &nodeBuffer, &nodePath, isRecoding)
				elemStart = -1
				elemStop = -1
			}else if elemStop != -1 {
				copy(startElement.buffer[startElement.position:], buffer[:elemStop])
				startElement.position = startElement.position + elemStop
				isRecoding = ElementType(startElement.buffer[:startElement.position], &nodeBuffer, &nodePath, isRecoding)
				startElement.position = 0
				elemStop = -1
			}
		}
		if elemStart == -1 && elemStop == -1 && startElement.position > 0 {
			copy(startElement.buffer[startElement.position:], buffer)
			startElement.position = startElement.position + n
		}else if elemStart != -1 {
			copy(startElement.buffer, buffer[elemStart:n])
			startElement.position = startElement.position + (n - elemStart)
		}
	}
}

func ElementType(nodeContent []byte, nodeBuffer *nodeBuffer.NodeBuffer, nodePath *nodePath.NodePath, isRecoding bool) bool {
	if nodeContent[1] == byte('/') {
		if isRecoding {
			if nodePath.MatchesPath() {
				nodeBuffer.Emit()
				nodeBuffer.Reset()
				nodePath.RemoveLast()
				return false
			}else {
				nodePath.RemoveLast()
				return true
			}
		}
		nodePath.RemoveLast()
		return false
	}else if nodeContent[len(nodeContent) - 1] == byte('/') {
		nodePath.Add(getNodeName(nodeContent))
		if nodePath.MatchesPath() {
			if !isRecoding {
				nodeBuffer.AddArray(nodeContent)
				nodeBuffer.Add(byte('>'))
				nodeBuffer.Emit()
				nodeBuffer.Reset()
			}
		}
		nodePath.RemoveLast()
		return false
	}else {
		nodename := getNodeName(nodeContent)
		nodePath.Add(nodename)
		if !isRecoding {
			if nodePath.MatchesPath() {
				nodeBuffer.AddArray(nodeContent)
				nodeBuffer.Add(byte('>'))
				return true
			}else {
				return false
			}
		}else{
			return true
		}
	}
}

func getNodeName(nodeContent []byte) string {
	idx := bytes.IndexByte(nodeContent, byte(' '))
	if idx == -1 {
		return string(nodeContent[1:])
	}else {
		return string(nodeContent[1:idx])
	}
}

func abs(name string) (string, error) {
	if path.IsAbs(name) {
		return name, nil
	}
	wd, err := os.Getwd()
	return path.Join(wd, name), err
}
<commit_msg>Node recoding<commit_after>package main

import (
	"fmt"
	"os"
	"path"
	"gopkg.in/alecthomas/kingpin.v2"
	"io"
	"log"
	"runtime/pprof"
	"github.com/tcw/saxer/histBuffer"
	"github.com/tcw/saxer/nodeBuffer"
	"github.com/tcw/saxer/nodePath"
	"bytes"
)

var (
	pathExp = kingpin.Arg("pathExp", "Sax Path Expression").Required().String()
	filename = kingpin.Arg("xml-file", "file").Required().String()
	cpuProfile = kingpin.Flag("profile", "Profile parser").Short('c').Bool()
)

type StartElement struct {
	buffer   []byte
	position int
}

func main() {
	kingpin.Version("0.0.1")
	kingpin.Parse()

	//go tool pprof --pdf saxer cpu.pprof > callgraph.pdf
	//evince callgraph.pdf
	if *cpuProfile {
		f, err := os.Create("cpu.pprof")
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		fmt.Println("profiling!")
		defer pprof.StopCPUProfile()
	}

	absFilename, err := abs(*filename)
	if err != nil {
		panic(err.Error())
	}
	SaxFile(absFilename)
}

func NewStartElement(bufferSize int) StartElement {
	return StartElement{buffer: make([]byte, bufferSize), position: 0}
}

func SaxFile(filename string) {
	file, err := os.Open(filename)
	if err != nil {
		panic(err.Error())
	}
	defer file.Close()
	emitter := make(chan string,1000)
	go emitterHandler(emitter)
	SaxReader(file, 1024*4, 1024*4, *pathExp,emitter)
}

func emitterHandler(emitter chan string)  {
	for{
		fmt.Println(<-emitter)
	}
}

func SaxReader(reader io.Reader, bufferSize int, tmpNodeBufferSize int, pathQuery string,emitter chan string) {
	startElement := NewStartElement(tmpNodeBufferSize)
	buffer := make([]byte, bufferSize)
	inEscapeMode := false
	history := histBuffer.NewHistoryBuffer(tmpNodeBufferSize)
	nodeBuffer := nodeBuffer.NewNodeBuffer(1024 * 1024,emitter)
	nodePath := nodePath.NewNodePath(1000, pathQuery)
	isRecoding := false
	var lineNumber uint64 = 0
	for {
		n, err := reader.Read(buffer)
		if n != 0 && err != nil {
			panic("Error while reading xml")
		}
		if n == 0 {
			break
		}
		elemStart := -1
		elemStop := -1
		for index := 0; index < n; index++ {
			value := buffer[index]
			if isRecoding {
				nodeBuffer.Add(value)
			}
			if inEscapeMode {
				history.Add(value)
				if value == byte('>') {
					if history.HasLast([]byte{'-', '-', '>'}) {
						inEscapeMode = false
						continue
					}
					if history.HasLast([]byte{']', ']', '>'}) {
						inEscapeMode = false
						continue
					}
				}
				continue
			}
			if value == 0x0A {
				lineNumber++
			}
			if value == byte('<') {
				elemStart = index
			}
			if value == byte('>') {
				elemStop = index
			}
			if ((elemStart != -1 && index != 0 && elemStart == index - 1) && value == byte('!')) ||
			(index == 0 && startElement.position == 1 && value == byte('!')) {
				inEscapeMode = true
				startElement.position = 0
				elemStart = -1
			}else if elemStart != -1 && elemStop != -1 && startElement.position == 0 {
				if elemStart > elemStop {
					panic(fmt.Sprintf("Parsing error at line %d, possible syntax error", lineNumber))
				}
				isRecoding = ElementType(buffer[elemStart:elemStop], &nodeBuffer, &nodePath, isRecoding)
				elemStart = -1
				elemStop = -1
			}else if elemStop != -1 {
				copy(startElement.buffer[startElement.position:], buffer[:elemStop])
				startElement.position = startElement.position + elemStop
				isRecoding = ElementType(startElement.buffer[:startElement.position], &nodeBuffer, &nodePath, isRecoding)
				startElement.position = 0
				elemStop = -1
			}
		}
		if elemStart == -1 && elemStop == -1 && startElement.position > 0 {
			copy(startElement.buffer[startElement.position:], buffer)
			startElement.position = startElement.position + n
		}else if elemStart != -1 {
			copy(startElement.buffer, buffer[elemStart:n])
			startElement.position = startElement.position + (n - elemStart)
		}
	}
}

func ElementType(nodeContent []byte, nodeBuffer *nodeBuffer.NodeBuffer, nodePath *nodePath.NodePath, isRecoding bool) bool {
	if nodeContent[1] == byte('/') {
		if isRecoding {
			if nodePath.MatchesPath() {
				nodeBuffer.Emit()
				nodeBuffer.Reset()
				nodePath.RemoveLast()
				return false
			}else {
				nodePath.RemoveLast()
				return true
			}
		}
		nodePath.RemoveLast()
		return false
	}else if nodeContent[len(nodeContent) - 1] == byte('/') {
		nodePath.Add(getNodeName(nodeContent))
		if nodePath.MatchesPath() {
			if !isRecoding {
				nodeBuffer.AddArray(nodeContent)
				nodeBuffer.Add(byte('>'))
				nodeBuffer.Emit()
				nodeBuffer.Reset()
			}
		}
		nodePath.RemoveLast()
		return false
	}else {
		nodename := getNodeName(nodeContent)
		nodePath.Add(nodename)
		if !isRecoding {
			if nodePath.MatchesPath() {
				nodeBuffer.AddArray(nodeContent)
				nodeBuffer.Add(byte('>'))
				return true
			}else {
				return false
			}
		}else{
			return true
		}
	}
}

func getNodeName(nodeContent []byte) string {
	idx := bytes.IndexByte(nodeContent, byte(' '))
	if idx == -1 {
		return string(nodeContent[1:])
	}else {
		return string(nodeContent[1:idx])
	}
}

func abs(name string) (string, error) {
	if path.IsAbs(name) {
		return name, nil
	}
	wd, err := os.Getwd()
	return path.Join(wd, name), err
}
<|endoftext|>


<commit_before>package cli

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise-machine/config"
	"github.com/bitrise-io/bitrise-machine/utils"
	"github.com/codegangsta/cli"
)

const (
	logChunkRuneLenght = 100

	// LogFormatJSON ...
	LogFormatJSON = "json"
)

// RunResults ...
type RunResults struct {
	IsTimeoutError bool
	RunError       error
}

// LogBuffer ...
type LogBuffer struct {
	logBytes bytes.Buffer
	rwlock   sync.RWMutex
}

// Write ...
func (buff *LogBuffer) Write(p []byte) (n int, err error) {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	return buff.logBytes.Write(p)
}

func (buff *LogBuffer) Read(n int) []byte {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	return buff.logBytes.Next(n)
}

// ReadRunes ...
func (buff *LogBuffer) ReadRunes(n int) (string, bool) {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	res := ""
	isEOF := false
	for i := 0; i < n; i++ {
		r, _, err := buff.logBytes.ReadRune()
		if err == nil {
			res += string(r)
		} else if err == io.EOF {
			isEOF = true
			break
		} else {
			log.Errorf("Failed to read from LogBuffer: %s", err)
		}
	}
	return res, isEOF
}

// LogChunkModel ...
type LogChunkModel struct {
	Data string `json:"data"`
	Pos  int64  `json:"pos"`
}

func logChunkJSONTransform(logChunkData string, logChunkIdx int64) ([]byte, error) {
	logChunk := LogChunkModel{
		Data: logChunkData,
		Pos:  logChunkIdx,
	}
	return json.Marshal(logChunk)
}

func performRun(sshConfig config.SSHConfigModel, commandToRunStr string, timeoutSeconds int64, logFormat string) RunResults {
	logBuff := LogBuffer{}
	var logChunkIndex int64
	lastLogChunkSentAt := time.Now()

	// Log processing
	processLogs := func(isFlush bool) (isLogChunkGenerated bool) {
		for {
			isChunkDone := false
			if logBuff.logBytes.Len() > logChunkRuneLenght || isFlush {
				chunkStr, isEOF := logBuff.ReadRunes(logChunkRuneLenght)
				if chunkStr != "" {
					if logFormat == LogFormatJSON {
						logChunkBytes, err := logChunkJSONTransform(chunkStr, logChunkIndex)
						logChunkIndex++
						if err != nil {
							log.Errorf("Failed to convert log chunk. Error: %s", err)
							log.Errorf(" Log chunk was: %s", chunkStr)
						}
						fmt.Printf("%s\n", logChunkBytes)
					} else {
						fmt.Printf("%s", chunkStr)
					}
					isLogChunkGenerated = true
				}
				if isEOF {
					isChunkDone = true
				}
			} else {
				isChunkDone = true
			}

			if !isFlush || isChunkDone {
				break
			}
		}
		return
	}

	// Run
	isRunFinished := false
	runRes := RunResults{
		IsTimeoutError: false,
		RunError:       nil,
	}
	c1 := make(chan RunResults, 1)
	go func() {
		if err := utils.RunCommandThroughSSHWithWriters(sshConfig, commandToRunStr, &logBuff, &logBuff); err != nil {
			log.Errorf("Failed to run command, error: %s", err)
			c1 <- RunResults{RunError: err, IsTimeoutError: false}
		} else {
			c1 <- RunResults{RunError: nil, IsTimeoutError: false}
		}
	}()

	var timeoutTriggerred <-chan time.Time
	if timeoutSeconds > 0 {
		log.Infof("Timeout registered with %d seconds from now.", timeoutSeconds)
		timeoutTriggerred = time.After(time.Duration(timeoutSeconds) * time.Second)
	}

	for !isRunFinished {
		select {
		case res := <-c1:
			if res.RunError == nil {
				runRes = res
			} else {
				runRes = res
			}
			isRunFinished = true
		case <-timeoutTriggerred:
			runRes = RunResults{RunError: fmt.Errorf("Timeout after %d seconds", timeoutSeconds), IsTimeoutError: true}
			isRunFinished = true
		case <-time.Tick(100 * time.Millisecond):
			isFlushLogs := false
			// force flush logs if we did not generated log chunks in the last
			//  couple of seconds - if the process did not generate enough logs
			//  to trigger a chunk generation
			timeDiffSec := time.Now().Sub(lastLogChunkSentAt).Seconds()
			if timeDiffSec > 5.0 {
				isFlushLogs = true
			}
			if processLogs(isFlushLogs) || isFlushLogs {
				lastLogChunkSentAt = time.Now()
			}
		}
	}

	processLogs(true)

	return runRes
}

func run(c *cli.Context) {
	log.Infoln("Run")

	if len(c.Args()) < 1 {
		log.Fatalln("No command to run specified!")
	}

	inCmdArgs := c.Args()
	cmdToRun := inCmdArgs[0]
	cmdToRunArgs := []string{}
	if len(inCmdArgs) > 1 {
		cmdToRunArgs = inCmdArgs[1:]
	}

	sshConfigModel, err := config.ReadSSHConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalln("Failed to read SSH configs - you should probably call 'setup' first!")
	}

	fullCmdToRunStr := fmt.Sprintf("%s %s", cmdToRun, strings.Join(cmdToRunArgs, " "))
	log.Infoln("fullCmdToRunStr: ", fullCmdToRunStr)

	timeoutSecs := c.Int(TimeoutFlagKey)
	if timeoutSecs > 0 {
		log.Infof("Timeout parameter: %d seconds", timeoutSecs)
	} else {
		log.Infoln("No timeout defined.")
		timeoutSecs = 0
	}

	logFormat := c.String(LogFormatFlagKey)
	if logFormat == "json" {
		log.Infof("Log format: %s", logFormat)
	} else {
		if logFormat != "" {
			log.Infof("Invalid Log Format - ignoring: %s", logFormat)
		}
		logFormat = ""
	}

	runResult := performRun(sshConfigModel, fullCmdToRunStr, int64(timeoutSecs), logFormat)
	if runResult.RunError != nil {
		if runResult.IsTimeoutError {
			log.Errorf("[!] Timeout: %s", runResult.RunError)
			os.Exit(2)
		} else {
			log.Errorf("Run failed: %s", runResult.RunError)
			os.Exit(1)
		}
	}

	log.Infoln("Run finished - OK")
}
<commit_msg>logChunk size optimization & special exit codes are now available as constant vars<commit_after>package cli

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise-machine/config"
	"github.com/bitrise-io/bitrise-machine/utils"
	"github.com/codegangsta/cli"
)

const (
	logChunkRuneLenght             = 10000 // ~ 10 KB
	buildFinishedWithErrorExitCode = 10
	buildAbortedByTimeoutExitCode  = 2

	// LogFormatJSON ...
	LogFormatJSON = "json"
)

// RunResults ...
type RunResults struct {
	IsTimeoutError bool
	RunError       error
}

// LogBuffer ...
type LogBuffer struct {
	logBytes bytes.Buffer
	rwlock   sync.RWMutex
}

// Write ...
func (buff *LogBuffer) Write(p []byte) (n int, err error) {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	return buff.logBytes.Write(p)
}

func (buff *LogBuffer) Read(n int) []byte {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	return buff.logBytes.Next(n)
}

// ReadRunes ...
func (buff *LogBuffer) ReadRunes(n int) (string, bool) {
	buff.rwlock.Lock()
	defer buff.rwlock.Unlock()
	res := ""
	isEOF := false
	for i := 0; i < n; i++ {
		r, _, err := buff.logBytes.ReadRune()
		if err == nil {
			res += string(r)
		} else if err == io.EOF {
			isEOF = true
			break
		} else {
			log.Errorf("Failed to read from LogBuffer: %s", err)
		}
	}
	return res, isEOF
}

// LogChunkModel ...
type LogChunkModel struct {
	Data string `json:"data"`
	Pos  int64  `json:"pos"`
}

func logChunkJSONTransform(logChunkData string, logChunkIdx int64) ([]byte, error) {
	logChunk := LogChunkModel{
		Data: logChunkData,
		Pos:  logChunkIdx,
	}
	return json.Marshal(logChunk)
}

func performRun(sshConfig config.SSHConfigModel, commandToRunStr string, timeoutSeconds int64, logFormat string) RunResults {
	logBuff := LogBuffer{}
	var logChunkIndex int64
	lastLogChunkSentAt := time.Now()

	// Log processing
	processLogs := func(isFlush bool) (isLogChunkGenerated bool) {
		for {
			isChunkDone := false
			if logBuff.logBytes.Len() > logChunkRuneLenght || isFlush {
				chunkStr, isEOF := logBuff.ReadRunes(logChunkRuneLenght)
				if chunkStr != "" {
					if logFormat == LogFormatJSON {
						logChunkBytes, err := logChunkJSONTransform(chunkStr, logChunkIndex)
						logChunkIndex++
						if err != nil {
							log.Errorf("Failed to convert log chunk. Error: %s", err)
							log.Errorf(" Log chunk was: %s", chunkStr)
						}
						fmt.Printf("%s\n", logChunkBytes)
					} else {
						fmt.Printf("%s", chunkStr)
					}
					isLogChunkGenerated = true
				}
				if isEOF {
					isChunkDone = true
				}
			} else {
				isChunkDone = true
			}

			if !isFlush || isChunkDone {
				break
			}
		}
		return
	}

	// Run
	isRunFinished := false
	runRes := RunResults{
		IsTimeoutError: false,
		RunError:       nil,
	}
	c1 := make(chan RunResults, 1)
	go func() {
		if err := utils.RunCommandThroughSSHWithWriters(sshConfig, commandToRunStr, &logBuff, &logBuff); err != nil {
			log.Errorf("Failed to run command, error: %s", err)
			c1 <- RunResults{RunError: err, IsTimeoutError: false}
		} else {
			c1 <- RunResults{RunError: nil, IsTimeoutError: false}
		}
	}()

	var timeoutTriggerred <-chan time.Time
	if timeoutSeconds > 0 {
		log.Infof("Timeout registered with %d seconds from now.", timeoutSeconds)
		timeoutTriggerred = time.After(time.Duration(timeoutSeconds) * time.Second)
	}

	for !isRunFinished {
		select {
		case res := <-c1:
			if res.RunError == nil {
				runRes = res
			} else {
				runRes = res
			}
			isRunFinished = true
		case <-timeoutTriggerred:
			runRes = RunResults{RunError: fmt.Errorf("Timeout after %d seconds", timeoutSeconds), IsTimeoutError: true}
			isRunFinished = true
		case <-time.Tick(100 * time.Millisecond):
			isFlushLogs := false
			// force flush logs if we did not generated log chunks in the last
			//  couple of seconds - if the process did not generate enough logs
			//  to trigger a chunk generation
			timeDiffSec := time.Now().Sub(lastLogChunkSentAt).Seconds()
			if timeDiffSec > 5.0 {
				isFlushLogs = true
			}
			if processLogs(isFlushLogs) || isFlushLogs {
				lastLogChunkSentAt = time.Now()
			}
		}
	}

	processLogs(true)

	return runRes
}

func run(c *cli.Context) {
	log.Infoln("Run")

	if len(c.Args()) < 1 {
		log.Fatalln("No command to run specified!")
	}

	inCmdArgs := c.Args()
	cmdToRun := inCmdArgs[0]
	cmdToRunArgs := []string{}
	if len(inCmdArgs) > 1 {
		cmdToRunArgs = inCmdArgs[1:]
	}

	sshConfigModel, err := config.ReadSSHConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalln("Failed to read SSH configs - you should probably call 'setup' first!")
	}

	fullCmdToRunStr := fmt.Sprintf("%s %s", cmdToRun, strings.Join(cmdToRunArgs, " "))
	log.Infoln("fullCmdToRunStr: ", fullCmdToRunStr)

	timeoutSecs := c.Int(TimeoutFlagKey)
	if timeoutSecs > 0 {
		log.Infof("Timeout parameter: %d seconds", timeoutSecs)
	} else {
		log.Infoln("No timeout defined.")
		timeoutSecs = 0
	}

	logFormat := c.String(LogFormatFlagKey)
	if logFormat == "json" {
		log.Infof("Log format: %s", logFormat)
	} else {
		if logFormat != "" {
			log.Infof("Invalid Log Format - ignoring: %s", logFormat)
		}
		logFormat = ""
	}

	runResult := performRun(sshConfigModel, fullCmdToRunStr, int64(timeoutSecs), logFormat)
	if runResult.RunError != nil {
		if runResult.IsTimeoutError {
			log.Errorf("[!] Timeout: %s", runResult.RunError)
			os.Exit(buildAbortedByTimeoutExitCode)
		} else {
			log.Errorf("Run failed: %s", runResult.RunError)
			os.Exit(buildFinishedWithErrorExitCode)
		}
	}

	log.Infoln("Run finished - OK")
}
<|endoftext|>


<commit_before>package edn

import "fmt"

// A lot of this is based on: http://cuddle.googlecode.com/hg/talk/lex.html

type tokenType int

const (
	tEOF tokenType = 1 << iota
	tOpenParen
	tCloseParen
	tOpenBrace
	tCloseBrace
	tOpenBracket
	tCloseBracket
	tSingleQuote
	tDoubleQuote
	tSymbol
	tKeyword
	tString
	tNumber
	tWhitespace // needed?
	tComment    // needed?

	tError
)

type stateFn func(*lexer) stateFn

type token struct {
	kind  tokenType
	value string
}

func (t *token) String() string {
	switch t.kind {
	case tEOF:
		return "EOF"
	case tError:
		return t.value
	default:
		return fmt.Sprintf("%q", t.value)
	}

	panic("unreachable")
}

type lexer struct {
	input    string
	start    int
	position int
	tokens   chan token
}

// Lexer states:
func lex(l *lexer) stateFn {
	l.emit(tEOF)
	return nil
}

func (l *lexer) run() {
	for t := lex; t != nil; {
		t = t(l)
	}

	close(l.tokens)
}

func (l *lexer) emit(tt tokenType) {
	value := l.input[l.start:l.position]
	l.start = l.position
	l.tokens <- token{kind: tt, value: value}
}

func (l *lexer) Next() (t token, more bool) {
	t, more = <-l.tokens
	return
}

func Lex(input string) *lexer {
	l := &lexer{
		input:  input,
		tokens: make(chan token, 100),
	}

	go l.run()
	return l
}
<commit_msg>Refactor to put lexer funcs in a map<commit_after>package edn

import "fmt"
import "strings"

// A lot of this is based on: http://cuddle.googlecode.com/hg/talk/lex.html

type tokenType int

const (
	tEOF tokenType = 1 << iota
	tOpenParen
	tCloseParen
	tOpenBrace
	tCloseBrace
	tOpenBracket
	tCloseBracket
	tSingleQuote
	tDoubleQuote
	tSymbol
	tKeyword
	tString
	tNumber
	tWhitespace // needed?
	tComment    // needed?

	tError
)

type token struct {
	kind  tokenType
	value string
}

func (t *token) String() string {
	switch t.kind {
	case tEOF:
		return "EOF"
	case tError:
		return t.value
	default:
		return fmt.Sprintf("%q", t.value)
	}

	panic("unreachable")
}

type lexer struct {
	input    string
	reader   *strings.Reader
	start    int
	position int
	tokens   chan token
}

type stateFn func(*lexer) stateFn

var stateFns map[string]stateFn = map[string]stateFn{
	"start": func(l *lexer) stateFn {
		l.emit(tEOF)
		return nil
	},
}

func (l *lexer) run() {
	for t := stateFns["start"]; t != nil; {
		t = t(l)
	}

	close(l.tokens)
}

func (l *lexer) emit(tt tokenType) {
	value := l.input[l.start:l.position]
	l.start = l.position
	l.tokens <- token{kind: tt, value: value}
}

func (l *lexer) Next() (t token, more bool) {
	t, more = <-l.tokens
	return
}

func Lex(input string) *lexer {
	l := &lexer{
		input:  input,
		reader: strings.NewReader(input),
		tokens: make(chan token, 100),
	}

	go l.run()
	return l
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 tcsclient

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aws/amazon-ecs-agent/agent/stats"
	"github.com/aws/amazon-ecs-agent/agent/tcs/model/ecstcs"
	"github.com/aws/amazon-ecs-agent/agent/utils"
	"github.com/aws/amazon-ecs-agent/agent/wsclient"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/cihub/seelog"
	"github.com/gorilla/websocket"
)

// tasksInMessage is the maximum number of tasks that can be sent in a message to the backend
// This is a very conservative estimate assuming max allowed string lengths for all fields.
const tasksInMessage = 10

// clientServer implements wsclient.ClientServer interface for metrics backend.
type clientServer struct {
	statsEngine            stats.Engine
	publishTicker          *time.Ticker
	endPublish             chan struct{}
	publishMetricsInterval time.Duration
	wsclient.ClientServerImpl
}

// New returns a client/server to bidirectionally communicate with the backend.
// The returned struct should have both 'Connect' and 'Serve' called upon it
// before being used.
func New(url string, region string, credentialProvider *credentials.Credentials, acceptInvalidCert bool, statsEngine stats.Engine, publishMetricsInterval time.Duration) wsclient.ClientServer {
	cs := &clientServer{
		statsEngine:            statsEngine,
		publishTicker:          nil,
		publishMetricsInterval: publishMetricsInterval,
	}
	cs.URL = url
	cs.Region = region
	cs.CredentialProvider = credentialProvider
	cs.AcceptInvalidCert = acceptInvalidCert
	cs.ServiceError = &tcsError{}
	cs.RequestHandlers = make(map[string]wsclient.RequestHandler)
	cs.TypeDecoder = &TcsDecoder{}
	return cs
}

// Serve begins serving requests using previously registered handlers (see
// AddRequestHandler). All request handlers should be added prior to making this
// call as unhandled requests will be discarded.
func (cs *clientServer) Serve() error {
	seelog.Debug("TCS client starting websocket poll loop")
	if cs.Conn == nil {
		return fmt.Errorf("nil connection")
	}

	if cs.statsEngine == nil {
		return fmt.Errorf("uninitialized stats engine")
	}

	// Start the timer function to publish metrics to the backend.
	cs.publishTicker = time.NewTicker(cs.publishMetricsInterval)
	cs.endPublish = make(chan struct{})
	go cs.publishMetrics()

	return cs.ConsumeMessages()
}

// MakeRequest makes a request using the given input. Note, the input *MUST* be
// a pointer to a valid backend type that this client recognises
func (cs *clientServer) MakeRequest(input interface{}) error {
	payload, err := cs.CreateRequestMessage(input)
	if err != nil {
		return err
	}

	seelog.Debug("TCS client sending payload: %s", string(payload))
	data := cs.signRequest(payload)

	// Over the wire we send something like
	// {"type":"AckRequest","message":{"messageId":"xyz"}}
	return cs.Conn.WriteMessage(websocket.TextMessage, data)
}

func (cs *clientServer) signRequest(payload []byte) []byte {
	reqBody := bytes.NewBuffer(payload)
	// NewRequest never returns an error if the url parses and we just verified
	// it did above
	request, _ := http.NewRequest("GET", cs.URL, reqBody)
	utils.SignHTTPRequest(request, cs.Region, "ecs", cs.CredentialProvider, aws.ReadSeekCloser(reqBody))

	request.Header.Add("Host", request.Host)
	var dataBuffer bytes.Buffer
	request.Header.Write(&dataBuffer)
	io.WriteString(&dataBuffer, "\r\n")

	data := dataBuffer.Bytes()
	data = append(data, payload...)

	return data
}

// Close closes the underlying connection.
func (cs *clientServer) Close() error {
	if cs.publishTicker != nil {
		cs.publishTicker.Stop()
		cs.endPublish <- struct{}{}
	}

	return cs.Disconnect()
}

// publishMetrics invokes the PublishMetricsRequest on the clientserver object.
func (cs *clientServer) publishMetrics() {
	if cs.publishTicker == nil {
		seelog.Debug("Skipping publishing metrics. Publish ticker is uninitialized")
		return
	}

	// Publish metrics immediately after we connect and wait for ticks. This makes
	// sure that there is no data loss when a scheduled metrics publishing fails
	// due to a connection reset.
	cs.publishMetricsOnce()
	// don't simply range over the ticker since its channel doesn't ever get closed
	for {
		select {
		case <-cs.publishTicker.C:
			cs.publishMetricsOnce()
		case <-cs.endPublish:
			return
		}
	}
}

// publishMetricsOnce is invoked by the ticker to periodically publish metrics to backend.
func (cs *clientServer) publishMetricsOnce() {
	// Get the list of objects to send to backend.
	requests, err := cs.metricsToPublishMetricRequests()
	if err != nil {
		seelog.Warnf("Error getting instance metrics: %v", err)
	}

	// Make the publish metrics request to the backend.
	for _, request := range requests {
		err = cs.MakeRequest(request)
		if err != nil {
			seelog.Warnf("Error publishing metrics: %v. Request: %v", err, request)
		}
	}
}

// metricsToPublishMetricRequests gets task metrics and converts them to a list of PublishMetricRequest
// objects.
func (cs *clientServer) metricsToPublishMetricRequests() ([]*ecstcs.PublishMetricsRequest, error) {
	metadata, taskMetrics, err := cs.statsEngine.GetInstanceMetrics()
	if err != nil {
		return nil, err
	}

	var requests []*ecstcs.PublishMetricsRequest
	if *metadata.Idle {
		metadata.Fin = aws.Bool(true)
		// Idle instance, we have only one request to send to backend.
		requests = append(requests, ecstcs.NewPublishMetricsRequest(metadata, taskMetrics))
		return requests, nil
	}
	var messageTaskMetrics []*ecstcs.TaskMetric
	numTasks := len(taskMetrics)

	for i, taskMetric := range taskMetrics {
		messageTaskMetrics = append(messageTaskMetrics, taskMetric)
		var requestMetadata *ecstcs.MetricsMetadata
		if (i + 1) == numTasks {
			// If this is the last task to send, set fin to true
			requestMetadata = copyMetricsMetadata(metadata, true)
		} else {
			requestMetadata = copyMetricsMetadata(metadata, false)
		}
		if (i+1)%tasksInMessage == 0 {
			// Construct payload with tasksInMessage number of task metrics and send to backend.
			requests = append(requests, ecstcs.NewPublishMetricsRequest(requestMetadata, copyTaskMetrics(messageTaskMetrics)))
			messageTaskMetrics = messageTaskMetrics[:0]
		}
	}

	if len(messageTaskMetrics) > 0 {
		// Create the new metadata object and set fin to true as this is the last message in the payload.
		requestMetadata := copyMetricsMetadata(metadata, true)
		// Create a request with remaining task metrics.
		requests = append(requests, ecstcs.NewPublishMetricsRequest(requestMetadata, messageTaskMetrics))
	}
	return requests, nil
}

// copyMetricsMetadata creates a new MetricsMetadata object from a given MetricsMetadata object.
// It copies all the fields from the source object to the new object and sets the 'Fin' field
// as specified by the argument.
func copyMetricsMetadata(metadata *ecstcs.MetricsMetadata, fin bool) *ecstcs.MetricsMetadata {
	return &ecstcs.MetricsMetadata{
		Cluster:           aws.String(*metadata.Cluster),
		ContainerInstance: aws.String(*metadata.ContainerInstance),
		Idle:              aws.Bool(*metadata.Idle),
		MessageId:         aws.String(*metadata.MessageId),
		Fin:               aws.Bool(fin),
	}
}

// copyTaskMetrics copies a slice of TaskMetric objects to another slice. This is needed as we
// reset the source slice after creating a new PublishMetricsRequest object.
func copyTaskMetrics(from []*ecstcs.TaskMetric) []*ecstcs.TaskMetric {
	to := make([]*ecstcs.TaskMetric, len(from))
	copy(to, from)
	return to
}
<commit_msg>tcs: Fix payload log message<commit_after>// Copyright 2014-2016 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 tcsclient

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aws/amazon-ecs-agent/agent/stats"
	"github.com/aws/amazon-ecs-agent/agent/tcs/model/ecstcs"
	"github.com/aws/amazon-ecs-agent/agent/utils"
	"github.com/aws/amazon-ecs-agent/agent/wsclient"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/cihub/seelog"
	"github.com/gorilla/websocket"
)

// tasksInMessage is the maximum number of tasks that can be sent in a message to the backend
// This is a very conservative estimate assuming max allowed string lengths for all fields.
const tasksInMessage = 10

// clientServer implements wsclient.ClientServer interface for metrics backend.
type clientServer struct {
	statsEngine            stats.Engine
	publishTicker          *time.Ticker
	endPublish             chan struct{}
	publishMetricsInterval time.Duration
	wsclient.ClientServerImpl
}

// New returns a client/server to bidirectionally communicate with the backend.
// The returned struct should have both 'Connect' and 'Serve' called upon it
// before being used.
func New(url string, region string, credentialProvider *credentials.Credentials, acceptInvalidCert bool, statsEngine stats.Engine, publishMetricsInterval time.Duration) wsclient.ClientServer {
	cs := &clientServer{
		statsEngine:            statsEngine,
		publishTicker:          nil,
		publishMetricsInterval: publishMetricsInterval,
	}
	cs.URL = url
	cs.Region = region
	cs.CredentialProvider = credentialProvider
	cs.AcceptInvalidCert = acceptInvalidCert
	cs.ServiceError = &tcsError{}
	cs.RequestHandlers = make(map[string]wsclient.RequestHandler)
	cs.TypeDecoder = &TcsDecoder{}
	return cs
}

// Serve begins serving requests using previously registered handlers (see
// AddRequestHandler). All request handlers should be added prior to making this
// call as unhandled requests will be discarded.
func (cs *clientServer) Serve() error {
	seelog.Debug("TCS client starting websocket poll loop")
	if cs.Conn == nil {
		return fmt.Errorf("nil connection")
	}

	if cs.statsEngine == nil {
		return fmt.Errorf("uninitialized stats engine")
	}

	// Start the timer function to publish metrics to the backend.
	cs.publishTicker = time.NewTicker(cs.publishMetricsInterval)
	cs.endPublish = make(chan struct{})
	go cs.publishMetrics()

	return cs.ConsumeMessages()
}

// MakeRequest makes a request using the given input. Note, the input *MUST* be
// a pointer to a valid backend type that this client recognises
func (cs *clientServer) MakeRequest(input interface{}) error {
	payload, err := cs.CreateRequestMessage(input)
	if err != nil {
		return err
	}

	seelog.Debugf("TCS client sending payload: %s", string(payload))
	data := cs.signRequest(payload)

	// Over the wire we send something like
	// {"type":"AckRequest","message":{"messageId":"xyz"}}
	return cs.Conn.WriteMessage(websocket.TextMessage, data)
}

func (cs *clientServer) signRequest(payload []byte) []byte {
	reqBody := bytes.NewBuffer(payload)
	// NewRequest never returns an error if the url parses and we just verified
	// it did above
	request, _ := http.NewRequest("GET", cs.URL, reqBody)
	utils.SignHTTPRequest(request, cs.Region, "ecs", cs.CredentialProvider, aws.ReadSeekCloser(reqBody))

	request.Header.Add("Host", request.Host)
	var dataBuffer bytes.Buffer
	request.Header.Write(&dataBuffer)
	io.WriteString(&dataBuffer, "\r\n")

	data := dataBuffer.Bytes()
	data = append(data, payload...)

	return data
}

// Close closes the underlying connection.
func (cs *clientServer) Close() error {
	if cs.publishTicker != nil {
		cs.publishTicker.Stop()
		cs.endPublish <- struct{}{}
	}

	return cs.Disconnect()
}

// publishMetrics invokes the PublishMetricsRequest on the clientserver object.
func (cs *clientServer) publishMetrics() {
	if cs.publishTicker == nil {
		seelog.Debug("Skipping publishing metrics. Publish ticker is uninitialized")
		return
	}

	// Publish metrics immediately after we connect and wait for ticks. This makes
	// sure that there is no data loss when a scheduled metrics publishing fails
	// due to a connection reset.
	cs.publishMetricsOnce()
	// don't simply range over the ticker since its channel doesn't ever get closed
	for {
		select {
		case <-cs.publishTicker.C:
			cs.publishMetricsOnce()
		case <-cs.endPublish:
			return
		}
	}
}

// publishMetricsOnce is invoked by the ticker to periodically publish metrics to backend.
func (cs *clientServer) publishMetricsOnce() {
	// Get the list of objects to send to backend.
	requests, err := cs.metricsToPublishMetricRequests()
	if err != nil {
		seelog.Warnf("Error getting instance metrics: %v", err)
	}

	// Make the publish metrics request to the backend.
	for _, request := range requests {
		err = cs.MakeRequest(request)
		if err != nil {
			seelog.Warnf("Error publishing metrics: %v. Request: %v", err, request)
		}
	}
}

// metricsToPublishMetricRequests gets task metrics and converts them to a list of PublishMetricRequest
// objects.
func (cs *clientServer) metricsToPublishMetricRequests() ([]*ecstcs.PublishMetricsRequest, error) {
	metadata, taskMetrics, err := cs.statsEngine.GetInstanceMetrics()
	if err != nil {
		return nil, err
	}

	var requests []*ecstcs.PublishMetricsRequest
	if *metadata.Idle {
		metadata.Fin = aws.Bool(true)
		// Idle instance, we have only one request to send to backend.
		requests = append(requests, ecstcs.NewPublishMetricsRequest(metadata, taskMetrics))
		return requests, nil
	}
	var messageTaskMetrics []*ecstcs.TaskMetric
	numTasks := len(taskMetrics)

	for i, taskMetric := range taskMetrics {
		messageTaskMetrics = append(messageTaskMetrics, taskMetric)
		var requestMetadata *ecstcs.MetricsMetadata
		if (i + 1) == numTasks {
			// If this is the last task to send, set fin to true
			requestMetadata = copyMetricsMetadata(metadata, true)
		} else {
			requestMetadata = copyMetricsMetadata(metadata, false)
		}
		if (i+1)%tasksInMessage == 0 {
			// Construct payload with tasksInMessage number of task metrics and send to backend.
			requests = append(requests, ecstcs.NewPublishMetricsRequest(requestMetadata, copyTaskMetrics(messageTaskMetrics)))
			messageTaskMetrics = messageTaskMetrics[:0]
		}
	}

	if len(messageTaskMetrics) > 0 {
		// Create the new metadata object and set fin to true as this is the last message in the payload.
		requestMetadata := copyMetricsMetadata(metadata, true)
		// Create a request with remaining task metrics.
		requests = append(requests, ecstcs.NewPublishMetricsRequest(requestMetadata, messageTaskMetrics))
	}
	return requests, nil
}

// copyMetricsMetadata creates a new MetricsMetadata object from a given MetricsMetadata object.
// It copies all the fields from the source object to the new object and sets the 'Fin' field
// as specified by the argument.
func copyMetricsMetadata(metadata *ecstcs.MetricsMetadata, fin bool) *ecstcs.MetricsMetadata {
	return &ecstcs.MetricsMetadata{
		Cluster:           aws.String(*metadata.Cluster),
		ContainerInstance: aws.String(*metadata.ContainerInstance),
		Idle:              aws.Bool(*metadata.Idle),
		MessageId:         aws.String(*metadata.MessageId),
		Fin:               aws.Bool(fin),
	}
}

// copyTaskMetrics copies a slice of TaskMetric objects to another slice. This is needed as we
// reset the source slice after creating a new PublishMetricsRequest object.
func copyTaskMetrics(from []*ecstcs.TaskMetric) []*ecstcs.TaskMetric {
	to := make([]*ecstcs.TaskMetric, len(from))
	copy(to, from)
	return to
}
<|endoftext|>


<commit_before>// Copyright ©2014 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package optimize

import (
	"github.com/gonum/floats"
)

// LBFGS implements the limited-memory BFGS algorithm. While the normal BFGS algorithm
// makes a full approximation to the inverse hessian, LBFGS instead approximates the
// hessian from the last Store optimization steps. The Store parameter is a tradeoff
// between cost of the method and accuracy of the hessian approximation.
// LBFGS has a cost (both in memory and time) of O(Store * inputDimension).
// Since BFGS has a cost of O(inputDimension^2), LBFGS is more appropriate
// for very large problems. This "forgetful" nature of LBFGS may also make it perform
// better than BFGS for functions with Hessians that vary rapidly spatially.
//
// If Store is 0, Store is defaulted to 15.
// A Linesearcher for LBFGS must satisfy the strong Wolfe conditions at every
// iteration. If Linesearcher == nil, an appropriate default is chosen.
type LBFGS struct {
	Linesearcher Linesearcher
	Store        int // how many past iterations to store

	ls *LinesearchMethod

	dim  int       // Dimension of the problem
	x    []float64 // Location at the last major iteration
	grad []float64 // Gradient at the last major iteration

	// History
	oldest int         // Index of the oldest element of the history
	y      [][]float64 // Last Store values of y
	s      [][]float64 // Last Store values of s
	rho    []float64   // Last Store values of rho
	a      []float64   // Cache of Hessian updates
}

func (l *LBFGS) Init(loc *Location) (Operation, error) {
	if l.Linesearcher == nil {
		l.Linesearcher = &Bisection{}
	}
	if l.Store == 0 {
		l.Store = 15
	}

	if l.ls == nil {
		l.ls = &LinesearchMethod{}
	}
	l.ls.Linesearcher = l.Linesearcher
	l.ls.NextDirectioner = l

	return l.ls.Init(loc)
}

func (l *LBFGS) Iterate(loc *Location) (Operation, error) {
	return l.ls.Iterate(loc)
}

func (l *LBFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) {
	dim := len(loc.X)
	l.dim = dim
	l.oldest = 0

	l.a = resize(l.a, l.Store)
	l.rho = resize(l.rho, l.Store)
	l.y = l.initHistory(l.y)
	l.s = l.initHistory(l.s)

	l.x = resize(l.x, dim)
	copy(l.x, loc.X)

	l.grad = resize(l.grad, dim)
	copy(l.grad, loc.Gradient)

	copy(dir, loc.Gradient)
	floats.Scale(-1, dir)
	return 1 / floats.Norm(dir, 2)
}

func (l *LBFGS) initHistory(hist [][]float64) [][]float64 {
	c := cap(hist)
	if c < l.Store {
		n := make([][]float64, l.Store-c)
		hist = append(hist[:c], n...)
	}
	hist = hist[:l.Store]
	for i := range hist {
		hist[i] = resize(hist[i], l.dim)
		for j := range hist[i] {
			hist[i][j] = 0
		}
	}
	return hist
}

func (l *LBFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) {
	// Uses two-loop correction as described in
	// Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). Springer (2006), chapter 7, page 178.

	if len(loc.X) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}
	if len(loc.Gradient) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}
	if len(dir) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}

	y := l.y[l.oldest]
	floats.SubTo(y, loc.Gradient, l.grad)
	s := l.s[l.oldest]
	floats.SubTo(s, loc.X, l.x)
	sDotY := floats.Dot(s, y)
	l.rho[l.oldest] = 1 / sDotY

	l.oldest = (l.oldest + 1) % l.Store

	copy(l.x, loc.X)
	copy(l.grad, loc.Gradient)
	copy(dir, loc.Gradient)

	// Start with the most recent element and go backward,
	for i := 0; i < l.Store; i++ {
		idx := l.oldest - i - 1
		if idx < 0 {
			idx += l.Store
		}
		l.a[idx] = l.rho[idx] * floats.Dot(l.s[idx], dir)
		floats.AddScaled(dir, -l.a[idx], l.y[idx])
	}

	// Scale the initial Hessian.
	gamma := sDotY / floats.Dot(y, y)
	floats.Scale(gamma, dir)

	// Start with the oldest element and go forward.
	for i := 0; i < l.Store; i++ {
		idx := i + l.oldest
		if idx >= l.Store {
			idx -= l.Store
		}
		beta := l.rho[idx] * floats.Dot(l.y[idx], dir)
		floats.AddScaled(dir, l.a[idx]-beta, l.s[idx])
	}

	// dir contains H^{-1} * g, so flip the direction for minimization.
	floats.Scale(-1, dir)

	return 1
}

func (*LBFGS) Needs() struct {
	Gradient bool
	Hessian  bool
} {
	return struct {
		Gradient bool
		Hessian  bool
	}{true, false}
}
<commit_msg>Update LBFGS documentation<commit_after>// Copyright ©2014 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package optimize

import (
	"github.com/gonum/floats"
)

// LBFGS implements the limited-memory BFGS method for gradient-based
// unconstrained minimization.
//
// It stores a modified version of the inverse Hessian approximation H
// implicitly from the last Store iterations while the normal BFGS method
// stores and manipulates H directly as a dense matrix. Therefore LBFGS is more
// appropriate than BFGS for large problems as the cost of LBFGS scales as
// O(Store * dim) while BFGS scales as O(dim^2). The "forgetful" nature of
// LBFGS may also make it perform better than BFGS for functions with Hessians
// that vary rapidly spatially.
type LBFGS struct {
	// Linesearcher selects suitable steps along the descent direction.
	// Accepted steps should satisfy the strong Wolfe conditions.
	// If Linesearcher is nil, a reasonable default will be chosen.
	Linesearcher Linesearcher
	// Store is the size of the limited-memory storage.
	// If Store is 0, it will be defaulted to 15.
	Store int

	ls *LinesearchMethod

	dim  int       // Dimension of the problem
	x    []float64 // Location at the last major iteration
	grad []float64 // Gradient at the last major iteration

	// History
	oldest int         // Index of the oldest element of the history
	y      [][]float64 // Last Store values of y
	s      [][]float64 // Last Store values of s
	rho    []float64   // Last Store values of rho
	a      []float64   // Cache of Hessian updates
}

func (l *LBFGS) Init(loc *Location) (Operation, error) {
	if l.Linesearcher == nil {
		l.Linesearcher = &Bisection{}
	}
	if l.Store == 0 {
		l.Store = 15
	}

	if l.ls == nil {
		l.ls = &LinesearchMethod{}
	}
	l.ls.Linesearcher = l.Linesearcher
	l.ls.NextDirectioner = l

	return l.ls.Init(loc)
}

func (l *LBFGS) Iterate(loc *Location) (Operation, error) {
	return l.ls.Iterate(loc)
}

func (l *LBFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) {
	dim := len(loc.X)
	l.dim = dim
	l.oldest = 0

	l.a = resize(l.a, l.Store)
	l.rho = resize(l.rho, l.Store)
	l.y = l.initHistory(l.y)
	l.s = l.initHistory(l.s)

	l.x = resize(l.x, dim)
	copy(l.x, loc.X)

	l.grad = resize(l.grad, dim)
	copy(l.grad, loc.Gradient)

	copy(dir, loc.Gradient)
	floats.Scale(-1, dir)
	return 1 / floats.Norm(dir, 2)
}

func (l *LBFGS) initHistory(hist [][]float64) [][]float64 {
	c := cap(hist)
	if c < l.Store {
		n := make([][]float64, l.Store-c)
		hist = append(hist[:c], n...)
	}
	hist = hist[:l.Store]
	for i := range hist {
		hist[i] = resize(hist[i], l.dim)
		for j := range hist[i] {
			hist[i][j] = 0
		}
	}
	return hist
}

func (l *LBFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) {
	// Uses two-loop correction as described in
	// Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). Springer (2006), chapter 7, page 178.

	if len(loc.X) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}
	if len(loc.Gradient) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}
	if len(dir) != l.dim {
		panic("lbfgs: unexpected size mismatch")
	}

	y := l.y[l.oldest]
	floats.SubTo(y, loc.Gradient, l.grad)
	s := l.s[l.oldest]
	floats.SubTo(s, loc.X, l.x)
	sDotY := floats.Dot(s, y)
	l.rho[l.oldest] = 1 / sDotY

	l.oldest = (l.oldest + 1) % l.Store

	copy(l.x, loc.X)
	copy(l.grad, loc.Gradient)
	copy(dir, loc.Gradient)

	// Start with the most recent element and go backward,
	for i := 0; i < l.Store; i++ {
		idx := l.oldest - i - 1
		if idx < 0 {
			idx += l.Store
		}
		l.a[idx] = l.rho[idx] * floats.Dot(l.s[idx], dir)
		floats.AddScaled(dir, -l.a[idx], l.y[idx])
	}

	// Scale the initial Hessian.
	gamma := sDotY / floats.Dot(y, y)
	floats.Scale(gamma, dir)

	// Start with the oldest element and go forward.
	for i := 0; i < l.Store; i++ {
		idx := i + l.oldest
		if idx >= l.Store {
			idx -= l.Store
		}
		beta := l.rho[idx] * floats.Dot(l.y[idx], dir)
		floats.AddScaled(dir, l.a[idx]-beta, l.s[idx])
	}

	// dir contains H^{-1} * g, so flip the direction for minimization.
	floats.Scale(-1, dir)

	return 1
}

func (*LBFGS) Needs() struct {
	Gradient bool
	Hessian  bool
} {
	return struct {
		Gradient bool
		Hessian  bool
	}{true, false}
}
<|endoftext|>


<commit_before>package sisyphus

import (
	"log"

	"github.com/boltdb/bolt"
	"github.com/retailnext/hllpp"
)

// Learn adds the the mail key to the list of words using hyper log log algorithm.
func (m *Mail) Learn(db *bolt.DB) error {

	log.Println("learn mail " + m.Key)

	list, err := m.cleanWordlist()
	if err != nil {
		return err
	}

	wordKey := "Good"
	if m.Junk {
		wordKey = "Junk"
	}

	// Learn words
	for _, val := range list {
		err = db.Update(func(tx *bolt.Tx) error {
			b := tx.Bucket([]byte("Wordlists"))

			bucket := b.Bucket([]byte(wordKey))
			wordRaw := bucket.Get([]byte(val))
			var word *hllpp.HLLPP
			if len(wordRaw) == 0 {
				word = hllpp.New()
			} else {
				word, err = hllpp.Unmarshal(wordRaw)
				if err != nil {
					return err
				}
			}

			word.Add([]byte(m.Key))

			err = bucket.Put([]byte(val), word.Marshal())

			return err
		})
		if err != nil {
			return err
		}
	}

	// Update the statistics counter
	err = db.Update(func(tx *bolt.Tx) error {
		p := tx.Bucket([]byte("Statistics"))

		key := "ProcessedGood"
		if m.Junk {
			key = "ProcessedJunk"
		}

		keyRaw := p.Get([]byte(key))
		var counter *hllpp.HLLPP
		if len(keyRaw) == 0 {
			counter = hllpp.New()
		} else {
			counter, err = hllpp.Unmarshal(keyRaw)
			if err != nil {
				return err
			}
		}

		counter.Add([]byte(m.Key))

		err = p.Put([]byte(key), counter.Marshal())

		return err
	})

	return err
}
<commit_msg>simlify the learn function by moving the two actions into private functions<commit_after>package sisyphus

import (
	"log"

	"github.com/boltdb/bolt"
	"github.com/retailnext/hllpp"
)

// learnWordlist adds the mail key to the respective word's list
func (m *Mail) learnWordlist(w string, db *bolt.DB) error {
	wordKey := "Good"
	if m.Junk {
		wordKey = "Junk"
	}

	err := db.Update(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte("Wordlists"))

		bucket := b.Bucket([]byte(wordKey))
		wordRaw := bucket.Get([]byte(w))
		var word *hllpp.HLLPP
		if len(wordRaw) == 0 {
			word = hllpp.New()
		} else {
			word, err = hllpp.Unmarshal(wordRaw)
			if err != nil {
				return err
			}
		}

		word.Add([]byte(m.Key))

		err = bucket.Put([]byte(w), word.Marshal())

		return err
	})

	return err
}

// learnStatistics adds the mail key to the respective word's list
func (m *Mail) learnStatistics(db *bolt.DB) error {
	err := db.Update(func(tx *bolt.Tx) (err error) {
		p := tx.Bucket([]byte("Statistics"))

		key := "ProcessedGood"
		if m.Junk {
			key = "ProcessedJunk"
		}

		keyRaw := p.Get([]byte(key))
		var counter *hllpp.HLLPP
		if len(keyRaw) == 0 {
			counter = hllpp.New()
		} else {
			counter, err = hllpp.Unmarshal(keyRaw)
			if err != nil {
				return err
			}
		}

		counter.Add([]byte(m.Key))

		err = p.Put([]byte(key), counter.Marshal())

		return err
	})

	return err
}

// Learn adds the the mail key to the list of words using hyper log log algorithm.
func (m *Mail) Learn(db *bolt.DB) error {

	log.Println("learn mail " + m.Key)

	list, err := m.cleanWordlist()
	if err != nil {
		return err
	}

	// Learn words
	for _, val := range list {
		err := m.learnWordlist(val, db)
		if err != nil {
			return err
		}
	}

	// Update the statistics counter
	err = m.learnStatistics(db)

	return err

}
<|endoftext|>


<commit_before>package cmd

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/smtp"
	"os"
	"os/user"
	"regexp"
	"strings"

	"github.com/ogier/pflag"
)

// Go runs the MailHog sendmail replacement.
func Go() {
	smtpAddr := "localhost:1025"

	goflag := false
	for _, g := range os.Args[1:] {
		if strings.HasPrefix(g, "-") && !strings.HasPrefix(g, "--") {
			if strings.HasPrefix(g, "-from ") || strings.HasPrefix(g, "-from=") ||
				strings.HasPrefix(g, "-smtp-addr ") || strings.HasPrefix(g, "-smtp-addr=") {
				goflag = true
				break
			}
		}
	}

	host, err := os.Hostname()
	if err != nil {
		host = "localhost"
	}

	username := "nobody"
	user, err := user.Current()
	if err == nil && user != nil && len(user.Username) > 0 {
		username = user.Username
	}

	fromAddr := username + "@" + host
	var recip []string

	if goflag {
		flag.StringVar(&smtpAddr, "smtp-addr", smtpAddr, "SMTP server address")
		flag.StringVar(&fromAddr, "from", fromAddr, "SMTP sender")

		flag.Parse()
		recip = flag.Args()
	} else {
		pflag.StringVar(&smtpAddr, "smtp-addr", smtpAddr, "SMTP server address")
		pflag.StringVarP(&fromAddr, "from", "f", fromAddr, "SMTP sender")

		pflag.Parse()
		recip = pflag.Args()
	}

	body, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error reading stdin")
		os.Exit(11)
	}

	if len(recip) == 0 {
		// We only need to parse the message to get a recipient if none where
		// provided on the command line.
		re := regexp.MustCompile("(?im)^To: (.*)\r\n$")
		n := bytes.IndexByte(body, 0)
		bodyStr := string(body[:n])
		includedRecip := re.FindAllString(bodyStr, -1)
		if includedRecip == nil {
			fmt.Fprintln(os.Stderr, "missing recipient")
			os.Exit(10)
		}
		newRecip := make([]string, len(recip), len(recip)+len(includedRecip))
		copy(newRecip, recip)
		recip = append(newRecip, includedRecip...)
	}

	err = smtp.SendMail(smtpAddr, nil, fromAddr, recip, body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error sending mail")
		log.Fatal(err)
	}

}
<commit_msg>Use net/mail to parse mail "To" header.<commit_after>package cmd

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/mail"
	"net/smtp"
	"os"
	"os/user"
	"strings"

	"github.com/ogier/pflag"
)

// Go runs the MailHog sendmail replacement.
func Go() {
	smtpAddr := "localhost:1025"

	goflag := false
	for _, g := range os.Args[1:] {
		if strings.HasPrefix(g, "-") && !strings.HasPrefix(g, "--") {
			if strings.HasPrefix(g, "-from ") || strings.HasPrefix(g, "-from=") ||
				strings.HasPrefix(g, "-smtp-addr ") || strings.HasPrefix(g, "-smtp-addr=") {
				goflag = true
				break
			}
		}
	}

	host, err := os.Hostname()
	if err != nil {
		host = "localhost"
	}

	username := "nobody"
	user, err := user.Current()
	if err == nil && user != nil && len(user.Username) > 0 {
		username = user.Username
	}

	fromAddr := username + "@" + host
	var recip []string

	if goflag {
		flag.StringVar(&smtpAddr, "smtp-addr", smtpAddr, "SMTP server address")
		flag.StringVar(&fromAddr, "from", fromAddr, "SMTP sender")

		flag.Parse()
		recip = flag.Args()
	} else {
		pflag.StringVar(&smtpAddr, "smtp-addr", smtpAddr, "SMTP server address")
		pflag.StringVarP(&fromAddr, "from", "f", fromAddr, "SMTP sender")

		pflag.Parse()
		recip = pflag.Args()
	}

	body, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error reading stdin")
		os.Exit(11)
	}

	msg, err := mail.ReadMessage(bytes.NewReader(body))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error parsing message body")
		os.Exit(11)
	}

	if len(recip) == 0 {
		// We only need to parse the message to get a recipient if none where
		// provided on the command line.
		recip = append(recip, msg.Header.Get("To"))
	}

	err = smtp.SendMail(smtpAddr, nil, fromAddr, recip, body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error sending mail")
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cmd

import (
	gerrors "errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"

	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/fs"
	"launchpad.net/gnuflag"
)

var ErrAbortCommand = gerrors.New("")

type exiter interface {
	Exit(int)
}

type osExiter struct{}

func (e osExiter) Exit(code int) {
	os.Exit(code)
}

type Lookup func(context *Context) error

type Manager struct {
	Commands      map[string]Command
	topics        map[string]string
	name          string
	stdout        io.Writer
	stderr        io.Writer
	stdin         io.Reader
	version       string
	versionHeader string
	e             exiter
	original      string
	wrong         bool
	lookup        Lookup
}

func NewManager(name, ver, verHeader string, stdout, stderr io.Writer, stdin io.Reader, lookup Lookup) *Manager {
	manager := &Manager{name: name, version: ver, versionHeader: verHeader, stdout: stdout, stderr: stderr, stdin: stdin, lookup: lookup}
	manager.Register(&help{manager})
	manager.Register(&version{manager})
	return manager
}

func BuildBaseManager(name, version, versionHeader string, lookup Lookup) *Manager {
	m := NewManager(name, version, versionHeader, os.Stdout, os.Stderr, os.Stdin, lookup)
	m.Register(&login{})
	m.Register(&logout{})
	m.Register(&userCreate{})
	m.Register(&resetPassword{})
	m.Register(&userRemove{})
	m.Register(&teamCreate{})
	m.Register(&teamRemove{})
	m.Register(&teamList{})
	m.Register(&teamUserAdd{})
	m.Register(&teamUserRemove{})
	m.Register(teamUserList{})
	m.Register(&changePassword{})
	m.Register(&targetList{})
	m.Register(&targetAdd{})
	m.Register(&targetRemove{})
	m.Register(&targetSet{})
	m.Register(&showAPIToken{})
	m.Register(&regenerateAPIToken{})
	m.RegisterTopic("target", fmt.Sprintf(targetTopic, name))
	return m
}

func (m *Manager) Register(command Command) {
	if m.Commands == nil {
		m.Commands = make(map[string]Command)
	}
	name := command.Info().Name
	_, found := m.Commands[name]
	if found {
		panic(fmt.Sprintf("command already registered: %s", name))
	}
	m.Commands[name] = command
}

func (m *Manager) RegisterDeprecated(command Command, oldName string) {
	if m.Commands == nil {
		m.Commands = make(map[string]Command)
	}
	name := command.Info().Name
	_, found := m.Commands[name]
	if found {
		panic(fmt.Sprintf("command already registered: %s", name))
	}
	m.Commands[name] = command
	m.Commands[oldName] = &DeprecatedCommand{Command: command, oldName: oldName}
}

func (m *Manager) RegisterTopic(name, content string) {
	if m.topics == nil {
		m.topics = make(map[string]string)
	}
	_, found := m.topics[name]
	if found {
		panic(fmt.Sprintf("topic already registered: %s", name))
	}
	m.topics[name] = content
}

func (m *Manager) Run(args []string) {
	var status int
	if len(args) == 0 {
		args = append(args, "help")
	}
	name := args[0]
	command, ok := m.Commands[name]
	if !ok {
		if m.lookup != nil {
			context := Context{args, m.stdout, m.stderr, m.stdin}
			err := m.lookup(&context)
			if err != nil {
				msg := ""
				if os.IsNotExist(err) {
					msg = fmt.Sprintf("Error: command %q does not exist\n", args[0])
				} else {
					msg = err.Error()
				}
				fmt.Fprint(m.stderr, msg)
				m.finisher().Exit(1)
			}
			return
		}
		fmt.Fprintf(m.stderr, "Error: command %q does not exist\n", args[0])
		m.finisher().Exit(1)
		return
	}
	args = args[1:]
	info := command.Info()
	if flagged, ok := command.(FlaggedCommand); ok {
		flagset := flagged.Flags()
		err := flagset.Parse(true, args)
		if err != nil {
			fmt.Fprint(m.stderr, err)
			m.finisher().Exit(1)
			return
		}
		args = flagset.Args()
	}
	if length := len(args); (length < info.MinArgs || (info.MaxArgs > 0 && length > info.MaxArgs)) &&
		name != "help" {
		m.wrong = true
		m.original = info.Name
		command = m.Commands["help"]
		args = []string{name}
		status = 1
	}
	context := Context{args, m.stdout, m.stderr, m.stdin}
	client := NewClient(&http.Client{}, &context, m)
	err := command.Run(&context, client)
	if err != nil {
		errorMsg := err.Error()
		httpErr, ok := err.(*errors.HTTP)
		if ok && httpErr.Code == http.StatusUnauthorized && name != "login" {
			errorMsg = `You're not authenticated or your session has expired. Please use "login" command for authentication.`
		}
		if !strings.HasSuffix(errorMsg, "\n") {
			errorMsg += "\n"
		}
		if err != ErrAbortCommand {
			io.WriteString(m.stderr, "Error: "+errorMsg)
		}
		status = 1
	}
	m.finisher().Exit(status)
}

func (m *Manager) finisher() exiter {
	if m.e == nil {
		m.e = osExiter{}
	}
	return m.e
}

type Command interface {
	Info() *Info
	Run(context *Context, client *Client) error
}

type FlaggedCommand interface {
	Command
	Flags() *gnuflag.FlagSet
}

type DeprecatedCommand struct {
	Command
	oldName string
}

func (c *DeprecatedCommand) Run(context *Context, client *Client) error {
	fmt.Fprintf(context.Stderr, "WARNING: %q has been deprecated, please use %q instead.\n\n", c.oldName, c.Command.Info().Name)
	return c.Command.Run(context, client)
}

func (c *DeprecatedCommand) Flags() *gnuflag.FlagSet {
	if cmd, ok := c.Command.(FlaggedCommand); ok {
		return cmd.Flags()
	}
	return gnuflag.NewFlagSet("", gnuflag.ContinueOnError)
}

type Context struct {
	Args   []string
	Stdout io.Writer
	Stderr io.Writer
	Stdin  io.Reader
}

type Info struct {
	Name    string
	MinArgs int
	MaxArgs int
	Usage   string
	Desc    string
}

// Implementing the Commandable interface allows extending
// the tsr command line interface
type Commandable interface {
	Commands() []Command
}

// Implementing the AdminCommandable interface allows extending
// the tsuru-admin command line interface
type AdminCommandable interface {
	AdminCommands() []Command
}

type help struct {
	manager *Manager
}

func (c *help) Info() *Info {
	return &Info{
		Name:  "help",
		Usage: "command [args]",
	}
}

func (c *help) Run(context *Context, client *Client) error {
	const deprecatedMsg = "WARNING: %q is deprecated. Showing help for %q instead.\n\n"
	output := fmt.Sprintf("%s version %s.\n\n", c.manager.name, c.manager.version)
	if c.manager.wrong {
		output += fmt.Sprint("ERROR: wrong number of arguments.\n\n")
	}
	if len(context.Args) > 0 {
		if cmd, ok := c.manager.Commands[context.Args[0]]; ok {
			if deprecated, ok := cmd.(*DeprecatedCommand); ok {
				fmt.Fprintf(context.Stderr, deprecatedMsg, deprecated.oldName, cmd.Info().Name)
			}
			info := cmd.Info()
			output += fmt.Sprintf("Usage: %s %s\n", c.manager.name, info.Usage)
			output += fmt.Sprintf("\n%s\n", info.Desc)
			if info.MinArgs > 0 {
				output += fmt.Sprintf("\nMinimum # of arguments: %d", info.MinArgs)
			}
			if info.MaxArgs > 0 {
				output += fmt.Sprintf("\nMaximum # of arguments: %d", info.MaxArgs)
			}
			output += fmt.Sprint("\n")
		} else if topic, ok := c.manager.topics[context.Args[0]]; ok {
			output += topic
		} else {
			return fmt.Errorf("command %q does not exist.", context.Args[0])
		}
	} else {
		output += fmt.Sprintf("Usage: %s %s\n\nAvailable commands:\n", c.manager.name, c.Info().Usage)
		var commands []string
		for name, cmd := range c.manager.Commands {
			if _, ok := cmd.(*DeprecatedCommand); !ok {
				commands = append(commands, name)
			}
		}
		sort.Strings(commands)
		for _, command := range commands {
			output += fmt.Sprintf("  %s\n", command)
		}
		output += fmt.Sprintf("\nUse %s help <commandname> to get more information about a command.\n", c.manager.name)
		if len(c.manager.topics) > 0 {
			output += fmt.Sprintln("\nAvailable topics:")
			for topic := range c.manager.topics {
				output += fmt.Sprintf("  %s\n", topic)
			}
			output += fmt.Sprintf("\nUse %s help <topicname> to get more information about a topic.\n", c.manager.name)
		}
	}
	io.WriteString(context.Stdout, output)
	return nil
}

type version struct {
	manager *Manager
}

func (c *version) Info() *Info {
	return &Info{
		Name:    "version",
		MinArgs: 0,
		Usage:   "version",
		Desc:    "display the current version",
	}
}

func (c *version) Run(context *Context, client *Client) error {
	fmt.Fprintf(context.Stdout, "%s version %s.\n", c.manager.name, c.manager.version)
	return nil
}

func ExtractProgramName(path string) string {
	parts := strings.Split(path, "/")
	return parts[len(parts)-1]
}

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		fsystem = fs.OsFs{}
	}
	return fsystem
}

// validateVersion checks whether current version is greater or equal to
// supported version.
func validateVersion(supported, current string) bool {
	var (
		bigger bool
		limit  int
	)
	if supported == "" || supported == current {
		return true
	}
	partsSupported := strings.Split(supported, ".")
	partsCurrent := strings.Split(current, ".")
	if len(partsSupported) > len(partsCurrent) {
		limit = len(partsCurrent)
		bigger = true
	} else {
		limit = len(partsSupported)
	}
	for i := 0; i < limit; i++ {
		current, err := strconv.Atoi(partsCurrent[i])
		if err != nil {
			return false
		}
		supported, err := strconv.Atoi(partsSupported[i])
		if err != nil {
			return false
		}
		if current < supported {
			return false
		}
		if current > supported {
			return true
		}
	}
	if bigger {
		return false
	}
	return true
}
<commit_msg>cmd.go: Nicer error for unknown command<commit_after>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cmd

import (
	gerrors "errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"

	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/fs"
	"launchpad.net/gnuflag"
)

var ErrAbortCommand = gerrors.New("")

type exiter interface {
	Exit(int)
}

type osExiter struct{}

func (e osExiter) Exit(code int) {
	os.Exit(code)
}

type Lookup func(context *Context) error

type Manager struct {
	Commands      map[string]Command
	topics        map[string]string
	name          string
	stdout        io.Writer
	stderr        io.Writer
	stdin         io.Reader
	version       string
	versionHeader string
	e             exiter
	original      string
	wrong         bool
	lookup        Lookup
}

func NewManager(name, ver, verHeader string, stdout, stderr io.Writer, stdin io.Reader, lookup Lookup) *Manager {
	manager := &Manager{name: name, version: ver, versionHeader: verHeader, stdout: stdout, stderr: stderr, stdin: stdin, lookup: lookup}
	manager.Register(&help{manager})
	manager.Register(&version{manager})
	return manager
}

func BuildBaseManager(name, version, versionHeader string, lookup Lookup) *Manager {
	m := NewManager(name, version, versionHeader, os.Stdout, os.Stderr, os.Stdin, lookup)
	m.Register(&login{})
	m.Register(&logout{})
	m.Register(&userCreate{})
	m.Register(&resetPassword{})
	m.Register(&userRemove{})
	m.Register(&teamCreate{})
	m.Register(&teamRemove{})
	m.Register(&teamList{})
	m.Register(&teamUserAdd{})
	m.Register(&teamUserRemove{})
	m.Register(teamUserList{})
	m.Register(&changePassword{})
	m.Register(&targetList{})
	m.Register(&targetAdd{})
	m.Register(&targetRemove{})
	m.Register(&targetSet{})
	m.Register(&showAPIToken{})
	m.Register(&regenerateAPIToken{})
	m.RegisterTopic("target", fmt.Sprintf(targetTopic, name))
	return m
}

func (m *Manager) Register(command Command) {
	if m.Commands == nil {
		m.Commands = make(map[string]Command)
	}
	name := command.Info().Name
	_, found := m.Commands[name]
	if found {
		panic(fmt.Sprintf("command already registered: %s", name))
	}
	m.Commands[name] = command
}

func (m *Manager) RegisterDeprecated(command Command, oldName string) {
	if m.Commands == nil {
		m.Commands = make(map[string]Command)
	}
	name := command.Info().Name
	_, found := m.Commands[name]
	if found {
		panic(fmt.Sprintf("command already registered: %s", name))
	}
	m.Commands[name] = command
	m.Commands[oldName] = &DeprecatedCommand{Command: command, oldName: oldName}
}

func (m *Manager) RegisterTopic(name, content string) {
	if m.topics == nil {
		m.topics = make(map[string]string)
	}
	_, found := m.topics[name]
	if found {
		panic(fmt.Sprintf("topic already registered: %s", name))
	}
	m.topics[name] = content
}

func (m *Manager) Run(args []string) {
	var status int
	if len(args) == 0 {
		args = append(args, "help")
	}
	name := args[0]
	command, ok := m.Commands[name]
	if !ok {
		if m.lookup != nil {
			context := Context{args, m.stdout, m.stderr, m.stdin}
			err := m.lookup(&context)
			if err != nil {
				msg := ""
				if os.IsNotExist(err) {
					msg = fmt.Sprintf("%s: %q is not a tsuru command. See %q.\n", os.Args[0], args[0], "tsuru help")
					msg = fmt.Sprintf("%s\nDid you mean?\n", msg)
					for key, _ := range m.Commands {
						if strings.HasPrefix(key, args[0]) {
							msg = fmt.Sprintf("%s	%s\n", msg, key)
						}
					}
				} else {
					msg = err.Error()
				}
				fmt.Fprint(m.stderr, msg)
				m.finisher().Exit(1)
			}
			return
		}
		fmt.Fprintf(m.stderr, "Error: command %q does not exist\n", args[0])
		m.finisher().Exit(1)
		return
	}
	args = args[1:]
	info := command.Info()
	if flagged, ok := command.(FlaggedCommand); ok {
		flagset := flagged.Flags()
		err := flagset.Parse(true, args)
		if err != nil {
			fmt.Fprint(m.stderr, err)
			m.finisher().Exit(1)
			return
		}
		args = flagset.Args()
	}
	if length := len(args); (length < info.MinArgs || (info.MaxArgs > 0 && length > info.MaxArgs)) &&
		name != "help" {
		m.wrong = true
		m.original = info.Name
		command = m.Commands["help"]
		args = []string{name}
		status = 1
	}
	context := Context{args, m.stdout, m.stderr, m.stdin}
	client := NewClient(&http.Client{}, &context, m)
	err := command.Run(&context, client)
	if err != nil {
		errorMsg := err.Error()
		httpErr, ok := err.(*errors.HTTP)
		if ok && httpErr.Code == http.StatusUnauthorized && name != "login" {
			errorMsg = `You're not authenticated or your session has expired. Please use "login" command for authentication.`
		}
		if !strings.HasSuffix(errorMsg, "\n") {
			errorMsg += "\n"
		}
		if err != ErrAbortCommand {
			io.WriteString(m.stderr, "Error: "+errorMsg)
		}
		status = 1
	}
	m.finisher().Exit(status)
}

func (m *Manager) finisher() exiter {
	if m.e == nil {
		m.e = osExiter{}
	}
	return m.e
}

type Command interface {
	Info() *Info
	Run(context *Context, client *Client) error
}

type FlaggedCommand interface {
	Command
	Flags() *gnuflag.FlagSet
}

type DeprecatedCommand struct {
	Command
	oldName string
}

func (c *DeprecatedCommand) Run(context *Context, client *Client) error {
	fmt.Fprintf(context.Stderr, "WARNING: %q has been deprecated, please use %q instead.\n\n", c.oldName, c.Command.Info().Name)
	return c.Command.Run(context, client)
}

func (c *DeprecatedCommand) Flags() *gnuflag.FlagSet {
	if cmd, ok := c.Command.(FlaggedCommand); ok {
		return cmd.Flags()
	}
	return gnuflag.NewFlagSet("", gnuflag.ContinueOnError)
}

type Context struct {
	Args   []string
	Stdout io.Writer
	Stderr io.Writer
	Stdin  io.Reader
}

type Info struct {
	Name    string
	MinArgs int
	MaxArgs int
	Usage   string
	Desc    string
}

// Implementing the Commandable interface allows extending
// the tsr command line interface
type Commandable interface {
	Commands() []Command
}

// Implementing the AdminCommandable interface allows extending
// the tsuru-admin command line interface
type AdminCommandable interface {
	AdminCommands() []Command
}

type help struct {
	manager *Manager
}

func (c *help) Info() *Info {
	return &Info{
		Name:  "help",
		Usage: "command [args]",
	}
}

func (c *help) Run(context *Context, client *Client) error {
	const deprecatedMsg = "WARNING: %q is deprecated. Showing help for %q instead.\n\n"
	output := fmt.Sprintf("%s version %s.\n\n", c.manager.name, c.manager.version)
	if c.manager.wrong {
		output += fmt.Sprint("ERROR: wrong number of arguments.\n\n")
	}
	if len(context.Args) > 0 {
		if cmd, ok := c.manager.Commands[context.Args[0]]; ok {
			if deprecated, ok := cmd.(*DeprecatedCommand); ok {
				fmt.Fprintf(context.Stderr, deprecatedMsg, deprecated.oldName, cmd.Info().Name)
			}
			info := cmd.Info()
			output += fmt.Sprintf("Usage: %s %s\n", c.manager.name, info.Usage)
			output += fmt.Sprintf("\n%s\n", info.Desc)
			if info.MinArgs > 0 {
				output += fmt.Sprintf("\nMinimum # of arguments: %d", info.MinArgs)
			}
			if info.MaxArgs > 0 {
				output += fmt.Sprintf("\nMaximum # of arguments: %d", info.MaxArgs)
			}
			output += fmt.Sprint("\n")
		} else if topic, ok := c.manager.topics[context.Args[0]]; ok {
			output += topic
		} else {
			return fmt.Errorf("command %q does not exist.", context.Args[0])
		}
	} else {
		output += fmt.Sprintf("Usage: %s %s\n\nAvailable commands:\n", c.manager.name, c.Info().Usage)
		var commands []string
		for name, cmd := range c.manager.Commands {
			if _, ok := cmd.(*DeprecatedCommand); !ok {
				commands = append(commands, name)
			}
		}
		sort.Strings(commands)
		for _, command := range commands {
			output += fmt.Sprintf("  %s\n", command)
		}
		output += fmt.Sprintf("\nUse %s help <commandname> to get more information about a command.\n", c.manager.name)
		if len(c.manager.topics) > 0 {
			output += fmt.Sprintln("\nAvailable topics:")
			for topic := range c.manager.topics {
				output += fmt.Sprintf("  %s\n", topic)
			}
			output += fmt.Sprintf("\nUse %s help <topicname> to get more information about a topic.\n", c.manager.name)
		}
	}
	io.WriteString(context.Stdout, output)
	return nil
}

type version struct {
	manager *Manager
}

func (c *version) Info() *Info {
	return &Info{
		Name:    "version",
		MinArgs: 0,
		Usage:   "version",
		Desc:    "display the current version",
	}
}

func (c *version) Run(context *Context, client *Client) error {
	fmt.Fprintf(context.Stdout, "%s version %s.\n", c.manager.name, c.manager.version)
	return nil
}

func ExtractProgramName(path string) string {
	parts := strings.Split(path, "/")
	return parts[len(parts)-1]
}

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		fsystem = fs.OsFs{}
	}
	return fsystem
}

// validateVersion checks whether current version is greater or equal to
// supported version.
func validateVersion(supported, current string) bool {
	var (
		bigger bool
		limit  int
	)
	if supported == "" || supported == current {
		return true
	}
	partsSupported := strings.Split(supported, ".")
	partsCurrent := strings.Split(current, ".")
	if len(partsSupported) > len(partsCurrent) {
		limit = len(partsCurrent)
		bigger = true
	} else {
		limit = len(partsSupported)
	}
	for i := 0; i < limit; i++ {
		current, err := strconv.Atoi(partsCurrent[i])
		if err != nil {
			return false
		}
		supported, err := strconv.Atoi(partsSupported[i])
		if err != nil {
			return false
		}
		if current < supported {
			return false
		}
		if current > supported {
			return true
		}
	}
	if bigger {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright © 2016 Chu Duc Minh <chu.ducminh@gmail.com>
//
// 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.

package cmd

import (
	"fmt"

	hwinfo "github.com/PiScale/hwinfo-lib"
	"github.com/spf13/cobra"
)

// hddCmd represents the hdd command
var hddCmd = &cobra.Command{
	Use:   "hdd",
	Short: "Show information about HDD",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		// TODO: Work your own magic here
		hdds, err := hwinfo.Get_hdd()
		if err == nil {
			for _, hdd := range hdds.Items {
				fmt.Println("Logical Device name:", hdd.DevName)
				fmt.Println("Model name:", hdd.Model)
				fmt.Println("Serial number:", hdd.SerialNumber)
				fmt.Println("Size:", hdd.Size)
				fmt.Println("Firmware revision:", hdd.Firmware)
				fmt.Println("Bus type:", hdd.Bus)
				fmt.Println("")
			}
		} else {
			fmt.Println("Unknown error:", err)
		}

	},
}

func init() {
	showCmd.AddCommand(hddCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// hddCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// hddCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}
<commit_msg>Improve output format for consistency<commit_after>// Copyright © 2016 Chu Duc Minh <chu.ducminh@gmail.com>
//
// 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.

package cmd

import (
	"fmt"

	hwinfo "github.com/PiScale/hwinfo-lib"
	"github.com/spf13/cobra"
)

// hddCmd represents the hdd command
var hddCmd = &cobra.Command{
	Use:   "hdd",
	Short: "Show information about HDD",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		// TODO: Work your own magic here
		hdds, err := hwinfo.Get_hdd()
		if err == nil {
			for _, hdd := range hdds.Items {
				fmt.Println("HDD Logical Device name:", hdd.DevName)
				fmt.Println("HDD Model name:", hdd.Model)
				fmt.Println("HDD Serial number:", hdd.SerialNumber)
				fmt.Println("HDD Size:", hdd.Size)
				fmt.Println("HDD Firmware revision:", hdd.Firmware)
				fmt.Println("HDD Bus type:", hdd.Bus)
				fmt.Println("")
			}
		} else {
			fmt.Println("Unknown error:", err)
		}

	},
}

func init() {
	showCmd.AddCommand(hddCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// hddCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// hddCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
)

// newLogger creates a new logger instance.
func newLogger(config *configuration) log.Logger {
	var logger log.Logger
	w := log.NewSyncWriter(os.Stdout)

	switch config.LogFormat {
	case "logfmt":
		logger = log.NewLogfmtLogger(w)

	case "json":
		logger = log.NewJSONLogger(w)

	default:
		panic(fmt.Errorf("Unsupported log format: %s", config.LogFormat))
	}

	// Add default context
	logger = log.With(logger, "service", ServiceName)

	// Default to Info level
	logger = level.NewInjector(logger, level.InfoValue())

	// Only log debug level messages if debug mode is turned on
	if config.Debug == false {
		logger = level.NewFilter(logger, level.AllowInfo())
	}

	return logger
}
<commit_msg>Fix log style<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
)

// newLogger creates a new logger instance.
func newLogger(config *configuration) log.Logger {
	var logger log.Logger
	w := log.NewSyncWriter(os.Stdout)

	switch config.LogFormat {
	case "logfmt":
		logger = log.NewLogfmtLogger(w)

	case "json":
		logger = log.NewJSONLogger(w)

	default:
		panic(fmt.Errorf("unsupported log format: %s", config.LogFormat))
	}

	// Add default context
	logger = log.With(logger, "service", ServiceName)

	// Default to Info level
	logger = level.NewInjector(logger, level.InfoValue())

	// Only log debug level messages if debug mode is turned on
	if config.Debug == false {
		logger = level.NewFilter(logger, level.AllowInfo())
	}

	return logger
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/spf13/cobra"
	"github.com/Sirupsen/logrus"
	"os"
	"github.com/emc-advanced-dev/unik/pkg/client"
	"strings"
	"fmt"
	"errors"
)

var instanceName, imageName string
var volumes, envPairs []string

// runCmd represents the run command
var runCmd = &cobra.Command{
	Use:   "run",
	Short: "Run a unikernel instance from a compiled image",
	Long: `Deploys a running instance from a unik-compiled unikernel disk image.
	The instance will be deployed on the provider the image was compiled for.
	e.g. if the image was compiled for virtualbox, unik will attempt to deploy
	the image on the configured virtualbox environment.

	'unik run' requires a unik-managed volume (see 'unik volumes' and 'unik create volume')
	to be attached and mounted to each mount point specified at image compilation time.
	This means that if the image was compiled with two mount points, /data1 and /data2,
	'unik run' requires 2 available volumes to be attached to the instance at runtime, which
	must be specified with the flags --vol SOME_VOLUME_NAME:/data1 --vol ANOTHER_VOLUME_NAME:/data2
	If no mount points are required for the image, volumes cannot be attached.

	environment variables can be set at runtime through the use of the -env flag.

	Example usage:
		unik run -instanceName newInstance -imageName myImage -vol myVol:/mount1 -vol yourVol:/mount2 -env foo=bar -env another=one

		# will create and run an instance of myImage on the provider environment myImage is compiled for
		# instance will be named newInstance
		# instance will attempt to mount unik-managed volume myVol to /mount1
		# instance will attempt to mount unik-managed volume yourVol to /mount2
		# instance will boot with env variable 'foo' set to 'bar'
		# instance will boot with env variable 'another' set to 'one'

		# note that run must take exactly one -vol argument for each mount point defined in the image specification
	`,
	Run: func(cmd *cobra.Command, args []string) {
		if err := func() error {
			if instanceName == "" {
				return errors.New("--instanceName must be set")
			}
			if imageName == "" {
				logrus.Error("--imageName must be set")
				return errors.New("--instanceName must be set")
			}
			if err := readClientConfig(); err != nil {
				return err
			}
			if host == "" {
				host = clientConfig.Host
			}

			mounts := make(map[string]string)
			for _, vol := range volumes {
				pair := strings.Split(vol, ":")
				if len(pair) != 2 {
					return errors.New(fmt.Sprintf("invalid format for vol flag: %s", vol))
				}
				volId := pair[0]
				mnt := pair[1]
				mounts[volId] = mnt
			}

			env := make(map[string]string)
			for _, e := range envPairs {
				pair := strings.Split(e, "=")
				if len(pair) != 2 {
					return errors.New(fmt.Sprintf("invalid format for env flag: %s", e))
				}
				key := pair[0]
				val := pair[1]
				env[key] = val
			}

			logrus.WithFields(logrus.Fields{
				"instanceName": instanceName,
				"imageName": imageName,
				"env": env,
				"mounts": mounts,
				"host": host,
			}).Infof("running unik run")
			instance, err := client.UnikClient(host).Instances().Run(instanceName, imageName, mounts, env)
			if err != nil {
				return errors.New(fmt.Sprintf("building image failed: %v", err))
			}
			printInstances(instance)
			return nil
		}(); err != nil {
			logrus.Errorf("failed running instance: %v", err)
			os.Exit(-1)
		}
	},
}

func init() {
	RootCmd.AddCommand(runCmd)
	buildCmd.Flags().StringVar(&instanceName, "instanceName", "", "<string,required> name to give the instance. must be unique")
	buildCmd.Flags().StringVar(&imageName, "imageName", "", "<string,required> image to use")
	buildCmd.Flags().StringSliceVar(&envPairs, "env", []string{}, "<string,repeated> set any number of environment variables for the instance. must be in the format KEY=VALUE")
	buildCmd.Flags().StringSliceVar(&volumes, "vol", []string{}, `<string,repeated> each --vol flag specifies one volume id and the corresponding mount point to attach
	to the instance at boot time. volumes must be attached to the instance for each mount point expected by the image.
	run 'unik image <image_name>' to see the mount points required for the image.
	specified in the format 'volume_id:mount_point'`)
}
<commit_msg>fix run<commit_after>package cmd

import (
	"github.com/spf13/cobra"
	"github.com/Sirupsen/logrus"
	"os"
	"github.com/emc-advanced-dev/unik/pkg/client"
	"strings"
	"fmt"
	"errors"
)

var instanceName, imageName string
var volumes, envPairs []string

// runCmd represents the run command
var runCmd = &cobra.Command{
	Use:   "run",
	Short: "Run a unikernel instance from a compiled image",
	Long: `Deploys a running instance from a unik-compiled unikernel disk image.
	The instance will be deployed on the provider the image was compiled for.
	e.g. if the image was compiled for virtualbox, unik will attempt to deploy
	the image on the configured virtualbox environment.

	'unik run' requires a unik-managed volume (see 'unik volumes' and 'unik create volume')
	to be attached and mounted to each mount point specified at image compilation time.
	This means that if the image was compiled with two mount points, /data1 and /data2,
	'unik run' requires 2 available volumes to be attached to the instance at runtime, which
	must be specified with the flags --vol SOME_VOLUME_NAME:/data1 --vol ANOTHER_VOLUME_NAME:/data2
	If no mount points are required for the image, volumes cannot be attached.

	environment variables can be set at runtime through the use of the -env flag.

	Example usage:
		unik run --instanceName newInstance --imageName myImage -vol myVol:/mount1 -vol yourVol:/mount2 -env foo=bar -env another=one

		# will create and run an instance of myImage on the provider environment myImage is compiled for
		# instance will be named newInstance
		# instance will attempt to mount unik-managed volume myVol to /mount1
		# instance will attempt to mount unik-managed volume yourVol to /mount2
		# instance will boot with env variable 'foo' set to 'bar'
		# instance will boot with env variable 'another' set to 'one'

		# note that run must take exactly one -vol argument for each mount point defined in the image specification
	`,
	Run: func(cmd *cobra.Command, args []string) {
		if err := func() error {
			if instanceName == "" {
				return errors.New("--instanceName must be set")
			}
			if imageName == "" {
				logrus.Error("--imageName must be set")
				return errors.New("--instanceName must be set")
			}
			if err := readClientConfig(); err != nil {
				return err
			}
			if host == "" {
				host = clientConfig.Host
			}

			mounts := make(map[string]string)
			for _, vol := range volumes {
				pair := strings.Split(vol, ":")
				if len(pair) != 2 {
					return errors.New(fmt.Sprintf("invalid format for vol flag: %s", vol))
				}
				volId := pair[0]
				mnt := pair[1]
				mounts[volId] = mnt
			}

			env := make(map[string]string)
			for _, e := range envPairs {
				pair := strings.Split(e, "=")
				if len(pair) != 2 {
					return errors.New(fmt.Sprintf("invalid format for env flag: %s", e))
				}
				key := pair[0]
				val := pair[1]
				env[key] = val
			}

			logrus.WithFields(logrus.Fields{
				"instanceName": instanceName,
				"imageName": imageName,
				"env": env,
				"mounts": mounts,
				"host": host,
			}).Infof("running unik run")
			instance, err := client.UnikClient(host).Instances().Run(instanceName, imageName, mounts, env)
			if err != nil {
				return errors.New(fmt.Sprintf("building image failed: %v", err))
			}
			printInstances(instance)
			return nil
		}(); err != nil {
			logrus.Errorf("failed running instance: %v", err)
			os.Exit(-1)
		}
	},
}

func init() {
	RootCmd.AddCommand(runCmd)
	runCmd.Flags().StringVar(&instanceName, "instanceName", "", "<string,required> name to give the instance. must be unique")
	runCmd.Flags().StringVar(&imageName, "imageName", "", "<string,required> image to use")
	runCmd.Flags().StringSliceVar(&envPairs, "env", []string{}, "<string,repeated> set any number of environment variables for the instance. must be in the format KEY=VALUE")
	runCmd.Flags().StringSliceVar(&volumes, "vol", []string{}, `<string,repeated> each --vol flag specifies one volume id and the corresponding mount point to attach
	to the instance at boot time. volumes must be attached to the instance for each mount point expected by the image.
	run 'unik image <image_name>' to see the mount points required for the image.
	specified in the format 'volume_id:mount_point'`)
}
<|endoftext|>


<commit_before>package cmd

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"os"

	"github.com/codegangsta/cli"

	"github.com/Unknwon/macaron"

	"github.com/containerops/wharf/setting"
	"github.com/containerops/wharf/web"
	"github.com/containerops/wrench/db"
	"github.com/containerops/wrench/utils"
)

var CmdWeb = cli.Command{
	Name:        "web",
	Usage:       "start wharf web service",
	Description: "wharf is the module of handler docker repository and rkt image.",
	Action:      runWeb,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "address",
			Value: "0.0.0.0",
			Usage: "web service listen ip, default is 0.0.0.0; if listen with Unix Socket, the value is sock file path.",
		},
		cli.IntFlag{
			Name:  "port",
			Value: 80,
			Usage: "web service listen at port 80; if run with https will be 443.",
		},
	},
}

func runWeb(c *cli.Context) {
	m := macaron.New()

	if err := db.InitDB(setting.DBURI, setting.DBPasswd, setting.DBDB); err != nil {
		fmt.Printf("Connect Database Error %s", err.Error())
	}

	//Set Macaron Web Middleware And Routers
	web.SetWharfMacaron(m)

	switch setting.ListenMode {
	case "http":
		listenaddr := fmt.Sprintf("%s:%d", c.String("address"), c.Int("port"))
		if err := http.ListenAndServe(listenaddr, m); err != nil {
			fmt.Printf("start wharf http service error: %v", err.Error())
		}
		break
	case "https":
		listenaddr := fmt.Sprintf("%s:443", c.String("address"))
		server := &http.Server{Addr: listenaddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m}
		if err := server.ListenAndServeTLS(setting.HttpsCertFile, setting.HttpsKeyFile); err != nil {
			fmt.Printf("start wharf https service error: %v", err.Error())
		}
		break
	case "unix":
		listenaddr := fmt.Sprintf("%s", c.String("address"))
		if utils.Exist(listenaddr) {
			os.Remove(listenaddr)
		}

		if listener, err := net.Listen("unix", listenaddr); err != nil {
			fmt.Printf("start wharf unix socket error: %v", err.Error())
		} else {
			server := &http.Server{Handler: m}
			if err := server.Serve(listener); err != nil {
				fmt.Printf("start wharf unix socket error: %v", err.Error())
			}
		}
		break
	default:
		break
	}
}
<commit_msg>Add dockyard/crew/generator function in the web command<commit_after>package cmd

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"os"

	"github.com/codegangsta/cli"

	"github.com/Unknwon/macaron"

	crew "github.com/containerops/crew/web"
	dockyard "github.com/containerops/dockyard/web"
	generator "github.com/containerops/generator/web"
	"github.com/containerops/wharf/setting"
	"github.com/containerops/wharf/web"
	"github.com/containerops/wrench/db"
	"github.com/containerops/wrench/utils"
)

var CmdWeb = cli.Command{
	Name:        "web",
	Usage:       "start wharf web service",
	Description: "wharf is the module of handler docker repository and rkt image.",
	Action:      runWeb,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "address",
			Value: "0.0.0.0",
			Usage: "web service listen ip, default is 0.0.0.0; if listen with Unix Socket, the value is sock file path.",
		},
		cli.IntFlag{
			Name:  "port",
			Value: 80,
			Usage: "web service listen at port 80; if run with https will be 443.",
		},
	},
}

func runWeb(c *cli.Context) {
	m := macaron.New()

	if err := db.InitDB(setting.DBURI, setting.DBPasswd, setting.DBDB); err != nil {
		fmt.Printf("Connect Database Error %s", err.Error())
	}

	web.SetWharfMacaron(m)
	dockyard.SetDockyardMacaron(m)
	crew.SetCrewMacaron(m)
	generator.SetGeneratorMacaron(m)

	switch setting.ListenMode {
	case "http":
		listenaddr := fmt.Sprintf("%s:%d", c.String("address"), c.Int("port"))
		if err := http.ListenAndServe(listenaddr, m); err != nil {
			fmt.Printf("start wharf http service error: %v", err.Error())
		}
		break
	case "https":
		listenaddr := fmt.Sprintf("%s:443", c.String("address"))
		server := &http.Server{Addr: listenaddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m}
		if err := server.ListenAndServeTLS(setting.HttpsCertFile, setting.HttpsKeyFile); err != nil {
			fmt.Printf("start wharf https service error: %v", err.Error())
		}
		break
	case "unix":
		listenaddr := fmt.Sprintf("%s", c.String("address"))
		if utils.Exist(listenaddr) {
			os.Remove(listenaddr)
		}

		if listener, err := net.Listen("unix", listenaddr); err != nil {
			fmt.Printf("start wharf unix socket error: %v", err.Error())
		} else {
			server := &http.Server{Handler: m}
			if err := server.Serve(listener); err != nil {
				fmt.Printf("start wharf unix socket error: %v", err.Error())
			}
		}
		break
	default:
		break
	}
}
<|endoftext|>


<commit_before>// list associated stations
package main

import (
	"flag"
	"fmt"
	"github.com/dim13/unifi"
	"log"
)

var (
	host    = flag.String("host", "unifi", "Controller hostname")
	user    = flag.String("user", "admin", "Controller username")
	pass    = flag.String("pass", "unifi", "Controller password")
	version = flag.Int("version", 2, "Controller base version")
	siteid  = flag.String("siteid", "default", "Site ID, UniFi v3 only")
)

func main() {
	flag.Parse()
	u, err := unifi.Login(*user, *pass, *host, *siteid, *version)
	if err != nil {
		log.Fatalln("Login returned error: ", err)
	}

	defer u.Logout()

	aps, err := u.Aps()
	if err != nil {
		log.Fatalln(err)
	}

	for _, s := range aps {
		fmt.Println(s.Mac, s.ModelName(), s.Name, s.Status())
	}
}
<commit_msg>Format output whith tabwriter<commit_after>// list associated stations
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"text/tabwriter"

	"github.com/dim13/unifi"
)

var (
	host    = flag.String("host", "unifi", "Controller hostname")
	user    = flag.String("user", "admin", "Controller username")
	pass    = flag.String("pass", "unifi", "Controller password")
	version = flag.Int("version", 2, "Controller base version")
	siteid  = flag.String("siteid", "default", "Site ID, UniFi v3 only")
)

func main() {
	w := new(tabwriter.Writer)
	w.Init(os.Stdout, 0, 8, 3, ' ', 0)
	defer w.Flush()

	flag.Parse()

	u, err := unifi.Login(*user, *pass, *host, *siteid, *version)
	if err != nil {
		log.Fatalln("Login returned error: ", err)
	}
	defer u.Logout()

	aps, err := u.Aps()
	if err != nil {
		log.Fatalln(err)
	}

	for _, s := range aps {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", s.Mac, s.ModelName(), s.Name, s.Status())
	}
}
<|endoftext|>