<commit_before>package bencoding

import (
	"fmt"
	"github.com/oleiade/lane"
	"strconv"
)

type ContainerType int

const (
	ContainerBString ContainerType = iota
	ContainerInteger
	ContainerList
	ContainerDict
)

type Container struct {
	Type    ContainerType
	BString string
	Integer int
	List    *[]Container
	Dict    map[string]Container
}

func (c *Container) String() string {
	switch c.Type {
	case ContainerBString:
		return c.BString
	case ContainerInteger:
		return fmt.Sprint(c.Integer)
	case ContainerList:
		substrs := make([]string, 0)
		for _, subContainer := range *c.List {
			substrs = append(substrs, subContainer.String())
		}
		return fmt.Sprint(substrs)
	default:
		substrs := make([]string, 0)
		substrs = append(substrs, "{")
		for key, val := range c.Dict {
			substrs = append(substrs, fmt.Sprint(key, ":", val.String(), ", "))
		}
		substrs = append(substrs, "}")
		return fmt.Sprint(substrs)
	}
}

func (c *Container) SetBString(val string) {
	c.BString = val
}

func (c *Container) SetInteger(val int) {
	c.Integer = val
}

func (c *Container) SetKey(key string, val Container) {
	c.Dict[key] = val
}

func (c *Container) Append(val Container) {
	*c.List = append(*c.List, val)
}

func (c *Container) Collapse() interface{} {
	switch c.Type {
	case ContainerBString:
		return c.BString
	case ContainerInteger:
		return c.Integer
	case ContainerList:
		listItems := make([]interface{}, 0)
		for _, subContainer := range *c.List {
			listItems = append(listItems, subContainer.Collapse())
		}
		return listItems
	case ContainerDict:
		dict := make(map[string]interface{})
		for key, val := range c.Dict {
			dict[key] = val.Collapse()
		}
		return dict
	default:
		panic(fmt.Sprint("UNKNOWN CONTAINER TYPE ", c.Type))
	}
}

/*
Parser keeps track of parsing state, corresponding tokens,
output data structure, etc.
*/
type Parser struct {
	Tokens []Token
	State  ParseFn
	Output interface{}
	Stack  *lane.Stack

	Pos int
	NextKey string
}

func (parser *Parser) CurrentType() TokenType {
	return parser.Tokens[parser.Pos].Type
}

func (parser *Parser) CurrentValue() string {
	return parser.Tokens[parser.Pos].Value
}

type ParseFn func(*Parser) ParseFn

/*
Parse takes a list of Tokens from the lexer and creates the final data structure.
*/
func Parse(tokens []Token) *Parser {
	parser := beginParsing(tokens, parseBegin)
	for parser.Pos < len(parser.Tokens) {
		if parser.State != nil {
			parser.State = parser.State(parser)
		} else {
			break
		}
	}
	return parser
}

/*
beginParsing initializes the Parser.
*/
func beginParsing(tokens []Token, state ParseFn) *Parser {
	p := &Parser{
		Tokens: tokens,
		State:  state,
		//		Output: make([]interface{}, 0),
		Stack: lane.NewStack(),
		Pos:   0,
	}

	//	p.CurrentContainer = p.Output
	return p
}

/*
parseBegin is the main state function to begin with and that
all other states eventually transition to.
*/
func parseBegin(parser *Parser) ParseFn {
	token := parser.Tokens[parser.Pos]
	switch token.Type {
	case TOKEN_STRING_LENGTH:
		return parseBString
	case TOKEN_INTEGER_START:
		return parseInteger
	case TOKEN_LIST_START:
		return parseList
	case TOKEN_LIST_END, TOKEN_DICT_END:
		parser.Pos++
		if parser.Stack.Size() > 1 {
			parser.Stack.Pop()
		}
		return parseBegin
	case TOKEN_DICT_START:
		return parseDict
	case TOKEN_COLON:
		// shouldn't get here directly
		return nil
	case TOKEN_STRING_VALUE:
		// shouldn't get here directly
		return nil
	default:
		container := parser.Stack.Head().(*Container)
		parser.Output = container.Collapse()
		return nil
	}
}

func parseBString(parser *Parser) ParseFn {
	// Get Length
	strLength, err := strconv.ParseInt(parser.CurrentValue(), 10, 64)
	if err != nil {
		panic("NOT A VALID STRING LENGTH")
	}
	parser.Pos++

	// Get Colon
	colon := parser.CurrentValue()
	if colon != ":" {
		panic("MISSING REQUIRED COLON")
	}
	parser.Pos++

	// Get Value
	strValue := parser.CurrentValue()
	if len(strValue) != int(strLength) {
		panic("STRING LENGTH DOESNT MATCH")
	}

	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			head.Append(Container{Type: ContainerBString, BString: strValue})
		case ContainerDict:
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, Container{Type: ContainerBString, BString: strValue})
				parser.NextKey = ""
			} else {
				parser.NextKey = strValue
			}
		}
	} else {
		container := &Container{Type: ContainerBString, BString: strValue}
		parser.Stack.Push(container)
	}

	parser.Pos++

	return parseBegin
}

func parseInteger(parser *Parser) ParseFn {
	//parser.CurrentValue() == TOKEN_INTEGER_START
	parser.Pos++

	num, err := strconv.ParseInt(parser.CurrentValue(), 10, 64)
	if err != nil {
		panic("NOT A VALID INTEGER")
	}

	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			head.Append(Container{Type: ContainerInteger, Integer: int(num)})
		case ContainerDict:
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, Container{Type: ContainerInteger, Integer: int(num)})
				parser.NextKey = ""
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerInteger, Integer: int(num)}
		parser.Stack.Push(&container)
	}
	parser.Pos++

	if parser.CurrentType() != TOKEN_INTEGER_END {
		panic("MISSING INTEGER END")
	}
	parser.Pos++

	return parseBegin
}

func parseList(parser *Parser) ParseFn {
	// "l"
	parser.Pos++

	list := make([]Container, 0)
	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			container := Container{Type: ContainerList, List: &list}
			head.Append(container)
			parser.Stack.Push(&container)
		case ContainerDict:
			container := Container{Type: ContainerList, List: &list}
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, container)
				parser.NextKey = ""
				parser.Stack.Push(&container)
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerList, List: &list}
		parser.Stack.Push(&container)
	}

	return parseBegin
}

func parseDict(parser *Parser) ParseFn {
	// "d"
	parser.Pos++

	dict := make(map[string]Container)
	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			container := Container{Type: ContainerDict, Dict: dict}
			head.Append(container)
			parser.Stack.Push(&container)
		case ContainerDict:
			container := Container{Type: ContainerDict, Dict: dict}
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, container)
				parser.NextKey = ""
				parser.Stack.Push(&container)
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerDict, Dict: dict}
		parser.Stack.Push(&container)
	}

	return parseBegin
}
<commit_msg>Cleaning up parseBegin state handling<commit_after>package bencoding

import (
	"fmt"
	"github.com/oleiade/lane"
	"strconv"
)

type ContainerType int

const (
	ContainerBString ContainerType = iota
	ContainerInteger
	ContainerList
	ContainerDict
)

type Container struct {
	Type    ContainerType
	BString string
	Integer int
	List    *[]Container
	Dict    map[string]Container
}

func (c *Container) String() string {
	switch c.Type {
	case ContainerBString:
		return c.BString
	case ContainerInteger:
		return fmt.Sprint(c.Integer)
	case ContainerList:
		substrs := make([]string, 0)
		for _, subContainer := range *c.List {
			substrs = append(substrs, subContainer.String())
		}
		return fmt.Sprint(substrs)
	default:
		substrs := make([]string, 0)
		substrs = append(substrs, "{")
		for key, val := range c.Dict {
			substrs = append(substrs, fmt.Sprint(key, ":", val.String(), ", "))
		}
		substrs = append(substrs, "}")
		return fmt.Sprint(substrs)
	}
}

func (c *Container) SetBString(val string) {
	c.BString = val
}

func (c *Container) SetInteger(val int) {
	c.Integer = val
}

func (c *Container) SetKey(key string, val Container) {
	c.Dict[key] = val
}

func (c *Container) Append(val Container) {
	*c.List = append(*c.List, val)
}

func (c *Container) Collapse() interface{} {
	switch c.Type {
	case ContainerBString:
		return c.BString
	case ContainerInteger:
		return c.Integer
	case ContainerList:
		listItems := make([]interface{}, 0)
		for _, subContainer := range *c.List {
			listItems = append(listItems, subContainer.Collapse())
		}
		return listItems
	case ContainerDict:
		dict := make(map[string]interface{})
		for key, val := range c.Dict {
			dict[key] = val.Collapse()
		}
		return dict
	default:
		panic(fmt.Sprint("UNKNOWN CONTAINER TYPE ", c.Type))
	}
}

/*
Parser keeps track of parsing state, corresponding tokens,
output data structure, etc.
*/
type Parser struct {
	Tokens []Token
	State  ParseFn
	Output interface{}
	Stack  *lane.Stack

	Pos int
	NextKey string
}

func (parser *Parser) CurrentType() TokenType {
	return parser.Tokens[parser.Pos].Type
}

func (parser *Parser) CurrentValue() string {
	return parser.Tokens[parser.Pos].Value
}

type ParseFn func(*Parser) ParseFn

/*
Parse takes a list of Tokens from the lexer and creates the final data structure.
*/
func Parse(tokens []Token) *Parser {
	parser := beginParsing(tokens, parseBegin)
	for parser.Pos < len(parser.Tokens) {
		if parser.State != nil {
			parser.State = parser.State(parser)
		} else {
			break
		}
	}
	return parser
}

/*
beginParsing initializes the Parser.
*/
func beginParsing(tokens []Token, state ParseFn) *Parser {
	p := &Parser{
		Tokens: tokens,
		State:  state,
		//		Output: make([]interface{}, 0),
		Stack: lane.NewStack(),
		Pos:   0,
	}

	//	p.CurrentContainer = p.Output
	return p
}

/*
parseBegin is the main state function to begin with and that
all other states eventually transition to.
*/
func parseBegin(parser *Parser) ParseFn {
	token := parser.Tokens[parser.Pos]
	switch token.Type {
	case TOKEN_STRING_LENGTH:
		return parseBString
	case TOKEN_INTEGER_START:
		return parseInteger
	case TOKEN_LIST_START:
		return parseList
	case TOKEN_DICT_START:
		return parseDict
	case TOKEN_LIST_END, TOKEN_DICT_END:
		// Pop stack so new items can be added to the parent container
		parser.Pos++
		if parser.Stack.Size() > 1 {
			parser.Stack.Pop()
		}
		return parseBegin
	case TOKEN_EOF:
		// TODO: Check if containers have been closed

		// Collapse root Container data structure into interface{}
		container := parser.Stack.Head().(*Container)
		parser.Output = container.Collapse()
		return nil
	default:
		// Some tokens should only be handled by other state functions
		fmt.Println("Current Token: ", parser.Pos, ", Total Tokens: ", len(parser.Tokens))
		panic(fmt.Sprint("UNEXPECTED TOKEN TYPE: ", token.Type))
	}
}

func parseBString(parser *Parser) ParseFn {
	// Get Length
	strLength, err := strconv.ParseInt(parser.CurrentValue(), 10, 64)
	if err != nil {
		panic("NOT A VALID STRING LENGTH")
	}
	parser.Pos++

	// Get Colon
	colon := parser.CurrentValue()
	if colon != ":" {
		panic("MISSING REQUIRED COLON")
	}
	parser.Pos++

	// Get Value
	strValue := parser.CurrentValue()
	if len(strValue) != int(strLength) {
		panic("STRING LENGTH DOESNT MATCH")
	}

	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			head.Append(Container{Type: ContainerBString, BString: strValue})
		case ContainerDict:
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, Container{Type: ContainerBString, BString: strValue})
				parser.NextKey = ""
			} else {
				parser.NextKey = strValue
			}
		}
	} else {
		container := &Container{Type: ContainerBString, BString: strValue}
		parser.Stack.Push(container)
	}

	parser.Pos++

	return parseBegin
}

func parseInteger(parser *Parser) ParseFn {
	//parser.CurrentValue() == TOKEN_INTEGER_START
	parser.Pos++

	num, err := strconv.ParseInt(parser.CurrentValue(), 10, 64)
	if err != nil {
		panic("NOT A VALID INTEGER")
	}

	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			head.Append(Container{Type: ContainerInteger, Integer: int(num)})
		case ContainerDict:
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, Container{Type: ContainerInteger, Integer: int(num)})
				parser.NextKey = ""
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerInteger, Integer: int(num)}
		parser.Stack.Push(&container)
	}
	parser.Pos++

	if parser.CurrentType() != TOKEN_INTEGER_END {
		panic("MISSING INTEGER END")
	}
	parser.Pos++

	return parseBegin
}

func parseList(parser *Parser) ParseFn {
	// "l"
	parser.Pos++

	list := make([]Container, 0)
	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			container := Container{Type: ContainerList, List: &list}
			head.Append(container)
			parser.Stack.Push(&container)
		case ContainerDict:
			container := Container{Type: ContainerList, List: &list}
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, container)
				parser.NextKey = ""
				parser.Stack.Push(&container)
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerList, List: &list}
		parser.Stack.Push(&container)
	}

	return parseBegin
}

func parseDict(parser *Parser) ParseFn {
	// "d"
	parser.Pos++

	dict := make(map[string]Container)
	if parser.Stack.Head() != nil {
		head := parser.Stack.Head().(*Container)
		switch head.Type {
		case ContainerBString:
			panic("CANT ADD TO STRING")
		case ContainerInteger:
			panic("CANT ADD TO INTEGER")
		case ContainerList:
			container := Container{Type: ContainerDict, Dict: dict}
			head.Append(container)
			parser.Stack.Push(&container)
		case ContainerDict:
			container := Container{Type: ContainerDict, Dict: dict}
			if parser.NextKey != "" {
				head.SetKey(parser.NextKey, container)
				parser.NextKey = ""
				parser.Stack.Push(&container)
			} else {
				panic("NO DICT KEY SET")
			}
		}
	} else {
		container := Container{Type: ContainerDict, Dict: dict}
		parser.Stack.Push(&container)
	}

	return parseBegin
}
<|endoftext|>


<commit_before>package beat

import (
	"bufio"
	"errors"
	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var blanks = regexp.MustCompile(`\s+`)

type Jstatbeat struct {
	// from configuration
	interval string
	name     string

	// state
	pid     string
	isAlive bool
}

func New() *Jstatbeat {
	return &Jstatbeat{}
}

func (jsb *Jstatbeat) Config(b *beat.Beat) error {
	var config ConfigSettings
	err := cfgfile.Read(&config, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	jsb.name = *config.Input.Name

	if config.Input.Interval != nil {
		jsb.interval = *config.Input.Interval
	} else {
		jsb.interval = "5000"
	}

	return nil
}

func (jsb *Jstatbeat) Setup(b *beat.Beat) error {
	cmd := exec.Command("jps")

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		logp.Err("Error get stdout pipe: %v", err)
		return err
	}

	cmd.Start()

	// TODO: handle error when 'jps' command cannot be executed.

	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		line := scanner.Text()
		items := strings.Split(line, " ")

		if len(items) == 2 && items[1] == jsb.name {
			jsb.pid = items[0]
			break
		}
	}
	cmd.Wait()

	if len(jsb.pid) == 0 {
		logp.Err("No target process: %v", jsb.name)
		return errors.New("No target process: " + jsb.name)
	}

	return nil
}

func (jsb *Jstatbeat) Run(b *beat.Beat) error {
	jsb.isAlive = true

	cmd := exec.Command("jstat", "-gc", "-t", jsb.pid, jsb.interval)
	stdout, err := cmd.StdoutPipe()

	if err != nil {
		logp.Err("Error get stdout pipe: %v", err)
		return err
	}

	cmd.Start()
	defer killProcess(cmd)

	scanner := bufio.NewScanner(stdout)
	var keys []string
	var version string
	for jsb.isAlive && scanner.Scan() {
		line := scanner.Text()

		values := blanks.Split(line, -1)

		if len(values) > 2 && values[0] == "Timestamp" {
			keys = values

			if strings.Contains(line, "CCSC") {
				version = "java8"
			} else {
				version = "java5"
			}

			continue
		}

		event := common.MapStr{
			"@timestamp": common.Time(time.Now()),
			"type":       version,
		}

		for i, key := range keys {
			if len(key) == 0 {
				continue
			}
			event[key] = toFloat(values[i+1])
		}
		b.Events.PublishEvent(event)
	}

	return nil
}

func killProcess(cmd *exec.Cmd) {
	if cmd.Process != nil {
		err := cmd.Process.Kill()
		if err != nil {
			logp.Err("Error killing jstat process: %v", err)
		}
	}
}

func toFloat(str string) float64 {
	value, err := strconv.ParseFloat(str, 64)

	if err != nil {
		logp.Err("Cannot parser to float. Ignore this value: %v", err)
		return 0
	}

	return value
}

func (jsb *Jstatbeat) Cleanup(b *beat.Beat) error {
	return nil
}

func (jsb *Jstatbeat) Stop() {
	jsb.isAlive = false
}
<commit_msg>Add pid and name<commit_after>package beat

import (
	"bufio"
	"errors"
	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var blanks = regexp.MustCompile(`\s+`)

type Jstatbeat struct {
	// from configuration
	interval string
	name     string

	// state
	pid     string
	isAlive bool
}

func New() *Jstatbeat {
	return &Jstatbeat{}
}

func (jsb *Jstatbeat) Config(b *beat.Beat) error {
	var config ConfigSettings
	err := cfgfile.Read(&config, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	jsb.name = *config.Input.Name

	if config.Input.Interval != nil {
		jsb.interval = *config.Input.Interval
	} else {
		jsb.interval = "5000"
	}

	return nil
}

func (jsb *Jstatbeat) Setup(b *beat.Beat) error {
	cmd := exec.Command("jps")

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		logp.Err("Error get stdout pipe: %v", err)
		return err
	}

	cmd.Start()

	// TODO: handle error when 'jps' command cannot be executed.

	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		line := scanner.Text()
		items := strings.Split(line, " ")

		if len(items) == 2 && items[1] == jsb.name {
			jsb.pid = items[0]
			break
		}
	}
	cmd.Wait()

	if len(jsb.pid) == 0 {
		logp.Err("No target process: %v", jsb.name)
		return errors.New("No target process: " + jsb.name)
	}

	return nil
}

func (jsb *Jstatbeat) Run(b *beat.Beat) error {
	jsb.isAlive = true

	cmd := exec.Command("jstat", "-gc", "-t", jsb.pid, jsb.interval)
	stdout, err := cmd.StdoutPipe()

	if err != nil {
		logp.Err("Error get stdout pipe: %v", err)
		return err
	}

	cmd.Start()
	defer killProcess(cmd)

	scanner := bufio.NewScanner(stdout)
	var keys []string
	var version string
	for jsb.isAlive && scanner.Scan() {
		line := scanner.Text()

		values := blanks.Split(line, -1)

		if len(values) > 2 && values[0] == "Timestamp" {
			keys = values

			if strings.Contains(line, "CCSC") {
				version = "java8"
			} else {
				version = "java5"
			}

			continue
		}

		event := common.MapStr{
			"@timestamp": common.Time(time.Now()),
			"type":       version,
			"pid":        jsb.pid,
			"name":       jsb.name,
		}

		for i, key := range keys {
			if len(key) == 0 {
				continue
			}
			event[key] = toFloat(values[i+1])
		}
		b.Events.PublishEvent(event)
	}

	return nil
}

func killProcess(cmd *exec.Cmd) {
	if cmd.Process != nil {
		err := cmd.Process.Kill()
		if err != nil {
			logp.Err("Error killing jstat process: %v", err)
		}
	}
}

func toFloat(str string) float64 {
	value, err := strconv.ParseFloat(str, 64)

	if err != nil {
		logp.Err("Cannot parser to float. Ignore this value: %v", err)
		return 0
	}

	return value
}

func (jsb *Jstatbeat) Cleanup(b *beat.Beat) error {
	return nil
}

func (jsb *Jstatbeat) Stop() {
	jsb.isAlive = false
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"os"
	"fmt"
	"strings"
	"log"
	"github.com/texttheater/golang-levenshtein/levenshtein"
	"math"
)

var (
	Input *bufio.Reader
	Namespace string
	Variables map[string]string
)

func prompt(text string) (string, error) {
	fmt.Printf("%s: ", text)
	response, err := Input.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.Trim(response, "\n"), nil
}

func mostSimilar(value string, targets []string) string {
	valueRunes := []rune(value)
	ops := levenshtein.Options{
		InsCost: 0,
		SubCost: 5,
		DelCost: 10,
		Matches: levenshtein.DefaultOptions.Matches,
	}

	distances := make(map[string]int, len(targets))
	for _, target := range targets {
		distances[target] = levenshtein.DistanceForStrings(valueRunes, []rune(target), ops)
	}

	best := struct {
		Distance int
		Value string
	}{math.MaxInt64,""}
	for target, distance := range distances {
		if distance < best.Distance {
			best.Distance = distance
			best.Value = target
		}
	}
	return best.Value
}

func pickNamespace() error {
	namespaces, err := GetNamespaces()
	if err != nil {
		return err
	}

	targets := make([]string, len(namespaces.Items))
	for num, ns := range namespaces.Items {
		fmt.Printf("$%d\t %s\n", num, ns.Name)
		targets[num] = ns.Name
	}

	response, err := prompt("Select namespace")
	if err != nil {
		return err
	}
	Namespace = mostSimilar(response, targets)
	return nil
}

func repl() error {
	command, err := prompt(Namespace)
	if err != nil {
		return err
	}

	for from, to := range Variables {
		command = strings.Replace(command, from, to, -1)
	}

	output, err := KubectlSh(command)

	if strings.HasPrefix(command, "get") {
		for index, line := range strings.Split(output, "\n") {
			key := fmt.Sprintf("$%d", index)
			Variables[key] = strings.Split(line, " ")[0]

			if strings.HasPrefix(line, "NAME ") {
				fmt.Printf("   \t%s\n", line)
			} else {
				fmt.Printf("$%v \t%s\n", index, line)
			}
		}
	} else {
		fmt.Println(output)
	}
	return err
}

func assert(v interface{}) {
	if v != nil {
		log.Fatal(v)
	}
}

func main() {
	Variables = make(map[string]string)
	Input = bufio.NewReader(os.Stdin)
	assert(KubernetesSetup())
	assert(pickNamespace())

	for {
		assert(repl())
	}
}
<commit_msg>variables skip header<commit_after>package main

import (
	"bufio"
	"os"
	"fmt"
	"strings"
	"log"
	"github.com/texttheater/golang-levenshtein/levenshtein"
	"math"
)

var (
	Input *bufio.Reader
	Namespace string
	Variables map[string]string
)

func prompt(text string) (string, error) {
	fmt.Print(text + " ")
	response, err := Input.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.Trim(response, "\n"), nil
}

func mostSimilar(value string, targets []string) string {
	valueRunes := []rune(value)
	ops := levenshtein.Options{
		InsCost: 0,
		SubCost: 5,
		DelCost: 10,
		Matches: levenshtein.DefaultOptions.Matches,
	}

	distances := make(map[string]int, len(targets))
	for _, target := range targets {
		distances[target] = levenshtein.DistanceForStrings(valueRunes, []rune(target), ops)
	}

	best := struct {
		Distance int
		Value string
	}{math.MaxInt64,""}
	for target, distance := range distances {
		if distance < best.Distance {
			best.Distance = distance
			best.Value = target
		}
	}
	return best.Value
}

func pickNamespace() error {
	namespaces, err := GetNamespaces()
	if err != nil {
		return err
	}

	targets := make([]string, len(namespaces.Items))
	for num, ns := range namespaces.Items {
		fmt.Printf("$%d\t %s\n", num, ns.Name)
		targets[num] = ns.Name
	}

	response, err := prompt("Select namespace:")
	if err != nil {
		return err
	}
	Namespace = mostSimilar(response, targets)
	return nil
}

func repl() error {
	command, err := prompt(Namespace)
	if err != nil {
		return err
	}

	for from, to := range Variables {
		command = strings.Replace(command, from, to, -1)
	}

	output, err := KubectlSh(command)

	if strings.HasPrefix(command, "get") {
		variableIndex := 0
		for _, line := range strings.Split(output, "\n") {
			if strings.HasPrefix(line, "NAME ") {
				fmt.Printf("   \t%s\n", line)
			} else {
				variableIndex++
				fmt.Printf("$%v \t%s\n", variableIndex, line)
			}
			key := fmt.Sprintf("$%d", variableIndex)
			Variables[key] = strings.Split(line, " ")[0]
		}
	} else {
		fmt.Println(output)
	}
	return err
}

func assert(v interface{}) {
	if v != nil {
		log.Fatal(v)
	}
}

func main() {
	Variables = make(map[string]string)
	Input = bufio.NewReader(os.Stdin)
	assert(KubernetesSetup())
	assert(pickNamespace())

	for {
		assert(repl())
	}
}
<|endoftext|>


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

package backend

import (
	"context"
	"sync"
	"time"

	"golang.org/x/time/rate"

	"go.chromium.org/luci/common/clock"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/sync/parallel"

	"go.chromium.org/luci/resultdb/internal/tasks"
)

type invocationProcessor struct {
	bqExporter
}

// permanentInvocationTaskErrTag set in an error indicates that the err is not
// resolvable by retry.
var permanentInvocationTaskErrTag = errors.BoolTag{
	Key: errors.NewTagKey("permanent failure to process invocation task"),
}

func (ip *invocationProcessor) dispatchInvocationTasks(ctx context.Context, taskType tasks.Type, ids []string) (processed []string, err error) {
	leaseDuration := time.Minute
	switch taskType {
	case tasks.TryFinalizeInvocation:
		leaseDuration = 10 * time.Second
	}

	var mu sync.Mutex
	err = parallel.WorkPool(10, func(workC chan<- func() error) {
		for _, id := range ids {
			id := id
			ctx := logging.SetField(ctx, "task_id", id)
			workC <- func() (err error) {
				startTime := clock.Now(ctx)
				taskStatus := transientFailure

				defer func() {
					// Send metrics to tsmon.
					typeStr := string(taskType)

					duration := float64(time.Since(startTime).Milliseconds())
					durationMetric.Add(ctx, duration, typeStr, taskStatus)

					taskAttemptMetric.Add(ctx, 1, typeStr, taskStatus)

					// Annotate the returned error with the task id.
					if err != nil {
						err = errors.Annotate(err, "failed to process task %s", id).Err()
					}
				}()

				invID, payload, err := tasks.Lease(ctx, taskType, id, leaseDuration)
				switch {
				case err == tasks.ErrConflict:
					// It's possible another worker has leased the task, and it's fine, skip.
					return nil
				case err != nil:
					return err
				}

				switch taskType {
				case tasks.BQExport:
					err = ip.exportResultsToBigQuery(ctx, invID, payload)
				case tasks.TryFinalizeInvocation:
					err = tryFinalizeInvocation(ctx, invID)
				default:
					err = errors.Reason("unexpected task type %q", taskType).Err()
				}
				if err != nil {
					if permanentInvocationTaskErrTag.In(err) {
						taskStatus = permanentFailure
						logging.Errorf(ctx, "permanent failure to process the task: %s", err)
						return tasks.Delete(ctx, taskType, id)
					}
					return err
				}

				// Invocation task is done, delete the row from spanner.
				if err := tasks.Delete(ctx, taskType, id); err != nil {
					return err
				}

				mu.Lock()
				processed = append(processed, id)
				mu.Unlock()
				taskStatus = success
				return nil
			}
		}
	})
	return
}

// runInvocationTasks gets invocation tasks and dispatches them to workers.
func runInvocationTasks(ctx context.Context, taskType tasks.Type) {
	mCtx, cancel := context.WithCancel(ctx)
	defer cancel()
	go processingLoop(ctx, time.Minute, time.Minute, time.Minute, func(ctx context.Context) error {
		recordOldestTaskMetric(mCtx, taskType)
		return nil
	})

	processingLoop(ctx, time.Second, 5*time.Second, 10*time.Minute, func(ctx context.Context) error {
		ids, err := tasks.Sample(ctx, taskType, time.Now(), 100)
		if err != nil {
			return errors.Annotate(err, "failed to query invocation tasks").Err()
		}

		ip := &invocationProcessor{
			bqExporter: bqExporter{
				maxBatchRowCount: maxBatchRowCount,
				maxBatchSize:     maxBatchSize,
				limit:            rate.NewLimiter(100, 1),
			},
		}
		processed, err := ip.dispatchInvocationTasks(ctx, taskType, ids)
		if len(processed) > 0 {
			logging.Infof(ctx, "processed tasks: %q", processed)
		}
		return err
	})
}
<commit_msg>[resultdb] Use FanOutIn when dispatch invocation tasks<commit_after>// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package backend

import (
	"context"
	"sync"
	"time"

	"golang.org/x/time/rate"

	"go.chromium.org/luci/common/clock"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/sync/parallel"

	"go.chromium.org/luci/resultdb/internal/tasks"
)

type invocationProcessor struct {
	bqExporter
}

// permanentInvocationTaskErrTag set in an error indicates that the err is not
// resolvable by retry.
var permanentInvocationTaskErrTag = errors.BoolTag{
	Key: errors.NewTagKey("permanent failure to process invocation task"),
}

func (ip *invocationProcessor) dispatchInvocationTasks(ctx context.Context, taskType tasks.Type, ids []string) (processed []string, err error) {
	leaseDuration := time.Minute
	switch taskType {
	case tasks.TryFinalizeInvocation:
		leaseDuration = 10 * time.Second
	}

	var mu sync.Mutex
	err = parallel.FanOutIn(func(workC chan<- func() error) {
		for _, id := range ids {
			id := id
			ctx := logging.SetField(ctx, "task_id", id)
			workC <- func() (err error) {
				startTime := clock.Now(ctx)
				taskStatus := transientFailure

				defer func() {
					// Send metrics to tsmon.
					typeStr := string(taskType)

					duration := float64(time.Since(startTime).Milliseconds())
					durationMetric.Add(ctx, duration, typeStr, taskStatus)

					taskAttemptMetric.Add(ctx, 1, typeStr, taskStatus)

					// Annotate the returned error with the task id.
					if err != nil {
						err = errors.Annotate(err, "failed to process task %s", id).Err()
					}
				}()

				invID, payload, err := tasks.Lease(ctx, taskType, id, leaseDuration)
				switch {
				case err == tasks.ErrConflict:
					// It's possible another worker has leased the task, and it's fine, skip.
					return nil
				case err != nil:
					return err
				}

				switch taskType {
				case tasks.BQExport:
					err = ip.exportResultsToBigQuery(ctx, invID, payload)
				case tasks.TryFinalizeInvocation:
					err = tryFinalizeInvocation(ctx, invID)
				default:
					err = errors.Reason("unexpected task type %q", taskType).Err()
				}
				if err != nil {
					if permanentInvocationTaskErrTag.In(err) {
						taskStatus = permanentFailure
						logging.Errorf(ctx, "permanent failure to process the task: %s", err)
						return tasks.Delete(ctx, taskType, id)
					}
					return err
				}

				// Invocation task is done, delete the row from spanner.
				if err := tasks.Delete(ctx, taskType, id); err != nil {
					return err
				}

				mu.Lock()
				processed = append(processed, id)
				mu.Unlock()
				taskStatus = success
				return nil
			}
		}
	})
	return
}

// runInvocationTasks gets invocation tasks and dispatches them to workers.
func runInvocationTasks(ctx context.Context, taskType tasks.Type) {
	mCtx, cancel := context.WithCancel(ctx)
	defer cancel()
	go processingLoop(ctx, time.Minute, time.Minute, time.Minute, func(ctx context.Context) error {
		recordOldestTaskMetric(mCtx, taskType)
		return nil
	})

	processingLoop(ctx, time.Second, 5*time.Second, 10*time.Minute, func(ctx context.Context) error {
		ids, err := tasks.Sample(ctx, taskType, time.Now(), 100)
		if err != nil {
			return errors.Annotate(err, "failed to query invocation tasks").Err()
		}

		ip := &invocationProcessor{
			bqExporter: bqExporter{
				maxBatchRowCount: maxBatchRowCount,
				maxBatchSize:     maxBatchSize,
				limit:            rate.NewLimiter(100, 1),
			},
		}
		processed, err := ip.dispatchInvocationTasks(ctx, taskType, ids)
		if len(processed) > 0 {
			logging.Infof(ctx, "processed tasks: %q", processed)
		}
		return err
	})
}
<|endoftext|>


<commit_before>package testing

import (
	"sort"

	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/storage"
)

// BaseRepoSuite sets up a local directory containing charms.
type BaseRepoSuite struct {
	CharmsPath string
}

func (s *BaseRepoSuite) SetUpSuite(c *gc.C)    {}
func (s *BaseRepoSuite) TearDownSuite(c *gc.C) {}

func (s *BaseRepoSuite) SetUpTest(c *gc.C) {
	s.CharmsPath = c.MkDir()
}

type RepoSuite struct {
	JujuConnSuite
	BaseRepoSuite
}

func (s *RepoSuite) SetUpSuite(c *gc.C) {
	s.JujuConnSuite.SetUpSuite(c)
	s.BaseRepoSuite.SetUpSuite(c)
}

func (s *RepoSuite) TearDownSuite(c *gc.C) {
	s.BaseRepoSuite.TearDownSuite(c)
	s.JujuConnSuite.TearDownSuite(c)
}

func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	s.BaseRepoSuite.SetUpTest(c)
	// Change the environ's config to ensure we're using the one in state.
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateModelConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
}

func (s *RepoSuite) TearDownTest(c *gc.C) {
	s.JujuConnSuite.TearDownTest(c)
}

func (s *RepoSuite) AssertService(c *gc.C, name string, expectCurl *charm.URL, unitCount, relCount int) (*state.Service, []*state.Relation) {
	svc, err := s.State.Service(name)
	c.Assert(err, jc.ErrorIsNil)
	ch, _, err := svc.Charm()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ch.URL(), gc.DeepEquals, expectCurl)
	s.AssertCharmUploaded(c, expectCurl)

	units, err := svc.AllUnits()
	c.Logf("Service units: %+v", units)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(units, gc.HasLen, unitCount)
	s.AssertUnitMachines(c, units)
	rels, err := svc.Relations()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(rels, gc.HasLen, relCount)
	return svc, rels
}

func (s *RepoSuite) AssertCharmUploaded(c *gc.C, curl *charm.URL) {
	ch, err := s.State.Charm(curl)
	c.Assert(err, jc.ErrorIsNil)

	storage := storage.NewStorage(s.State.ModelUUID(), s.State.MongoSession())
	r, _, err := storage.Get(ch.StoragePath())
	c.Assert(err, jc.ErrorIsNil)
	defer r.Close()

	digest, _, err := utils.ReadSHA256(r)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ch.BundleSha256(), gc.Equals, digest)
}

func (s *RepoSuite) AssertUnitMachines(c *gc.C, units []*state.Unit) {
	tags := make([]names.UnitTag, len(units))
	expectUnitNames := make([]string, len(units))
	for i, u := range units {
		expectUnitNames[i] = u.Name()
		tags[i] = u.UnitTag()
	}

	// manually assign all units to machines.  This replaces work normally done
	// by the unitassigner code.
	errs, err := s.APIState.UnitAssigner().AssignUnits(tags)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(errs, gc.DeepEquals, make([]error, len(units)))

	sort.Strings(expectUnitNames)

	machines, err := s.State.AllMachines()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(machines, gc.HasLen, len(units))

	unitNames := []string{}
	for _, m := range machines {
		mUnits, err := m.Units()
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(mUnits, gc.HasLen, 1)
		unitNames = append(unitNames, mUnits[0].Name())
	}
	sort.Strings(unitNames)
	c.Assert(unitNames, gc.DeepEquals, expectUnitNames)
}
<commit_msg>Remove unneeded suite and calls.<commit_after>package testing

import (
	"sort"

	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/storage"
)

type RepoSuite struct {
	JujuConnSuite
	CharmsPath string
}

func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	s.CharmsPath = c.MkDir()
	// Change the environ's config to ensure we're using the one in state.
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateModelConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
}

func (s *RepoSuite) AssertService(c *gc.C, name string, expectCurl *charm.URL, unitCount, relCount int) (*state.Service, []*state.Relation) {
	svc, err := s.State.Service(name)
	c.Assert(err, jc.ErrorIsNil)
	ch, _, err := svc.Charm()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ch.URL(), gc.DeepEquals, expectCurl)
	s.AssertCharmUploaded(c, expectCurl)

	units, err := svc.AllUnits()
	c.Logf("Service units: %+v", units)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(units, gc.HasLen, unitCount)
	s.AssertUnitMachines(c, units)
	rels, err := svc.Relations()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(rels, gc.HasLen, relCount)
	return svc, rels
}

func (s *RepoSuite) AssertCharmUploaded(c *gc.C, curl *charm.URL) {
	ch, err := s.State.Charm(curl)
	c.Assert(err, jc.ErrorIsNil)

	storage := storage.NewStorage(s.State.ModelUUID(), s.State.MongoSession())
	r, _, err := storage.Get(ch.StoragePath())
	c.Assert(err, jc.ErrorIsNil)
	defer r.Close()

	digest, _, err := utils.ReadSHA256(r)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ch.BundleSha256(), gc.Equals, digest)
}

func (s *RepoSuite) AssertUnitMachines(c *gc.C, units []*state.Unit) {
	tags := make([]names.UnitTag, len(units))
	expectUnitNames := make([]string, len(units))
	for i, u := range units {
		expectUnitNames[i] = u.Name()
		tags[i] = u.UnitTag()
	}

	// manually assign all units to machines.  This replaces work normally done
	// by the unitassigner code.
	errs, err := s.APIState.UnitAssigner().AssignUnits(tags)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(errs, gc.DeepEquals, make([]error, len(units)))

	sort.Strings(expectUnitNames)

	machines, err := s.State.AllMachines()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(machines, gc.HasLen, len(units))

	unitNames := []string{}
	for _, m := range machines {
		mUnits, err := m.Units()
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(mUnits, gc.HasLen, 1)
		unitNames = append(unitNames, mUnits[0].Name())
	}
	sort.Strings(unitNames)
	c.Assert(unitNames, gc.DeepEquals, expectUnitNames)
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package e2e

// Put common test fixtures (e.g. resources to be created) here.

import (
	"github.com/golang/glog"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
)

const (
	echoheadersImage = "k8s.gcr.io/echoserver:1.10"
)

// CreateEchoService creates the pod and service serving echoheaders.
func CreateEchoService(s *Sandbox, name string, annotations map[string]string) (*v1.Pod, *v1.Service, error) {
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:        name,
			Labels:      map[string]string{"app": name},
			Annotations: annotations,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  "web",
					Image: echoheadersImage,
					Ports: []v1.ContainerPort{{ContainerPort: 8080, Name: "web"}},
				},
			},
		},
	}
	service := &v1.Service{
		ObjectMeta: metav1.ObjectMeta{Name: name},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{{
				Name:       "web",
				Protocol:   v1.ProtocolTCP,
				Port:       80,
				TargetPort: intstr.FromString("web"),
			}},
			Selector: map[string]string{"app": name},
			Type:     v1.ServiceTypeNodePort,
		},
	}
	var err error
	if pod, err = s.f.Clientset.Core().Pods(s.Namespace).Create(pod); err != nil {
		return nil, nil, err
	}
	if service, err = s.f.Clientset.Core().Services(s.Namespace).Create(service); err != nil {
		return nil, nil, err
	}
	glog.V(2).Infof("Echo service %q:%q created", s.Namespace, name)

	return pod, service, nil
}

// CreateSecret creates a secret from the given data.
func CreateSecret(s *Sandbox, name string, data map[string][]byte) (*v1.Secret, error) {
	secret := &v1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Data: data,
	}
	var err error
	if secret, err = s.f.Clientset.Core().Secrets(s.Namespace).Create(secret); err != nil {
		return nil, err
	}
	glog.V(2).Infof("Secret %q:%q created", s.Namespace, name)

	return secret, nil
}
<commit_msg>Assign annotations to service instead of pod<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package e2e

// Put common test fixtures (e.g. resources to be created) here.

import (
	"github.com/golang/glog"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
)

const (
	echoheadersImage = "k8s.gcr.io/echoserver:1.10"
)

// CreateEchoService creates the pod and service serving echoheaders.
func CreateEchoService(s *Sandbox, name string, annotations map[string]string) (*v1.Pod, *v1.Service, error) {
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:   name,
			Labels: map[string]string{"app": name},
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  "web",
					Image: echoheadersImage,
					Ports: []v1.ContainerPort{{ContainerPort: 8080, Name: "web"}},
				},
			},
		},
	}
	service := &v1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:        name,
			Annotations: annotations,
		},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{{
				Name:       "web",
				Protocol:   v1.ProtocolTCP,
				Port:       80,
				TargetPort: intstr.FromString("web"),
			}},
			Selector: map[string]string{"app": name},
			Type:     v1.ServiceTypeNodePort,
		},
	}
	var err error
	if pod, err = s.f.Clientset.Core().Pods(s.Namespace).Create(pod); err != nil {
		return nil, nil, err
	}
	if service, err = s.f.Clientset.Core().Services(s.Namespace).Create(service); err != nil {
		return nil, nil, err
	}
	glog.V(2).Infof("Echo service %q:%q created", s.Namespace, name)

	return pod, service, nil
}

// CreateSecret creates a secret from the given data.
func CreateSecret(s *Sandbox, name string, data map[string][]byte) (*v1.Secret, error) {
	secret := &v1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Data: data,
	}
	var err error
	if secret, err = s.f.Clientset.Core().Secrets(s.Namespace).Create(secret); err != nil {
		return nil, err
	}
	glog.V(2).Infof("Secret %q:%q created", s.Namespace, name)

	return secret, nil
}
<|endoftext|>


<commit_before>package main
import (
	"net/http"
	"log"
	"os"
	"github.com/AtomasBots/atomas_server_hook/atomas"
	"os/exec"
	"time"
	"io/ioutil"
)

var version string

func doOnHook() {
	exec.Command("bash", "onhook").Start()
}

func main() {
	hooks := atomas.Hooks{[]string{}}
	http.HandleFunc("/hook", atomas.CreateHookHandler(&hooks, doOnHook))
	http.HandleFunc("/hook_list", atomas.CreateHookListHandler(&hooks))
	http.HandleFunc("/health", atomas.CreateHealthService())
	http.HandleFunc("/version", atomas.CreateVersionHandler(version))
	port := os.Args[1]
	go doOnHook()
	log.Fatal(http.ListenAndServe(port, nil))
}
<commit_msg>remove imports<commit_after>package main
import (
	"net/http"
	"log"
	"os"
	"github.com/AtomasBots/atomas_server_hook/atomas"
	"os/exec"
)

var version string

func doOnHook() {
	exec.Command("bash", "onhook").Start()
}

func main() {
	hooks := atomas.Hooks{[]string{}}
	http.HandleFunc("/hook", atomas.CreateHookHandler(&hooks, doOnHook))
	http.HandleFunc("/hook_list", atomas.CreateHookListHandler(&hooks))
	http.HandleFunc("/health", atomas.CreateHealthService())
	http.HandleFunc("/version", atomas.CreateVersionHandler(version))
	port := os.Args[1]
	go doOnHook()
	log.Fatal(http.ListenAndServe(port, nil))
}
<|endoftext|>


<commit_before>// Copyright 2015 gandalf 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 hook

import (
	"io/ioutil"
	"os"
	"testing"

	"github.com/tsuru/commandmocker"
	"github.com/tsuru/config"
	"github.com/tsuru/gandalf/db"
	"github.com/tsuru/gandalf/fs"
	"github.com/tsuru/tsuru/fs/fstest"
	"gopkg.in/check.v1"
)

func Test(t *testing.T) { check.TestingT(t) }

type S struct {
	tmpdir string
	rfs    *fstest.RecordingFs
}

var _ = check.Suite(&S{})

func (s *S) SetUpSuite(c *check.C) {
	err := config.ReadConfigFile("../etc/gandalf.conf")
	c.Assert(err, check.IsNil)
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "gandalf_api_tests")
	s.tmpdir, err = commandmocker.Add("git", "")
	c.Assert(err, check.IsNil)
}

func (s *S) SetUpTest(c *check.C) {
	s.rfs = &fstest.RecordingFs{}
	fs.Fsystem = s.rfs
	bareTemplate, _ := config.GetString("git:bare:template")
	fs.Fsystem.MkdirAll(bareTemplate+"/hooks", 0755)
}

func (s *S) TearDownTest(c *check.C) {
	fs.Fsystem = nil
}

func (s *S) TearDownSuite(c *check.C) {
	commandmocker.Remove(s.tmpdir)
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	conn.User().Database.DropDatabase()
}

func (s *S) TestCanCreateHookFile(c *check.C) {
	hookContent := []byte("some content")
	err := createHookFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewHook(c *check.C) {
	hookContent := []byte("some content")
	err := Add("test-can-add-new-hook", []string{}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewHookInOldRepository(c *check.C) {
	s.rfs = &fstest.RecordingFs{}
	fs.Fsystem = s.rfs
	bareTemplate, _ := config.GetString("git:bare:template")
	err := fs.Fsystem.RemoveAll(bareTemplate + "/hooks")
	c.Assert(err, check.IsNil)
	hookContent := []byte("some content")
	err = Add("test-can-add-new-hook", []string{}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewRepository(c *check.C) {
	hookContent := []byte("some content")
	err := Add("test-can-add-new-repository-hook", []string{"some-repo"}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-add-new-repository-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}
<commit_msg>hook: change test collection name to avoid conflict with api pkg<commit_after>// Copyright 2015 gandalf 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 hook

import (
	"io/ioutil"
	"os"
	"testing"

	"github.com/tsuru/commandmocker"
	"github.com/tsuru/config"
	"github.com/tsuru/gandalf/db"
	"github.com/tsuru/gandalf/fs"
	"github.com/tsuru/tsuru/fs/fstest"
	"gopkg.in/check.v1"
)

func Test(t *testing.T) { check.TestingT(t) }

type S struct {
	tmpdir string
	rfs    *fstest.RecordingFs
}

var _ = check.Suite(&S{})

func (s *S) SetUpSuite(c *check.C) {
	err := config.ReadConfigFile("../etc/gandalf.conf")
	c.Assert(err, check.IsNil)
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "gandalf_hooks_tests")
	s.tmpdir, err = commandmocker.Add("git", "")
	c.Assert(err, check.IsNil)
}

func (s *S) SetUpTest(c *check.C) {
	s.rfs = &fstest.RecordingFs{}
	fs.Fsystem = s.rfs
	bareTemplate, _ := config.GetString("git:bare:template")
	fs.Fsystem.MkdirAll(bareTemplate+"/hooks", 0755)
}

func (s *S) TearDownTest(c *check.C) {
	fs.Fsystem = nil
}

func (s *S) TearDownSuite(c *check.C) {
	commandmocker.Remove(s.tmpdir)
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	conn.User().Database.DropDatabase()
}

func (s *S) TestCanCreateHookFile(c *check.C) {
	hookContent := []byte("some content")
	err := createHookFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewHook(c *check.C) {
	hookContent := []byte("some content")
	err := Add("test-can-add-new-hook", []string{}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewHookInOldRepository(c *check.C) {
	s.rfs = &fstest.RecordingFs{}
	fs.Fsystem = s.rfs
	bareTemplate, _ := config.GetString("git:bare:template")
	err := fs.Fsystem.RemoveAll(bareTemplate + "/hooks")
	c.Assert(err, check.IsNil)
	hookContent := []byte("some content")
	err = Add("test-can-add-new-hook", []string{}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}

func (s *S) TestCanAddNewRepository(c *check.C) {
	hookContent := []byte("some content")
	err := Add("test-can-add-new-repository-hook", []string{"some-repo"}, hookContent)
	c.Assert(err, check.IsNil)
	file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-add-new-repository-hook", os.O_RDONLY, 0755)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	c.Assert(err, check.IsNil)
	c.Assert(string(content), check.Equals, "some content")
}
<|endoftext|>


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

package main

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"regexp"
	"strings"
	"unicode/utf8"

	"github.com/minio/minio/pkg/safe"
)

const (
	// Minio meta volume.
	minioMetaVolume = ".minio"
)

// validBucket regexp.
var validBucket = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`)

// IsValidBucketName verifies a bucket name in accordance with Amazon's
// requirements. It must be 3-63 characters long, can contain dashes
// and periods, but must begin and end with a lowercase letter or a number.
// See: http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
func IsValidBucketName(bucket string) bool {
	if len(bucket) < 3 || len(bucket) > 63 {
		return false
	}
	if bucket[0] == '.' || bucket[len(bucket)-1] == '.' {
		return false
	}
	return validBucket.MatchString(bucket)
}

// IsValidObjectName verifies an object name in accordance with Amazon's
// requirements. It cannot exceed 1024 characters and must be a valid UTF8
// string.
//
// See:
// http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
//
// You should avoid the following characters in a key name because of
// significant special handling for consistency across all
// applications.
//
// Rejects strings with following characters.
//
// - Backslash ("\")
// - Left curly brace ("{")
// - Caret ("^")
// - Right curly brace ("}")
// - Grave accent / back tick ("`")
// - Tilde ("~")
// - 'Greater Than' symbol (">")
// - 'Less Than' symbol ("<")
// - Vertical bar / pipe ("|")
func IsValidObjectName(object string) bool {
	if len(object) > 1024 || len(object) == 0 {
		return false
	}
	if !utf8.ValidString(object) {
		return false
	}
	// Reject unsupported characters in object name.
	return !strings.ContainsAny(object, "`^*{}|\\\"'")
}

// IsValidObjectPrefix verifies whether the prefix is a valid object name.
// Its valid to have a empty prefix.
func IsValidObjectPrefix(object string) bool {
	// Prefix can be empty or "/".
	if object == "" || object == "/" {
		return true
	}
	// Verify if prefix is a valid object name.
	return IsValidObjectName(object)

}

// Slash separator.
const slashSeparator = "/"

// retainSlash - retains slash from a path.
func retainSlash(s string) string {
	return strings.TrimSuffix(s, slashSeparator) + slashSeparator
}

// pathJoin - path join.
func pathJoin(s1 string, s2 string) string {
	return retainSlash(s1) + s2
}

// Create an s3 compatible MD5sum for complete multipart transaction.
func makeS3MD5(md5Strs ...string) (string, error) {
	var finalMD5Bytes []byte
	for _, md5Str := range md5Strs {
		md5Bytes, err := hex.DecodeString(md5Str)
		if err != nil {
			return "", err
		}
		finalMD5Bytes = append(finalMD5Bytes, md5Bytes...)
	}
	md5Hasher := md5.New()
	md5Hasher.Write(finalMD5Bytes)
	s3MD5 := fmt.Sprintf("%s-%d", hex.EncodeToString(md5Hasher.Sum(nil)), len(md5Strs))
	return s3MD5, nil
}

// byBucketName is a collection satisfying sort.Interface.
type byBucketName []BucketInfo

func (d byBucketName) Len() int           { return len(d) }
func (d byBucketName) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }
func (d byBucketName) Less(i, j int) bool { return d[i].Name < d[j].Name }

// safeCloseAndRemove - safely closes and removes underlying temporary
// file writer if possible.
func safeCloseAndRemove(writer io.WriteCloser) error {
	// If writer is a safe file, Attempt to close and remove.
	safeWriter, ok := writer.(*safe.File)
	if ok {
		return safeWriter.CloseAndRemove()
	}
	pipeWriter, ok := writer.(*io.PipeWriter)
	if ok {
		return pipeWriter.CloseWithError(errors.New("Close and error out."))
	}
	return nil
}
<commit_msg>obj: support object names with curly braces. (#1429)<commit_after>/*
 * Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"regexp"
	"strings"
	"unicode/utf8"

	"github.com/minio/minio/pkg/safe"
)

const (
	// Minio meta volume.
	minioMetaVolume = ".minio"
)

// validBucket regexp.
var validBucket = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`)

// IsValidBucketName verifies a bucket name in accordance with Amazon's
// requirements. It must be 3-63 characters long, can contain dashes
// and periods, but must begin and end with a lowercase letter or a number.
// See: http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
func IsValidBucketName(bucket string) bool {
	if len(bucket) < 3 || len(bucket) > 63 {
		return false
	}
	if bucket[0] == '.' || bucket[len(bucket)-1] == '.' {
		return false
	}
	return validBucket.MatchString(bucket)
}

// IsValidObjectName verifies an object name in accordance with Amazon's
// requirements. It cannot exceed 1024 characters and must be a valid UTF8
// string.
//
// See:
// http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
//
// You should avoid the following characters in a key name because of
// significant special handling for consistency across all
// applications.
//
// Rejects strings with following characters.
//
// - Backslash ("\")
// - Caret ("^")
// - Grave accent / back tick ("`")
// - Vertical bar / pipe ("|")
func IsValidObjectName(object string) bool {
	if len(object) > 1024 || len(object) == 0 {
		return false
	}
	if !utf8.ValidString(object) {
		return false
	}
	// Reject unsupported characters in object name.
	return !strings.ContainsAny(object, "`^*|\\\"")
}

// IsValidObjectPrefix verifies whether the prefix is a valid object name.
// Its valid to have a empty prefix.
func IsValidObjectPrefix(object string) bool {
	// Prefix can be empty or "/".
	if object == "" || object == "/" {
		return true
	}
	// Verify if prefix is a valid object name.
	return IsValidObjectName(object)

}

// Slash separator.
const slashSeparator = "/"

// retainSlash - retains slash from a path.
func retainSlash(s string) string {
	return strings.TrimSuffix(s, slashSeparator) + slashSeparator
}

// pathJoin - path join.
func pathJoin(s1 string, s2 string) string {
	return retainSlash(s1) + s2
}

// Create an s3 compatible MD5sum for complete multipart transaction.
func makeS3MD5(md5Strs ...string) (string, error) {
	var finalMD5Bytes []byte
	for _, md5Str := range md5Strs {
		md5Bytes, err := hex.DecodeString(md5Str)
		if err != nil {
			return "", err
		}
		finalMD5Bytes = append(finalMD5Bytes, md5Bytes...)
	}
	md5Hasher := md5.New()
	md5Hasher.Write(finalMD5Bytes)
	s3MD5 := fmt.Sprintf("%s-%d", hex.EncodeToString(md5Hasher.Sum(nil)), len(md5Strs))
	return s3MD5, nil
}

// byBucketName is a collection satisfying sort.Interface.
type byBucketName []BucketInfo

func (d byBucketName) Len() int           { return len(d) }
func (d byBucketName) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }
func (d byBucketName) Less(i, j int) bool { return d[i].Name < d[j].Name }

// safeCloseAndRemove - safely closes and removes underlying temporary
// file writer if possible.
func safeCloseAndRemove(writer io.WriteCloser) error {
	// If writer is a safe file, Attempt to close and remove.
	safeWriter, ok := writer.(*safe.File)
	if ok {
		return safeWriter.CloseAndRemove()
	}
	pipeWriter, ok := writer.(*io.PipeWriter)
	if ok {
		return pipeWriter.CloseWithError(errors.New("Close and error out."))
	}
	return nil
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package executor

import (
	"fmt"
	"os"
	"testing"

	"github.com/mesos/mesos-go/healthchecker"
	"github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	"github.com/mesos/mesos-go/messenger"
	"github.com/mesos/mesos-go/upid"
	"github.com/stretchr/testify/assert"
)

var (
	slavePID    = "slave(1)@127.0.0.1:8080"
	slaveID     = "some-slave-id-uuid"
	frameworkID = "some-framework-id-uuid"
	executorID  = "some-executor-id-uuid"
)

func setEnvironments(t *testing.T, workDir string, checkpoint bool) {
	assert.NoError(t, os.Setenv("MESOS_SLAVE_PID", slavePID))
	assert.NoError(t, os.Setenv("MESOS_SLAVE_ID", slaveID))
	assert.NoError(t, os.Setenv("MESOS_FRAMEWORK_ID", frameworkID))
	assert.NoError(t, os.Setenv("MESOS_EXECUTOR_ID", executorID))
	if len(workDir) > 0 {
		assert.NoError(t, os.Setenv("MESOS_DIRECTORY", workDir))
	}
	if checkpoint {
		assert.NoError(t, os.Setenv("MESOS_CHECKPOINT", "1"))
	}
}

func clearEnvironments(t *testing.T) {
	assert.NoError(t, os.Setenv("MESOS_SLAVE_PID", ""))
	assert.NoError(t, os.Setenv("MESOS_SLAVE_ID", ""))
	assert.NoError(t, os.Setenv("MESOS_FRAMEWORK_ID", ""))
	assert.NoError(t, os.Setenv("MESOS_EXECUTOR_ID", ""))
}

func newTestExecutorDriver(t *testing.T, exec Executor) *MesosExecutorDriver {
	dconfig := DriverConfig{
		Executor: exec,
	}
	driver, err := NewMesosExecutorDriver(dconfig)
	if err != nil {
		t.Fatal(err)
	}
	return driver
}

type testExecutorDriver struct {
	*MesosExecutorDriver
}

func (e *testExecutorDriver) setConnected(b bool) {
	e.lock.Lock()
	defer e.lock.Unlock()
	e.connected = b
}

func createTestExecutorDriver(t *testing.T) (
	*testExecutorDriver,
	*messenger.MockedMessenger,
	*healthchecker.MockedHealthChecker) {

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)

	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	checker := healthchecker.NewMockedHealthChecker()
	checker.On("Start").Return()
	checker.On("Stop").Return()

	driver.messenger = messenger
	return &testExecutorDriver{driver}, messenger, checker
}

func TestExecutorDriverStartFailedToParseEnvironment(t *testing.T) {
	clearEnvironments(t)
	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)
	dconfig := DriverConfig{Executor: exec}
	driver, err := NewMesosExecutorDriver(dconfig)
	assert.Nil(t, driver)
	assert.Error(t, err)
}

func TestExecutorDriverStartFailedToStartMessenger(t *testing.T) {
	exec := NewMockedExecutor()

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)
	assert.NotNil(t, driver)
	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger

	// Set expections and return values.
	messenger.On("Start").Return(fmt.Errorf("messenger failed to start"))
	messenger.On("Stop").Return(nil)

	status, err := driver.Start()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_NOT_STARTED, status)

	messenger.Stop()

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStartFailedToSendRegisterMessage(t *testing.T) {
	exec := NewMockedExecutor()

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)
	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger

	// Set expections and return values.
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(fmt.Errorf("messenger failed to send"))
	messenger.On("Stop").Return(nil)

	status, err := driver.Start()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_NOT_STARTED, status)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStartSucceed(t *testing.T) {
	setEnvironments(t, "", false)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)

	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	checker := healthchecker.NewMockedHealthChecker()
	checker.On("Start").Return()
	checker.On("Stop").Return()

	assert.False(t, driver.Running())
	status, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, status)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
}

func TestExecutorDriverRun(t *testing.T) {
	setEnvironments(t, "", false)

	// Set expections and return values.
	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)
	driver.messenger = messenger
	assert.False(t, driver.Running())

	checker := healthchecker.NewMockedHealthChecker()
	checker.On("Start").Return()
	checker.On("Stop").Return()

	ch := make(chan struct{})
	go func() {
		defer close(ch)
		stat, err := driver.Run()
		assert.NoError(t, err)
		assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	}()
	<-driver.started
	assert.True(t, driver.Running())
	driver.Stop()
	<-ch
}

func TestExecutorDriverJoin(t *testing.T) {
	setEnvironments(t, "", false)

	// Set expections and return values.
	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)
	driver.messenger = messenger
	assert.False(t, driver.Running())

	checker := healthchecker.NewMockedHealthChecker()
	checker.On("Start").Return()
	checker.On("Stop").Return()

	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.True(t, driver.Running())
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)

	testCh := make(chan mesosproto.Status)
	go func() {
		stat, _ := driver.Join()
		testCh <- stat
	}()

	driver.Stop()
	stat = <-testCh // when Stop() is called, stat will be DRIVER_STOPPED.
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
}

func TestExecutorDriverAbort(t *testing.T) {
	statusChan := make(chan mesosproto.Status)
	driver, messenger, _ := createTestExecutorDriver(t)

	assert.False(t, driver.Running())
	stat, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	go func() {
		st, _ := driver.Join()
		statusChan <- st
	}()

	stat, err = driver.Abort()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, <-statusChan)
	assert.False(t, driver.Running())

	// Abort for the second time, should return directly.
	stat, err = driver.Abort()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	stat, err = driver.Stop()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	assert.False(t, driver.Running())

	// Restart should not start.
	stat, err = driver.Start()
	assert.False(t, driver.Running())
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStop(t *testing.T) {
	statusChan := make(chan mesosproto.Status)
	driver, messenger, _ := createTestExecutorDriver(t)

	assert.False(t, driver.Running())
	stat, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	go func() {
		stat, _ := driver.Join()
		statusChan <- stat
	}()
	stat, err = driver.Stop()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, <-statusChan)
	assert.False(t, driver.Running())

	// Stop for the second time, should return directly.
	stat, err = driver.Stop()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	stat, err = driver.Abort()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	assert.False(t, driver.Running())

	// Restart should not start.
	stat, err = driver.Start()
	assert.False(t, driver.Running())
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverSendStatusUpdate(t *testing.T) {

	driver, _, _ := createTestExecutorDriver(t)

	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_RUNNING,
	)

	stat, err = driver.SendStatusUpdate(taskStatus)
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
}

func TestExecutorDriverSendStatusUpdateStaging(t *testing.T) {

	driver, _, _ := createTestExecutorDriver(t)
	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_STAGING,
	)

	stat, err = driver.SendStatusUpdate(taskStatus)
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
}

func TestExecutorDriverSendFrameworkMessage(t *testing.T) {

	driver, _, _ := createTestExecutorDriver(t)

	stat, err := driver.SendFrameworkMessage("failed")
	assert.Error(t, err)

	stat, err = driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	stat, err = driver.SendFrameworkMessage("Testing Mesos")
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
}

func TestStatusUpdateAckRace_Issue103(t *testing.T) {
	driver, _, _ := createTestExecutorDriver(t)
	_, err := driver.Start()
	assert.NoError(t, err)

	msg := &mesosproto.StatusUpdateAcknowledgementMessage{}
	go func() {
		driver.lock.Lock()
		defer driver.lock.Unlock()
		driver.statusUpdateAcknowledgement(nil, msg)
	}()

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_STAGING,
	)

	driver.SendStatusUpdate(taskStatus)
}
<commit_msg>removed unused healthchecker from executor tests<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package executor

import (
	"fmt"
	"os"
	"testing"

	"github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	"github.com/mesos/mesos-go/messenger"
	"github.com/mesos/mesos-go/upid"
	"github.com/stretchr/testify/assert"
)

var (
	slavePID    = "slave(1)@127.0.0.1:8080"
	slaveID     = "some-slave-id-uuid"
	frameworkID = "some-framework-id-uuid"
	executorID  = "some-executor-id-uuid"
)

func setEnvironments(t *testing.T, workDir string, checkpoint bool) {
	assert.NoError(t, os.Setenv("MESOS_SLAVE_PID", slavePID))
	assert.NoError(t, os.Setenv("MESOS_SLAVE_ID", slaveID))
	assert.NoError(t, os.Setenv("MESOS_FRAMEWORK_ID", frameworkID))
	assert.NoError(t, os.Setenv("MESOS_EXECUTOR_ID", executorID))
	if len(workDir) > 0 {
		assert.NoError(t, os.Setenv("MESOS_DIRECTORY", workDir))
	}
	if checkpoint {
		assert.NoError(t, os.Setenv("MESOS_CHECKPOINT", "1"))
	}
}

func clearEnvironments(t *testing.T) {
	assert.NoError(t, os.Setenv("MESOS_SLAVE_PID", ""))
	assert.NoError(t, os.Setenv("MESOS_SLAVE_ID", ""))
	assert.NoError(t, os.Setenv("MESOS_FRAMEWORK_ID", ""))
	assert.NoError(t, os.Setenv("MESOS_EXECUTOR_ID", ""))
}

func newTestExecutorDriver(t *testing.T, exec Executor) *MesosExecutorDriver {
	dconfig := DriverConfig{
		Executor: exec,
	}
	driver, err := NewMesosExecutorDriver(dconfig)
	if err != nil {
		t.Fatal(err)
	}
	return driver
}

type testExecutorDriver struct {
	*MesosExecutorDriver
}

func (e *testExecutorDriver) setConnected(b bool) {
	e.lock.Lock()
	defer e.lock.Unlock()
	e.connected = b
}

func createTestExecutorDriver(t *testing.T) (
	*testExecutorDriver,
	*messenger.MockedMessenger) {

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)

	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	driver.messenger = messenger
	return &testExecutorDriver{driver}, messenger
}

func TestExecutorDriverStartFailedToParseEnvironment(t *testing.T) {
	clearEnvironments(t)
	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)
	dconfig := DriverConfig{Executor: exec}
	driver, err := NewMesosExecutorDriver(dconfig)
	assert.Nil(t, driver)
	assert.Error(t, err)
}

func TestExecutorDriverStartFailedToStartMessenger(t *testing.T) {
	exec := NewMockedExecutor()

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)
	assert.NotNil(t, driver)
	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger

	// Set expections and return values.
	messenger.On("Start").Return(fmt.Errorf("messenger failed to start"))
	messenger.On("Stop").Return(nil)

	status, err := driver.Start()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_NOT_STARTED, status)

	messenger.Stop()

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStartFailedToSendRegisterMessage(t *testing.T) {
	exec := NewMockedExecutor()

	setEnvironments(t, "", false)
	driver := newTestExecutorDriver(t, exec)
	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger

	// Set expections and return values.
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(fmt.Errorf("messenger failed to send"))
	messenger.On("Stop").Return(nil)

	status, err := driver.Start()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_NOT_STARTED, status)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStartSucceed(t *testing.T) {
	setEnvironments(t, "", false)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)

	messenger := messenger.NewMockedMessenger()
	driver.messenger = messenger
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	assert.False(t, driver.Running())
	status, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, status)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
}

func TestExecutorDriverRun(t *testing.T) {
	setEnvironments(t, "", false)

	// Set expections and return values.
	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)
	driver.messenger = messenger
	assert.False(t, driver.Running())

	ch := make(chan struct{})
	go func() {
		defer close(ch)
		stat, err := driver.Run()
		assert.NoError(t, err)
		assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	}()
	<-driver.started
	assert.True(t, driver.Running())
	driver.Stop()
	<-ch
}

func TestExecutorDriverJoin(t *testing.T) {
	setEnvironments(t, "", false)

	// Set expections and return values.
	messenger := messenger.NewMockedMessenger()
	messenger.On("Start").Return(nil)
	messenger.On("UPID").Return(upid.UPID{})
	messenger.On("Send").Return(nil)
	messenger.On("Stop").Return(nil)

	exec := NewMockedExecutor()
	exec.On("Error").Return(nil)

	driver := newTestExecutorDriver(t, exec)
	driver.messenger = messenger
	assert.False(t, driver.Running())

	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.True(t, driver.Running())
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)

	testCh := make(chan mesosproto.Status)
	go func() {
		stat, _ := driver.Join()
		testCh <- stat
	}()

	driver.Stop()
	stat = <-testCh // when Stop() is called, stat will be DRIVER_STOPPED.
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
}

func TestExecutorDriverAbort(t *testing.T) {
	statusChan := make(chan mesosproto.Status)
	driver, messenger := createTestExecutorDriver(t)

	assert.False(t, driver.Running())
	stat, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	go func() {
		st, _ := driver.Join()
		statusChan <- st
	}()

	stat, err = driver.Abort()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, <-statusChan)
	assert.False(t, driver.Running())

	// Abort for the second time, should return directly.
	stat, err = driver.Abort()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	stat, err = driver.Stop()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
	assert.False(t, driver.Running())

	// Restart should not start.
	stat, err = driver.Start()
	assert.False(t, driver.Running())
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverStop(t *testing.T) {
	statusChan := make(chan mesosproto.Status)
	driver, messenger := createTestExecutorDriver(t)

	assert.False(t, driver.Running())
	stat, err := driver.Start()
	assert.True(t, driver.Running())
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	go func() {
		stat, _ := driver.Join()
		statusChan <- stat
	}()
	stat, err = driver.Stop()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, <-statusChan)
	assert.False(t, driver.Running())

	// Stop for the second time, should return directly.
	stat, err = driver.Stop()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	stat, err = driver.Abort()
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)
	assert.False(t, driver.Running())

	// Restart should not start.
	stat, err = driver.Start()
	assert.False(t, driver.Running())
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_STOPPED, stat)

	messenger.AssertNumberOfCalls(t, "Start", 1)
	messenger.AssertNumberOfCalls(t, "UPID", 1)
	messenger.AssertNumberOfCalls(t, "Send", 1)
	messenger.AssertNumberOfCalls(t, "Stop", 1)
}

func TestExecutorDriverSendStatusUpdate(t *testing.T) {

	driver, _ := createTestExecutorDriver(t)

	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_RUNNING,
	)

	stat, err = driver.SendStatusUpdate(taskStatus)
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
}

func TestExecutorDriverSendStatusUpdateStaging(t *testing.T) {

	driver, _ := createTestExecutorDriver(t)
	stat, err := driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_STAGING,
	)

	stat, err = driver.SendStatusUpdate(taskStatus)
	assert.Error(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_ABORTED, stat)
}

func TestExecutorDriverSendFrameworkMessage(t *testing.T) {

	driver, _ := createTestExecutorDriver(t)

	stat, err := driver.SendFrameworkMessage("failed")
	assert.Error(t, err)

	stat, err = driver.Start()
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
	driver.setConnected(true)

	stat, err = driver.SendFrameworkMessage("Testing Mesos")
	assert.NoError(t, err)
	assert.Equal(t, mesosproto.Status_DRIVER_RUNNING, stat)
}

func TestStatusUpdateAckRace_Issue103(t *testing.T) {
	driver, _ := createTestExecutorDriver(t)
	_, err := driver.Start()
	assert.NoError(t, err)

	msg := &mesosproto.StatusUpdateAcknowledgementMessage{}
	go func() {
		driver.lock.Lock()
		defer driver.lock.Unlock()
		driver.statusUpdateAcknowledgement(nil, msg)
	}()

	taskStatus := util.NewTaskStatus(
		util.NewTaskID("test-task-001"),
		mesosproto.TaskState_TASK_STAGING,
	)

	driver.SendStatusUpdate(taskStatus)
}
<|endoftext|>