<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 snippets

// [START translate_text_with_model]
import (
	"context"
	"fmt"

	"cloud.google.com/go/translate"
	"golang.org/x/text/language"
)

func translateTextWithModel(targetLanguage, text, model string) (string, error) {
	// targetLanguage := "ja"
	// text := "The Go Gopher is cute"
	// model := "nmt"

	ctx := context.Background()

	lang, err := language.Parse(targetLanguage)
	if err != nil {
		return "", fmt.Errorf("language.Parse: %v", err)
	}

	client, err := translate.NewClient(ctx)
	if err != nil {
		return "", fmt.Errorf("translate.NewClient: %v", err)
	}
	defer client.Close()

	resp, err := client.Translate(ctx, []string{text}, lang, &translate.Options{
		Model: model, // Either "mnt" or "base".
	})
	if err != nil {
		return "", fmt.Errorf("Translate: %v", err)
	}
	if len(resp) == 0 {
		return "", nil
	}
	return resp[0].Text, nil
}

// [END translate_text_with_model]
<commit_msg>docs(translate): fix model name (#2000)<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 snippets

// [START translate_text_with_model]
import (
	"context"
	"fmt"

	"cloud.google.com/go/translate"
	"golang.org/x/text/language"
)

func translateTextWithModel(targetLanguage, text, model string) (string, error) {
	// targetLanguage := "ja"
	// text := "The Go Gopher is cute"
	// model := "nmt"

	ctx := context.Background()

	lang, err := language.Parse(targetLanguage)
	if err != nil {
		return "", fmt.Errorf("language.Parse: %v", err)
	}

	client, err := translate.NewClient(ctx)
	if err != nil {
		return "", fmt.Errorf("translate.NewClient: %v", err)
	}
	defer client.Close()

	resp, err := client.Translate(ctx, []string{text}, lang, &translate.Options{
		Model: model, // Either "nmt" or "base".
	})
	if err != nil {
		return "", fmt.Errorf("Translate: %v", err)
	}
	if len(resp) == 0 {
		return "", nil
	}
	return resp[0].Text, nil
}

// [END translate_text_with_model]
<|endoftext|>


<commit_before>// Package trigram provides types for string indexing and matching.
package trigram

import (
	"sort"
	"strings"
	"unicode"

	"dasa.cc/x/set"
)

// Set indexer; zero value is valid.
type Set struct {
	// Mapping function used when calling Parse or defaults to IsSpaceDigitLetterToLower if not set.
	Mapping func(rune) rune

	// Fields function used when calling Parse or defaults to unicode.IsSpace if not set.
	Fields func(rune) bool

	ks set.StringSlice
	vs []set.StringSlice
}

// Index parses and stores trigrams for each s in xs. Panics if nil.
func (a *Set) Index(xs ...string) {
	if a.Mapping == nil {
		a.Mapping = IsSpaceDigitLetterToLower
	}
	if a.Fields == nil {
		a.Fields = unicode.IsSpace
	}
	for _, s := range xs {
		for _, t := range Parse(s, a.Mapping, a.Fields) {
			i, ok := 0, false
			if i, ok = a.ks.Insert(t); ok {
				a.vs = append(a.vs, nil)
				copy(a.vs[i+1:], a.vs[i:])
				a.vs[i] = nil
			}
			a.vs[i].Insert(s)
		}
	}
}

// Match indexed values for x that meet min threshold; returns matches and unit scores.
func (a Set) Match(x string, min float64) ([]string, []float64) {
	var p set.StringSlice
	var u []float64

	q := Parse(x, a.Mapping, a.Fields)
	for _, s := range q {
		if i := sort.SearchStrings(a.ks, s); i < len(a.ks) && a.ks[i] == s {
			for _, t := range a.vs[i] {
				j, ok := 0, false
				if j, ok = p.Insert(t); ok {
					u = append(u, 0)
					copy(u[j+1:], u[j:])
					u[j] = 0
				}
				u[j]++
			}
		}
	}

	fp, fu := p[:0], u[:0]
	for i, s := range p {
		if w := u[i] / float64(len(q)); min <= w {
			fp, fu = append(fp, s), append(fu, w)
		}
	}
	return fp, fu
}

// Parse returns a slice of trigrams for s after modifying characters according to
// the mapping function followed by word splitting according to fields function.
func Parse(s string, mapping func(rune) rune, fields func(rune) bool) []string {
	var p set.StringSlice
	for _, t := range strings.FieldsFunc(strings.Map(mapping, s), fields) {
		t = "\x00\x00" + t + "\x00"
		for i := 0; i <= len(t)-3; i++ {
			p.Insert(t[i : i+3])
		}
	}
	return p
}

// IsSpaceDigitLetterToLower reports whether rune is a letter, digit, or space character
// as defined by Unicode's White Space property and maps rune to lower case.
func IsSpaceDigitLetterToLower(r rune) rune {
	if unicode.IsLetter(r) || unicode.IsDigit(r) || unicode.IsSpace(r) {
		return unicode.ToLower(r)
	}
	return -1
}

// NoFields always returns false; preserves white space in Parse results.
func NoFields(rune) bool { return false }
<commit_msg>doc formatting<commit_after>// Package trigram provides string indexing and matching.
package trigram

import (
	"sort"
	"strings"
	"unicode"

	"dasa.cc/x/set"
)

// Set indexer; zero value is valid.
type Set struct {
	// Mapping function used when calling Parse
	// or defaults to IsSpaceDigitLetterToLower if not set.
	Mapping func(rune) rune

	// Fields function used when calling Parse
	// or defaults to unicode.IsSpace if not set.
	Fields func(rune) bool

	ks set.StringSlice
	vs []set.StringSlice
}

// Index parses and stores trigrams for each s in xs. Panics if nil.
func (a *Set) Index(xs ...string) {
	if a.Mapping == nil {
		a.Mapping = IsSpaceDigitLetterToLower
	}
	if a.Fields == nil {
		a.Fields = unicode.IsSpace
	}
	for _, s := range xs {
		for _, t := range Parse(s, a.Mapping, a.Fields) {
			i, ok := 0, false
			if i, ok = a.ks.Insert(t); ok {
				a.vs = append(a.vs, nil)
				copy(a.vs[i+1:], a.vs[i:])
				a.vs[i] = nil
			}
			a.vs[i].Insert(s)
		}
	}
}

// Match indexed values for x that meet min threshold; returns matches and unit scores.
func (a Set) Match(x string, min float64) ([]string, []float64) {
	var p set.StringSlice
	var u []float64

	q := Parse(x, a.Mapping, a.Fields)
	for _, s := range q {
		if i := sort.SearchStrings(a.ks, s); i < len(a.ks) && a.ks[i] == s {
			for _, t := range a.vs[i] {
				j, ok := 0, false
				if j, ok = p.Insert(t); ok {
					u = append(u, 0)
					copy(u[j+1:], u[j:])
					u[j] = 0
				}
				u[j]++
			}
		}
	}

	fp, fu := p[:0], u[:0]
	for i, s := range p {
		if w := u[i] / float64(len(q)); min <= w {
			fp, fu = append(fp, s), append(fu, w)
		}
	}
	return fp, fu
}

// Parse returns a slice of trigrams for s after modifying characters according to
// the mapping function followed by word splitting according to fields function.
func Parse(s string, mapping func(rune) rune, fields func(rune) bool) []string {
	var p set.StringSlice
	for _, t := range strings.FieldsFunc(strings.Map(mapping, s), fields) {
		t = "\x00\x00" + t + "\x00"
		for i := 0; i <= len(t)-3; i++ {
			p.Insert(t[i : i+3])
		}
	}
	return p
}

// IsSpaceDigitLetterToLower reports whether rune is a letter, digit, or space character
// as defined by Unicode's White Space property and maps rune to lower case.
func IsSpaceDigitLetterToLower(r rune) rune {
	if unicode.IsLetter(r) || unicode.IsDigit(r) || unicode.IsSpace(r) {
		return unicode.ToLower(r)
	}
	return -1
}

// NoFields always returns false; preserves white space in Parse results.
func NoFields(rune) bool { return false }
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-martini/martini"
	"log"
	//"net/http"
)

func main() {
	m := martini.Classic()
	//中间件处理器是工作于请求和路由之间的. 本质上来说和Martini其他的处理器没有分别.
	/*
		你可以通过Handlers函数对中间件堆有完全的控制. 它将会替换掉之前的任何设置过的处理器
		m.Handlers(
		  Middleware1,
		  Middleware2,
		  Middleware3,
		)
		中间件处理器可以非常好处理一些功能，像logging(日志), authorization(授权), authentication(认证), sessions(会话), error pages(错误页面),
		以及任何其他的操作需要在http请求发生之前或者之后的:
	*/
	// 验证api密匙
	// m.Use(func(res http.ResponseWriter, req *http.Request) {
	// 	if req.Header.Get("X-API-KEY") != "secret123" {
	// 		res.WriteHeader(http.StatusUnauthorized)
	// 	}
	// })

	//Context.Next()是一个可选的函数用于中间件处理器暂时放弃执行直到其他的处理器都执行完毕. 这样就可以很好的处理在http请求完成后需要做的操作.
	// log 记录请求完成前后  (*译者注: 很巧妙，掌声鼓励.)
	m.Use(func(c martini.Context, log *log.Logger) {
		log.Println("before a request")

		c.Next()

		log.Println("after a request")
	})

	//路由匹配的顺序是按照他们被定义的顺序执行的. 最先被定义的路由将会首先被用户请求匹配并调用
	m.Get("/", func() (int, string) {
		return 418, "I'm a teaport" //状态码418
	})

	m.Patch("/", func() {
		// 更新
	})

	m.Post("/", func() {
		// 创建
	})

	m.Put("/", func() {
		// 替换
	})

	m.Delete("/", func() {
		// 删除
	})

	m.Options("/", func() {
		// http 选项
	})

	m.NotFound(func() {
		// 处理 404
	})

	//路由模型可能包含参数列表, 可以通过martini.Params服务来获取
	m.Get("/hello/:name", func(params martini.Params) string {
		return "Hello " + params["name"]
	})

	//路由匹配可以通过正则表达式或者glob的形式
	m.Get("/hello2/**", func(params martini.Params) string {
		log.Println("hello2")
		return "Hello " + params["_1"]
	})
	m.Run()
}
<commit_msg>修改端口号<commit_after>package main

import (
	"github.com/go-martini/martini"
	"log"
	"net/http"
)

func main() {
	m := martini.Classic()
	//中间件处理器是工作于请求和路由之间的. 本质上来说和Martini其他的处理器没有分别.
	/*
		你可以通过Handlers函数对中间件堆有完全的控制. 它将会替换掉之前的任何设置过的处理器
		m.Handlers(
		  Middleware1,
		  Middleware2,
		  Middleware3,
		)
		中间件处理器可以非常好处理一些功能，像logging(日志), authorization(授权), authentication(认证), sessions(会话), error pages(错误页面),
		以及任何其他的操作需要在http请求发生之前或者之后的:
	*/
	// 验证api密匙
	// m.Use(func(res http.ResponseWriter, req *http.Request) {
	// 	if req.Header.Get("X-API-KEY") != "secret123" {
	// 		res.WriteHeader(http.StatusUnauthorized)
	// 	}
	// })

	//Context.Next()是一个可选的函数用于中间件处理器暂时放弃执行直到其他的处理器都执行完毕. 这样就可以很好的处理在http请求完成后需要做的操作.
	// log 记录请求完成前后  (*译者注: 很巧妙，掌声鼓励.)
	m.Use(func(c martini.Context, log *log.Logger) {
		log.Println("before a request")

		c.Next()

		log.Println("after a request")
	})

	//路由匹配的顺序是按照他们被定义的顺序执行的. 最先被定义的路由将会首先被用户请求匹配并调用
	m.Get("/", func() (int, string) {
		return 418, "I'm a teaport" //状态码418
	})

	m.Patch("/", func() {
		// 更新
	})

	m.Post("/", func() {
		// 创建
	})

	m.Put("/", func() {
		// 替换
	})

	m.Delete("/", func() {
		// 删除
	})

	m.Options("/", func() {
		// http 选项
	})

	m.NotFound(func() {
		// 处理 404
	})

	//路由模型可能包含参数列表, 可以通过martini.Params服务来获取
	m.Get("/hello/:name", func(params martini.Params) string {
		return "Hello " + params["name"]
	})

	//路由匹配可以通过正则表达式或者glob的形式
	m.Get("/hello2/**", func(params martini.Params) string {
		log.Println("hello2")
		return "Hello " + params["_1"]
	})
	//m.Run()
	//修改端口
	http.ListenAndServe(":8080", m)
}
<|endoftext|>


<commit_before>package tutum

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/gorilla/websocket"
)

/*
func ListContainers
Returns : Array of Container objects
*/
func ListContainers() (CListResponse, error) {

	url := "container/"
	request := "GET"
	//Empty Body Request
	body := []byte(`{}`)
	var response CListResponse
	var finalResponse CListResponse

	data, err := TutumCall(url, request, body)
	if err != nil {
		return response, err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return response, err
	}

	finalResponse = response

Loop:
	for {
		if response.Meta.Next != "" {
			var nextResponse CListResponse
			data, err := TutumCall(response.Meta.Next[8:], request, body)
			if err != nil {
				return nextResponse, err
			}
			err = json.Unmarshal(data, &nextResponse)
			if err != nil {
				return nextResponse, err
			}
			finalResponse.Objects = append(finalResponse.Objects, nextResponse.Objects...)
			response = nextResponse

		} else {
			break Loop
		}
	}

	return finalResponse, nil
}

/*
func GetContainer
Argument : uuid
Returns : Container JSON object
*/
func GetContainer(uuid string) (Container, error) {

	url := ""
	if string(uuid[0]) == "/" {
		url = uuid[8:]
	} else {
		url = "container/" + uuid + "/"
	}

	request := "GET"
	//Empty Body Request
	body := []byte(`{}`)
	var response Container

	data, err := TutumCall(url, request, body)
	if err != nil {
		return response, err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return response, err
	}

	return response, nil
}

/*
func GetContainerLogs
Argument : a channel of type string for the output
*/

func (self *Container) Logs(c chan Logs) {

	endpoint := "container/" + self.Uuid + "/logs/?user=" + User + "&token=" + ApiKey
	url := StreamUrl + endpoint

	header := http.Header{}
	header.Add("User-Agent", customUserAgent)

	var Dialer websocket.Dialer
	ws, _, err := Dialer.Dial(url, header)
	if err != nil {
		log.Println(err)
	}

	var msg Logs
	for {
		if err = ws.ReadJSON(&msg); err != nil {
			if err != nil && err.Error() != "EOF" {
				log.Println(err)
			} else {
				break
			}
		}
		c <- msg
	}
}

/*
func Exec
Arguments : the command to execute, a channel of type string for the output
*/

func (self *Container) Exec(command string, c chan Exec) {
	go self.Run(command, c)
Loop:
	for {
		select {
		case s := <-c:
			if s.Output != "EOF" {
				fmt.Printf("%s", s.Output)
			} else {
				break Loop
			}
		}
	}
}

func (self *Container) Run(command string, c chan Exec) {

	endpoint := "container/" + self.Uuid + "/exec/?user=" + User + "&token=" + ApiKey + "&command=" + url.QueryEscape(command)
	url := StreamUrl + endpoint

	header := http.Header{}
	header.Add("User-Agent", customUserAgent)

	var Dialer websocket.Dialer
	ws, _, err := Dialer.Dial(url, header)
	if err != nil {
		log.Println(err)
	}

	var msg Exec
	for {
		if err = ws.ReadJSON(&msg); err != nil {
			if err != nil && err.Error() != "EOF" {
				log.Println(err)
			} else {
				break
			}
		}
		c <- msg
	}
}

/*
func StartContainer
Returns : Error
*/
func (self *Container) Start() error {

	url := "container/" + self.Uuid + "/start/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)
	var response Container

	data, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return err
	}

	return nil
}

/*
func StopContainer
Returns : Error
*/
func (self *Container) Stop() error {

	url := "container/" + self.Uuid + "/stop/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}

/*
func RedeployContainer
Returns : Error
*/
func (self *Container) Redeploy() error {

	url := "container/" + self.Uuid + "/redeploy/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}

/*
func TerminateContainer
Returns : Error
*/
func (self *Container) Terminate() error {

	url := "container/" + self.Uuid + "/"
	request := "DELETE"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Fixed websocket usage in Container.Run, .Exec, .Log * We look for the error CloseError to see when the websocket closes * When the websocket closes, we close the channel<commit_after>package tutum

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/gorilla/websocket"
)

/*
func ListContainers
Returns : Array of Container objects
*/
func ListContainers() (CListResponse, error) {

	url := "container/"
	request := "GET"
	//Empty Body Request
	body := []byte(`{}`)
	var response CListResponse
	var finalResponse CListResponse

	data, err := TutumCall(url, request, body)
	if err != nil {
		return response, err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return response, err
	}

	finalResponse = response

Loop:
	for {
		if response.Meta.Next != "" {
			var nextResponse CListResponse
			data, err := TutumCall(response.Meta.Next[8:], request, body)
			if err != nil {
				return nextResponse, err
			}
			err = json.Unmarshal(data, &nextResponse)
			if err != nil {
				return nextResponse, err
			}
			finalResponse.Objects = append(finalResponse.Objects, nextResponse.Objects...)
			response = nextResponse

		} else {
			break Loop
		}
	}

	return finalResponse, nil
}

/*
func GetContainer
Argument : uuid
Returns : Container JSON object
*/
func GetContainer(uuid string) (Container, error) {

	url := ""
	if string(uuid[0]) == "/" {
		url = uuid[8:]
	} else {
		url = "container/" + uuid + "/"
	}

	request := "GET"
	//Empty Body Request
	body := []byte(`{}`)
	var response Container

	data, err := TutumCall(url, request, body)
	if err != nil {
		return response, err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return response, err
	}

	return response, nil
}

/*
func GetContainerLogs
Argument : a channel of type string for the output
*/

func (self *Container) Logs(c chan Logs) {

	endpoint := "container/" + self.Uuid + "/logs/?user=" + User + "&token=" + ApiKey
	url := StreamUrl + endpoint

	header := http.Header{}
	header.Add("User-Agent", customUserAgent)

	var Dialer websocket.Dialer
	ws, _, err := Dialer.Dial(url, header)
	if err != nil {
		log.Println(err)
	}

	var msg Logs
	for {
		if err = ws.ReadJSON(&msg); err != nil {
			//Type switches don't work here, so we use a type assertion instead
			_, ok := err.(*websocket.CloseError)
			if ok {
				close(c)
				break
			} else {
				log.Println(err)
			}
		}
		c <- msg
	}
}

/*
func Exec
Arguments : the command to execute, a channel of type string for the output
*/

func (self *Container) Exec(command string, c chan Exec) {
	go self.Run(command, c)
Loop:
	for {
		select {
		case s, open := <-c:
			if open {
				fmt.Printf("%s", s.Output)
			} else {
				break Loop
			}
		}
	}
}

func (self *Container) Run(command string, c chan Exec) {

	endpoint := "container/" + self.Uuid + "/exec/?user=" + User + "&token=" + ApiKey + "&command=" + url.QueryEscape(command)
	url := StreamUrl + endpoint

	header := http.Header{}
	header.Add("User-Agent", customUserAgent)

	var Dialer websocket.Dialer
	ws, _, err := Dialer.Dial(url, header)
	if err != nil {
		log.Println(err)
	}

	var msg Exec
Loop:
	for {
		if err = ws.ReadJSON(&msg); err != nil {
			//Type switches don't work here, so we use a type assertion instead
			_, ok := err.(*websocket.CloseError)
			if ok {
				close(c)
				break Loop
			} else {
				log.Println(err)
			}
		}
		c <- msg
	}
}

/*
func StartContainer
Returns : Error
*/
func (self *Container) Start() error {

	url := "container/" + self.Uuid + "/start/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)
	var response Container

	data, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		return err
	}

	return nil
}

/*
func StopContainer
Returns : Error
*/
func (self *Container) Stop() error {

	url := "container/" + self.Uuid + "/stop/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}

/*
func RedeployContainer
Returns : Error
*/
func (self *Container) Redeploy() error {

	url := "container/" + self.Uuid + "/redeploy/"
	request := "POST"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}

/*
func TerminateContainer
Returns : Error
*/
func (self *Container) Terminate() error {

	url := "container/" + self.Uuid + "/"
	request := "DELETE"
	//Empty Body Request
	body := []byte(`{}`)

	_, err := TutumCall(url, request, body)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/kless/term"
	"io/ioutil"
	"log"
	"os"
	"path"
	"regexp"
	"strings"
	"syscall"
)

const cmdDeploy = "deploy"
const cmdInstall = "install"

var argNum = 0

var projectName = flag.String("project", "", "project name to use for AWS credentials")
var filterPackageName = flag.Bool("p", false, "filter by package name; detect it by default")
var execInSeries = flag.Bool("s", false, "run the exec commands in series (default is parallel)")
var packageName = flag.String("package", "", "package name to filter by")
var args []string

type dotfileNotFoundError struct {
	name string
}

func (self dotfileNotFoundError) Error() string {
	return fmt.Sprintf("%s not found. Please ensure your project is configured properly.", self.name)
}

func main() {
	log.SetFlags(0)

	flag.Parse()
	args = flag.Args()

	var cluster string
	var err error

	envCluster := getNextArg("environment not given")
	envClusterSplit := strings.Split(envCluster, "/")
	env := envClusterSplit[0]
	if len(envClusterSplit) > 1 {
		cluster = envClusterSplit[1]
	}

	cmd := getNextArg("command not given")

	if *projectName == "" {
		*projectName, err = detectProjectName()
		if err != nil {
			log.Fatalln(err)
		}
		*projectName = os.Getenv("AWS_DEFAULT_PROFILE")
		if *projectName == "" {
			log.Fatalln("Please provide a profile to target")
		}
	}

	var packageNames, filterPackageNames []string

	if cmd == cmdDeploy || cmd == cmdInstall {
		packageNames = getRemainingArgsAsSlice("")
		if cmd == cmdInstall && len(packageNames) == 0 {
			log.Fatalln("no packages given")
		}
	}

	if cmd == cmdDeploy {
		*filterPackageName = true
		filterPackageNames = packageNames
	}

	if *filterPackageName && (filterPackageNames == nil || len(filterPackageNames) == 0) {
		if *packageName == "" {
			filterPackageNames, err = detectPackageNames()
			if err != nil {
				log.Fatalln(err)
			}
		} else {
			filterPackageNames = []string{*packageName}
		}
	}

	if cmd == cmdDeploy {
		packageNames = filterPackageNames
	}

	awsConf, err := getAWSConf(*projectName)
	if err != nil {
		log.Fatalln(err)
	}
	job, err := NewJob(awsConf, env, cluster, *projectName, packageNames,
		filterPackageNames, os.Stdout, term.IsTerminal(syscall.Stdout))
	if err != nil {
		log.Fatalln(err)
	}

	switch cmd {
	case cmdDeploy:
		showErrorsList(job.Deploy(true, *execInSeries))
	case cmdInstall:
		showErrorsList(job.Deploy(false, *execInSeries))
	case "exec":
		cmd := getRemainingArgsAsString("command not given")
		showErrorsList(job.Exec(cmd, *execInSeries))
	case "ssh":
		hostName := getNextArg("")
		sshArgs := getRemainingArgsAsSlice("")
		err = job.Ssh(hostName, sshArgs)
	case "scp":
		if len(args) <= argNum {
			log.Fatalln("you must give at least one source file")
		}
		err = job.Scp(args[argNum:])
	case "ls":
		err = job.List()
	case "hostname":
		instanceName := getNextArg("instance name not given")
		err = job.Hostname(instanceName)
	default:
		log.Fatalf("command not recognised: %s\n", cmd)
	}

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

func showErrorsList(errs []error) {
	if len(errs) > 0 {
		errStrings := make([]string, len(errs))
		for i, err := range errs {
			errStrings[i] = err.Error()
		}
		log.Fatalf(strings.Join(errStrings, "\n"))
	}
}

func fatalUsageError(errMsg string) {
	fmt.Fprintln(os.Stderr, "fatal: "+errMsg+"\n")
	usage()
	os.Exit(1)
}

func getNextArg(errMsg string) (val string) {
	if len(args) >= (argNum + 1) {
		val = args[argNum]
		argNum += 1
	} else if errMsg != "" {
		fatalUsageError(errMsg)
	}
	return
}

func getRemainingArgsAsString(errMsg string) (val string) {
	remainingArgs := args[argNum:]
	if len(remainingArgs) >= 1 {
		val = strings.Join(remainingArgs, " ")
	} else {
		log.Fatalln(errMsg)
	}
	return
}

func getRemainingArgsAsSlice(errMsg string) (val []string) {
	val = args[argNum:]
	if errMsg != "" && len(val) == 0 {
		log.Fatalln(errMsg)
	}
	return
}

func findDotfileAndRead(fn string, errName string) (value string, err error) {
	dir, err := os.Getwd()
	if err != nil {
		return
	}

	var newDir string
	for {
		if fBytes, err := ioutil.ReadFile(path.Join(dir, fn)); err == nil && len(fBytes) > 0 {
			return strings.TrimSpace(string(fBytes)), nil
		}

		newDir = path.Dir(dir)
		if dir == newDir {
			break
		}
		dir = newDir
	}

	return "", dotfileNotFoundError{name: errName}
}

func findDotfilesAndRead(fns []string, errName string) (value string, err error) {
	for _, fn := range fns {
		value, err = findDotfileAndRead(fn, errName)
		if err == nil {
			return value, nil
		} else {
			if _, ok := err.(dotfileNotFoundError); !ok {
				fmt.Printf("err: %#v\n", err)
				return "", err
			}
		}
	}
	return
}

func detectProjectName() (projectName string, err error) {
	return findDotfilesAndRead([]string{".project-name", ".moltar-project", ".mxm-project"}, "Project name")
}

var packageNamePattern = regexp.MustCompile(`\b[-\w]+\b`)

func detectPackageNames() (packageNames []string, err error) {
	ps, err := findDotfilesAndRead([]string{
		".package-name", ".moltar-package", ".mxm-package",
		".package-names", ".moltar-packages", ".mxm-packages",
	}, "Package name")
	if err == nil {
		return packageNamePattern.FindAllString(ps, -1), nil
	} else {
		return nil, err
	}
}

func formatTable(fields [][]string) (out string) {
	if len(fields) == 0 {
		return
	}
	outBuf := new(bytes.Buffer)
	numFields := len(fields[0])
	maxIndex := numFields - 1
	maxWidths := make([]int, numFields)
	for _, f := range fields {
		for i, c := range f {
			if lenc := len(c); lenc > maxWidths[i] {
				maxWidths[i] = lenc
			}
		}
	}

	for _, f := range fields {
		for i := 0; i < numFields; i++ {
			c := f[i]
			outBuf.WriteString(c)
			if i < maxIndex {
				outBuf.Write(
					bytes.Repeat([]byte(" "), maxWidths[i]-len(c)+2))
			}
		}
		outBuf.WriteRune('\n')
	}

	out = outBuf.String()

	return
}
<commit_msg>Fixed issue with project name from env overwriting file based profile<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/kless/term"
	"io/ioutil"
	"log"
	"os"
	"path"
	"regexp"
	"strings"
	"syscall"
)

const cmdDeploy = "deploy"
const cmdInstall = "install"

var argNum = 0

var projectName = flag.String("project", "", "project name to use for AWS credentials")
var filterPackageName = flag.Bool("p", false, "filter by package name; detect it by default")
var execInSeries = flag.Bool("s", false, "run the exec commands in series (default is parallel)")
var packageName = flag.String("package", "", "package name to filter by")
var args []string

type dotfileNotFoundError struct {
	name string
}

func (self dotfileNotFoundError) Error() string {
	return fmt.Sprintf("%s not found. Please ensure your project is configured properly.", self.name)
}

func main() {
	log.SetFlags(0)

	flag.Parse()
	args = flag.Args()

	var cluster string
	var err error

	envCluster := getNextArg("environment not given")
	envClusterSplit := strings.Split(envCluster, "/")
	env := envClusterSplit[0]
	if len(envClusterSplit) > 1 {
		cluster = envClusterSplit[1]
	}

	cmd := getNextArg("command not given")

	*projectName = os.Getenv("AWS_DEFAULT_PROFILE")
	if *projectName == "" {
		*projectName, err = detectProjectName()
		if err != nil {
			log.Fatalln(err)
		}
		if *projectName == "" {
			log.Fatalln("Please provide a profile to target")
		}
	}

	var packageNames, filterPackageNames []string

	if cmd == cmdDeploy || cmd == cmdInstall {
		packageNames = getRemainingArgsAsSlice("")
		if cmd == cmdInstall && len(packageNames) == 0 {
			log.Fatalln("no packages given")
		}
	}

	if cmd == cmdDeploy {
		*filterPackageName = true
		filterPackageNames = packageNames
	}

	if *filterPackageName && (filterPackageNames == nil || len(filterPackageNames) == 0) {
		if *packageName == "" {
			filterPackageNames, err = detectPackageNames()
			if err != nil {
				log.Fatalln(err)
			}
		} else {
			filterPackageNames = []string{*packageName}
		}
	}

	if cmd == cmdDeploy {
		packageNames = filterPackageNames
	}

	awsConf, err := getAWSConf(*projectName)
	if err != nil {
		log.Fatalln(err)
	}
	job, err := NewJob(awsConf, env, cluster, *projectName, packageNames,
		filterPackageNames, os.Stdout, term.IsTerminal(syscall.Stdout))
	if err != nil {
		log.Fatalln(err)
	}

	switch cmd {
	case cmdDeploy:
		showErrorsList(job.Deploy(true, *execInSeries))
	case cmdInstall:
		showErrorsList(job.Deploy(false, *execInSeries))
	case "exec":
		cmd := getRemainingArgsAsString("command not given")
		showErrorsList(job.Exec(cmd, *execInSeries))
	case "ssh":
		hostName := getNextArg("")
		sshArgs := getRemainingArgsAsSlice("")
		err = job.Ssh(hostName, sshArgs)
	case "scp":
		if len(args) <= argNum {
			log.Fatalln("you must give at least one source file")
		}
		err = job.Scp(args[argNum:])
	case "ls":
		err = job.List()
	case "hostname":
		instanceName := getNextArg("instance name not given")
		err = job.Hostname(instanceName)
	default:
		log.Fatalf("command not recognised: %s\n", cmd)
	}

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

func showErrorsList(errs []error) {
	if len(errs) > 0 {
		errStrings := make([]string, len(errs))
		for i, err := range errs {
			errStrings[i] = err.Error()
		}
		log.Fatalf(strings.Join(errStrings, "\n"))
	}
}

func fatalUsageError(errMsg string) {
	fmt.Fprintln(os.Stderr, "fatal: "+errMsg+"\n")
	usage()
	os.Exit(1)
}

func getNextArg(errMsg string) (val string) {
	if len(args) >= (argNum + 1) {
		val = args[argNum]
		argNum += 1
	} else if errMsg != "" {
		fatalUsageError(errMsg)
	}
	return
}

func getRemainingArgsAsString(errMsg string) (val string) {
	remainingArgs := args[argNum:]
	if len(remainingArgs) >= 1 {
		val = strings.Join(remainingArgs, " ")
	} else {
		log.Fatalln(errMsg)
	}
	return
}

func getRemainingArgsAsSlice(errMsg string) (val []string) {
	val = args[argNum:]
	if errMsg != "" && len(val) == 0 {
		log.Fatalln(errMsg)
	}
	return
}

func findDotfileAndRead(fn string, errName string) (value string, err error) {
	dir, err := os.Getwd()
	if err != nil {
		return
	}

	var newDir string
	for {
		if fBytes, err := ioutil.ReadFile(path.Join(dir, fn)); err == nil && len(fBytes) > 1 {
			return strings.TrimSpace(string(fBytes)), nil
		}

		newDir = path.Dir(dir)
		if dir == newDir {
			break
		}
		dir = newDir
	}

	return "", dotfileNotFoundError{name: errName}
}

func findDotfilesAndRead(fns []string, errName string) (value string, err error) {
	for _, fn := range fns {
		value, err = findDotfileAndRead(fn, errName)
		if err == nil {
			return value, nil
		} else {
			if _, ok := err.(dotfileNotFoundError); !ok {
				fmt.Printf("err: %#v\n", err)
				return "", err
			}
		}
	}
	return
}

func detectProjectName() (projectName string, err error) {
	return findDotfilesAndRead([]string{".project-name", ".moltar-project", ".mxm-project"}, "Project name")
}

var packageNamePattern = regexp.MustCompile(`\b[-\w]+\b`)

func detectPackageNames() (packageNames []string, err error) {
	ps, err := findDotfilesAndRead([]string{
		".package-name", ".moltar-package", ".mxm-package",
		".package-names", ".moltar-packages", ".mxm-packages",
	}, "Package name")
	if err == nil {
		return packageNamePattern.FindAllString(ps, -1), nil
	} else {
		return nil, err
	}
}

func formatTable(fields [][]string) (out string) {
	if len(fields) == 0 {
		return
	}
	outBuf := new(bytes.Buffer)
	numFields := len(fields[0])
	maxIndex := numFields - 1
	maxWidths := make([]int, numFields)
	for _, f := range fields {
		for i, c := range f {
			if lenc := len(c); lenc > maxWidths[i] {
				maxWidths[i] = lenc
			}
		}
	}

	for _, f := range fields {
		for i := 0; i < numFields; i++ {
			c := f[i]
			outBuf.WriteString(c)
			if i < maxIndex {
				outBuf.Write(
					bytes.Repeat([]byte(" "), maxWidths[i]-len(c)+2))
			}
		}
		outBuf.WriteRune('\n')
	}

	out = outBuf.String()

	return
}
<|endoftext|>


<commit_before>/*
Package drive provides the definitions for the low-level pfs storage drivers.
*/
package drive

import (
	"io"

	"go.pedge.io/google-protobuf"

	"github.com/pachyderm/pachyderm/src/pfs"
)

// ReaderAtCloser is an interface that implements both io.ReaderAt and io.Closer.
type ReaderAtCloser interface {
	io.Reader
	io.ReaderAt
	io.Closer
}

// Driver represents a low-level pfs storage driver.
type Driver interface {
	CreateRepo(repo *pfs.Repo, created *google_protobuf.Timestamp, shards map[uint64]bool) error
	InspectRepo(repo *pfs.Repo, shards map[uint64]bool) (*pfs.RepoInfo, error)
	ListRepo(shards map[uint64]bool) ([]*pfs.RepoInfo, error)
	DeleteRepo(repo *pfs.Repo, shards map[uint64]bool) error
	StartCommit(parent *pfs.Commit, commit *pfs.Commit, started *google_protobuf.Timestamp, shards map[uint64]bool) error
	FinishCommit(commit *pfs.Commit, finished *google_protobuf.Timestamp, shards map[uint64]bool) error
	InspectCommit(commit *pfs.Commit, shards map[uint64]bool) (*pfs.CommitInfo, error)
	ListCommit(repo []*pfs.Repo, fromCommit []*pfs.Commit, shards map[uint64]bool) ([]*pfs.CommitInfo, error)
	DeleteCommit(commit *pfs.Commit, shards map[uint64]bool) error
	PutFile(file *pfs.File, shard uint64, offset int64, reader io.Reader) error
	MakeDirectory(file *pfs.File, shards map[uint64]bool) error
	GetFile(file *pfs.File, filterShard *pfs.Shard, offset int64, size int64, shard uint64) (io.ReadCloser, error)
	InspectFile(file *pfs.File, filterShard *pfs.Shard, shard uint64) (*pfs.FileInfo, error)
	ListFile(file *pfs.File, filterShard *pfs.Shard, shard uint64) ([]*pfs.FileInfo, error)
	DeleteFile(file *pfs.File, shard uint64) error
	AddShard(shard uint64) error
	DeleteShard(shard uint64) error
}
<commit_msg>Remove unused interface.<commit_after>/*
Package drive provides the definitions for the low-level pfs storage drivers.
*/
package drive

import (
	"io"

	"go.pedge.io/google-protobuf"

	"github.com/pachyderm/pachyderm/src/pfs"
)

// Driver represents a low-level pfs storage driver.
type Driver interface {
	CreateRepo(repo *pfs.Repo, created *google_protobuf.Timestamp, shards map[uint64]bool) error
	InspectRepo(repo *pfs.Repo, shards map[uint64]bool) (*pfs.RepoInfo, error)
	ListRepo(shards map[uint64]bool) ([]*pfs.RepoInfo, error)
	DeleteRepo(repo *pfs.Repo, shards map[uint64]bool) error
	StartCommit(parent *pfs.Commit, commit *pfs.Commit, started *google_protobuf.Timestamp, shards map[uint64]bool) error
	FinishCommit(commit *pfs.Commit, finished *google_protobuf.Timestamp, shards map[uint64]bool) error
	InspectCommit(commit *pfs.Commit, shards map[uint64]bool) (*pfs.CommitInfo, error)
	ListCommit(repo []*pfs.Repo, fromCommit []*pfs.Commit, shards map[uint64]bool) ([]*pfs.CommitInfo, error)
	DeleteCommit(commit *pfs.Commit, shards map[uint64]bool) error
	PutFile(file *pfs.File, shard uint64, offset int64, reader io.Reader) error
	MakeDirectory(file *pfs.File, shards map[uint64]bool) error
	GetFile(file *pfs.File, filterShard *pfs.Shard, offset int64, size int64, shard uint64) (io.ReadCloser, error)
	InspectFile(file *pfs.File, filterShard *pfs.Shard, shard uint64) (*pfs.FileInfo, error)
	ListFile(file *pfs.File, filterShard *pfs.Shard, shard uint64) ([]*pfs.FileInfo, error)
	DeleteFile(file *pfs.File, shard uint64) error
	AddShard(shard uint64) error
	DeleteShard(shard uint64) error
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go 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 gob

import (
	"bytes";
	"io";
	"os";
	"reflect";
	"sync";
)

// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
	mutex		sync.Mutex;					// each item must be received atomically
	r		io.Reader;					// source of the data
	wireType	map[typeId]*wireType;				// map from remote ID to local description
	decoderCache	map[reflect.Type]map[typeId]**decEngine;	// cache of compiled engines
	ignorerCache	map[typeId]**decEngine;				// ditto for ignored objects
	state		*decodeState;					// reads data from in-memory buffer
	countState	*decodeState;					// reads counts from wire
	buf		[]byte;
	oneByte		[]byte;
}

// NewDecoder returns a new decoder that reads from the io.Reader.
func NewDecoder(r io.Reader) *Decoder {
	dec := new(Decoder);
	dec.r = r;
	dec.wireType = make(map[typeId]*wireType);
	dec.state = newDecodeState(nil);	// buffer set in Decode(); rest is unimportant
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine);
	dec.ignorerCache = make(map[typeId]**decEngine);
	dec.oneByte = make([]byte, 1);

	return dec;
}

func (dec *Decoder) recvType(id typeId) {
	// Have we already seen this type?  That's an error
	if _, alreadySeen := dec.wireType[id]; alreadySeen {
		dec.state.err = os.ErrorString("gob: duplicate type received");
		return;
	}

	// Type:
	wire := new(wireType);
	dec.state.err = dec.decode(tWireType, wire);
	// Remember we've seen this type.
	dec.wireType[id] = wire;
}

// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// The value underlying e must be the correct type for the next
// data item received.
func (dec *Decoder) Decode(e interface{}) os.Error {
	// If e represents a value, the answer won't get back to the
	// caller.  Make sure it's a pointer.
	if _, ok := reflect.Typeof(e).(*reflect.PtrType); !ok {
		dec.state.err = os.ErrorString("gob: attempt to decode into a non-pointer");
		return dec.state.err;
	}

	// Make sure we're single-threaded through here.
	dec.mutex.Lock();
	defer dec.mutex.Unlock();

	dec.state.err = nil;
	for {
		// Read a count.
		var nbytes uint64;
		nbytes, dec.state.err = decodeUintReader(dec.r, dec.oneByte);
		if dec.state.err != nil {
			break
		}
		// Allocate the buffer.
		if nbytes > uint64(len(dec.buf)) {
			dec.buf = make([]byte, nbytes+1000)
		}
		dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes]);

		// Read the data
		_, dec.state.err = io.ReadFull(dec.r, dec.buf[0:nbytes]);
		if dec.state.err != nil {
			if dec.state.err == os.EOF {
				dec.state.err = io.ErrUnexpectedEOF
			}
			break;
		}

		// Receive a type id.
		id := typeId(decodeInt(dec.state));
		if dec.state.err != nil {
			break
		}

		// Is it a new type?
		if id < 0 {	// 0 is the error state, handled above
			// If the id is negative, we have a type.
			dec.recvType(-id);
			if dec.state.err != nil {
				break
			}
			continue;
		}

		// No, it's a value.
		// Make sure the type has been defined already.
		_, ok := dec.wireType[id];
		if !ok {
			dec.state.err = errBadType;
			break;
		}
		dec.state.err = dec.decode(id, e);
		break;
	}
	return dec.state.err;
}
<commit_msg>fix bug for large counts: used a one-byte buffer.<commit_after>// Copyright 2009 The Go 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 gob

import (
	"bytes";
	"io";
	"os";
	"reflect";
	"sync";
)

// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
	mutex		sync.Mutex;					// each item must be received atomically
	r		io.Reader;					// source of the data
	wireType	map[typeId]*wireType;				// map from remote ID to local description
	decoderCache	map[reflect.Type]map[typeId]**decEngine;	// cache of compiled engines
	ignorerCache	map[typeId]**decEngine;				// ditto for ignored objects
	state		*decodeState;					// reads data from in-memory buffer
	countState	*decodeState;					// reads counts from wire
	buf		[]byte;
	countBuf	[9]byte;	// counts may be uint64s (unlikely!), require 9 bytes
}

// NewDecoder returns a new decoder that reads from the io.Reader.
func NewDecoder(r io.Reader) *Decoder {
	dec := new(Decoder);
	dec.r = r;
	dec.wireType = make(map[typeId]*wireType);
	dec.state = newDecodeState(nil);	// buffer set in Decode(); rest is unimportant
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine);
	dec.ignorerCache = make(map[typeId]**decEngine);

	return dec;
}

func (dec *Decoder) recvType(id typeId) {
	// Have we already seen this type?  That's an error
	if _, alreadySeen := dec.wireType[id]; alreadySeen {
		dec.state.err = os.ErrorString("gob: duplicate type received");
		return;
	}

	// Type:
	wire := new(wireType);
	dec.state.err = dec.decode(tWireType, wire);
	// Remember we've seen this type.
	dec.wireType[id] = wire;
}

// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// The value underlying e must be the correct type for the next
// data item received.
func (dec *Decoder) Decode(e interface{}) os.Error {
	// If e represents a value, the answer won't get back to the
	// caller.  Make sure it's a pointer.
	if _, ok := reflect.Typeof(e).(*reflect.PtrType); !ok {
		dec.state.err = os.ErrorString("gob: attempt to decode into a non-pointer");
		return dec.state.err;
	}

	// Make sure we're single-threaded through here.
	dec.mutex.Lock();
	defer dec.mutex.Unlock();

	dec.state.err = nil;
	for {
		// Read a count.
		var nbytes uint64;
		nbytes, dec.state.err = decodeUintReader(dec.r, dec.countBuf[0:]);
		if dec.state.err != nil {
			break
		}
		// Allocate the buffer.
		if nbytes > uint64(len(dec.buf)) {
			dec.buf = make([]byte, nbytes+1000)
		}
		dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes]);

		// Read the data
		_, dec.state.err = io.ReadFull(dec.r, dec.buf[0:nbytes]);
		if dec.state.err != nil {
			if dec.state.err == os.EOF {
				dec.state.err = io.ErrUnexpectedEOF
			}
			break;
		}

		// Receive a type id.
		id := typeId(decodeInt(dec.state));
		if dec.state.err != nil {
			break
		}

		// Is it a new type?
		if id < 0 {	// 0 is the error state, handled above
			// If the id is negative, we have a type.
			dec.recvType(-id);
			if dec.state.err != nil {
				break
			}
			continue;
		}

		// No, it's a value.
		// Make sure the type has been defined already.
		_, ok := dec.wireType[id];
		if !ok {
			dec.state.err = errBadType;
			break;
		}
		dec.state.err = dec.decode(id, e);
		break;
	}
	return dec.state.err;
}
<|endoftext|>


<commit_before>// Copyright 2018 Istio 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 v2_test

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"istio.io/istio/istioctl/pkg/util/configdump"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pilot/pkg/proxy/envoy/v2"
	"istio.io/istio/tests/util"
)

func TestSyncz(t *testing.T) {
	t.Run("return the sent and ack status of adsClient connections", func(t *testing.T) {
		initLocalPilotTestEnv(t)
		adsstr, err := connectADS(util.MockPilotGrpcAddr)
		if err != nil {
			t.Fatal(err)
		}
		defer adsstr.CloseSend()

		// Need to send two of each so that the second sends an Ack that is picked up
		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}

		for i := 0; i < 4; i++ {
			_, err := adsReceive(adsstr, 5*time.Second)
			if err != nil {
				t.Fatal("Recv failed", err)
			}
		}
		node, _ := model.ParseServiceNode(sidecarId(app3Ip, "syncApp"))
		verifySyncStatus(t, getSyncStatus(t), node.ID, true, true)
	})
	t.Run("sync status not set when Nackd", func(t *testing.T) {
		initLocalPilotTestEnv(t)
		adsstr, err := connectADS(util.MockPilotGrpcAddr)
		if err != nil {
			t.Fatal(err)
		}
		defer adsstr.CloseSend()

		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendEDSNack([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSNack(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSNack(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp2"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSNack(sidecarId(app3Ip, "syncApp2"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		for i := 0; i < 5; i++ {
			_, err := adsReceive(adsstr, 5*time.Second)
			if err != nil {
				t.Fatal("Recv failed", err)
			}
		}
		node, _ := model.ParseServiceNode(sidecarId(app3Ip, "syncApp2"))
		verifySyncStatus(t, getSyncStatus(t), node.ID, true, false)
	})
}

func getSyncStatus(t *testing.T) []v2.SyncStatus {
	req, err := http.NewRequest("GET", "/debug", nil)
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	syncz := http.HandlerFunc(v2.Syncz)
	syncz.ServeHTTP(rr, req)
	got := []v2.SyncStatus{}
	if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
		t.Error(err)
	}
	return got
}

func verifySyncStatus(t *testing.T, gotStatus []v2.SyncStatus, nodeID string, wantSent, wantAcked bool) {
	// This is a mostly horrible hack because the single pilot instance is shared across multiple tests
	// This makes this test contaminated by others
	for _, ss := range gotStatus {
		if ss.ProxyID == nodeID {
			if ss.ProxyVersion == "" {
				t.Errorf("ProxyVersion should always be set for %v", nodeID)
			}
			if (ss.ClusterSent != "") != wantSent {
				t.Errorf("wanted ClusterSent set %v got %v for %v", wantSent, ss.ClusterSent, nodeID)
			}
			if (ss.ClusterAcked != "") != wantAcked {
				t.Errorf("wanted ClusterAcked set %v got %v for %v", wantAcked, ss.ClusterAcked, nodeID)
			}
			if (ss.ListenerSent != "") != wantSent {
				t.Errorf("wanted ListenerSent set %v got %v for %v", wantSent, ss.ListenerSent, nodeID)
			}
			if (ss.ListenerAcked != "") != wantAcked {
				t.Errorf("wanted ListenerAcked set %v got %v for %v", wantAcked, ss.ListenerAcked, nodeID)
			}
			if (ss.RouteSent != "") != wantSent {
				t.Errorf("wanted RouteSent set %v got %v for %v", wantSent, ss.RouteSent, nodeID)
			}
			if (ss.RouteAcked != "") != wantAcked {
				t.Errorf("wanted RouteAcked set %v got %v for %v", wantAcked, ss.RouteAcked, nodeID)
			}
			if (ss.EndpointSent != "") != wantSent {
				t.Errorf("wanted EndpointSent set %v got %v for %v", wantSent, ss.EndpointSent, nodeID)
			}
			if (ss.EndpointAcked != "") != wantAcked {
				t.Errorf("wanted EndpointAcked set %v got %v for %v", wantAcked, ss.EndpointAcked, nodeID)
			}
			if (ss.EndpointPercent != 0) != wantAcked {
				t.Errorf("wanted EndpointPercent set %v got %v for %v", wantAcked, ss.EndpointPercent, nodeID)
			}
			return
		}
	}
	t.Errorf("node id %v not found", nodeID)
}

func TestConfigDump(t *testing.T) {
	tests := []struct {
		name     string
		wantCode int
		proxyID  string
	}{
		{
			name:     "dumps most recent proxy with 200",
			proxyID:  "dumpApp-644fc65469-96dza.testns",
			wantCode: 200,
		},
		{
			name:     "returns 404 if proxy not found",
			proxyID:  "not-found",
			wantCode: 404,
		},
		{
			name:     "returns 400 if no proxyID",
			proxyID:  "",
			wantCode: 400,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			s := initLocalPilotTestEnv(t)
			for i := 0; i < 2; i++ {
				envoy, err := connectADS(util.MockPilotGrpcAddr)
				if err != nil {
					t.Fatal(err)
				}
				defer envoy.CloseSend()
				if err := sendCDSReq(sidecarId(app3Ip, "dumpApp"), envoy); err != nil {
					t.Fatal(err)
				}
				if err := sendLDSReq(sidecarId(app3Ip, "dumpApp"), envoy); err != nil {
					t.Fatal(err)
				}
				// Only most recent proxy will have routes
				if i == 1 {
					if err := sendRDSReq(sidecarId(app3Ip, "dumpApp"), []string{"80", "8080"}, envoy); err != nil {
						t.Fatal(err)
					}
					_, err := adsReceive(envoy, 5*time.Second)
					if err != nil {
						t.Fatal("Recv failed", err)
					}
				}
				for j := 0; j < 2; j++ {
					_, err := adsReceive(envoy, 5*time.Second)
					if err != nil {
						t.Fatal("Recv failed", err)
					}
				}
			}
			wrapper := getConfigDump(t, s.EnvoyXdsServer, tt.proxyID, tt.wantCode)
			if wrapper != nil {
				if rs, err := wrapper.GetDynamicRouteDump(false); err != nil || len(rs.DynamicRouteConfigs) == 0 {
					t.Errorf("routes were present, must have received an older connection's dump")
				}
			} else if tt.wantCode < 400 {
				t.Error("expected a non-nil wrapper with successful status code")
			}
		})
	}
}

func getConfigDump(t *testing.T, s *v2.DiscoveryServer, proxyID string, wantCode int) *configdump.Wrapper {
	path := "/config_dump"
	if proxyID != "" {
		path += fmt.Sprintf("?proxyID=%v", proxyID)
	}
	req, err := http.NewRequest("GET", path, nil)
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	syncz := http.HandlerFunc(s.ConfigDump)
	syncz.ServeHTTP(rr, req)
	if rr.Code != wantCode {
		t.Errorf("wanted response code %v, got %v", wantCode, rr.Code)
	}
	if wantCode > 399 {
		return nil
	}
	got := &configdump.Wrapper{}
	if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
		t.Fatalf(err.Error())
	}
	return got
}
<commit_msg>speculate fix for flaky syncz tests (#7703)<commit_after>// Copyright 2018 Istio 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 v2_test

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"istio.io/istio/istioctl/pkg/util/configdump"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pilot/pkg/proxy/envoy/v2"
	"istio.io/istio/tests/util"
)

func TestSyncz(t *testing.T) {
	t.Run("return the sent and ack status of adsClient connections", func(t *testing.T) {
		initLocalPilotTestEnv(t)
		adsstr, err := connectADS(util.MockPilotGrpcAddr)
		if err != nil {
			t.Fatal(err)
		}
		defer adsstr.CloseSend()

		// Need to send two of each so that the second sends an Ack that is picked up
		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}

		for i := 0; i < 4; i++ {
			_, err := adsReceive(adsstr, 5*time.Second)
			if err != nil {
				t.Fatal("Recv failed", err)
			}
		}
		node, _ := model.ParseServiceNode(sidecarId(app3Ip, "syncApp"))
		verifySyncStatus(t, node.ID, true, true)
	})
	t.Run("sync status not set when Nackd", func(t *testing.T) {
		initLocalPilotTestEnv(t)
		adsstr, err := connectADS(util.MockPilotGrpcAddr)
		if err != nil {
			t.Fatal(err)
		}
		defer adsstr.CloseSend()

		if err := sendEDSReq([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendEDSNack([]string{"outbound|9080||app2.default.svc.cluster.local"}, sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSReq(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendCDSNack(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSReq(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendLDSNack(sidecarId(app3Ip, "syncApp2"), adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSReq(sidecarId(app3Ip, "syncApp2"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		if err := sendRDSNack(sidecarId(app3Ip, "syncApp2"), []string{"80", "8080"}, adsstr); err != nil {
			t.Fatal(err)
		}
		for i := 0; i < 5; i++ {
			_, err := adsReceive(adsstr, 5*time.Second)
			if err != nil {
				t.Fatal("Recv failed", err)
			}
		}
		node, _ := model.ParseServiceNode(sidecarId(app3Ip, "syncApp2"))
		verifySyncStatus(t, node.ID, true, false)
	})
}

func getSyncStatus(t *testing.T) []v2.SyncStatus {
	req, err := http.NewRequest("GET", "/debug", nil)
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	syncz := http.HandlerFunc(v2.Syncz)
	syncz.ServeHTTP(rr, req)
	got := []v2.SyncStatus{}
	if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
		t.Error(err)
	}
	return got
}

func verifySyncStatus(t *testing.T, nodeID string, wantSent, wantAcked bool) {
	// This is a mostly horrible hack because the single pilot instance is shared across multiple tests
	// This makes this test contaminated by others and gives it horrible timing windows
	attempts := 5
	for i := 0; i < attempts; i++ {
		gotStatus := getSyncStatus(t)
		var errorHandler func(string, ...interface{})
		if i == attempts-1 {
			errorHandler = t.Errorf
		} else {
			errorHandler = t.Logf
		}
		for _, ss := range gotStatus {
			if ss.ProxyID == nodeID {
				if ss.ProxyVersion == "" {
					errorHandler("ProxyVersion should always be set for %v", nodeID)
				}
				if (ss.ClusterSent != "") != wantSent {
					errorHandler("wanted ClusterSent set %v got %v for %v", wantSent, ss.ClusterSent, nodeID)
				}
				if (ss.ClusterAcked != "") != wantAcked {
					errorHandler("wanted ClusterAcked set %v got %v for %v", wantAcked, ss.ClusterAcked, nodeID)
				}
				if (ss.ListenerSent != "") != wantSent {
					errorHandler("wanted ListenerSent set %v got %v for %v", wantSent, ss.ListenerSent, nodeID)
				}
				if (ss.ListenerAcked != "") != wantAcked {
					errorHandler("wanted ListenerAcked set %v got %v for %v", wantAcked, ss.ListenerAcked, nodeID)
				}
				if (ss.RouteSent != "") != wantSent {
					errorHandler("wanted RouteSent set %v got %v for %v", wantSent, ss.RouteSent, nodeID)
				}
				if (ss.RouteAcked != "") != wantAcked {
					errorHandler("wanted RouteAcked set %v got %v for %v", wantAcked, ss.RouteAcked, nodeID)
				}
				if (ss.EndpointSent != "") != wantSent {
					errorHandler("wanted EndpointSent set %v got %v for %v", wantSent, ss.EndpointSent, nodeID)
				}
				if (ss.EndpointAcked != "") != wantAcked {
					errorHandler("wanted EndpointAcked set %v got %v for %v", wantAcked, ss.EndpointAcked, nodeID)
				}
				if (ss.EndpointPercent != 0) != wantAcked {
					errorHandler("wanted EndpointPercent set %v got %v for %v", wantAcked, ss.EndpointPercent, nodeID)
				}
				return
			}
		}
		errorHandler("node id %v not found", nodeID)
	}
}

func TestConfigDump(t *testing.T) {
	tests := []struct {
		name     string
		wantCode int
		proxyID  string
	}{
		{
			name:     "dumps most recent proxy with 200",
			proxyID:  "dumpApp-644fc65469-96dza.testns",
			wantCode: 200,
		},
		{
			name:     "returns 404 if proxy not found",
			proxyID:  "not-found",
			wantCode: 404,
		},
		{
			name:     "returns 400 if no proxyID",
			proxyID:  "",
			wantCode: 400,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			s := initLocalPilotTestEnv(t)
			for i := 0; i < 2; i++ {
				envoy, err := connectADS(util.MockPilotGrpcAddr)
				if err != nil {
					t.Fatal(err)
				}
				defer envoy.CloseSend()
				if err := sendCDSReq(sidecarId(app3Ip, "dumpApp"), envoy); err != nil {
					t.Fatal(err)
				}
				if err := sendLDSReq(sidecarId(app3Ip, "dumpApp"), envoy); err != nil {
					t.Fatal(err)
				}
				// Only most recent proxy will have routes
				if i == 1 {
					if err := sendRDSReq(sidecarId(app3Ip, "dumpApp"), []string{"80", "8080"}, envoy); err != nil {
						t.Fatal(err)
					}
					_, err := adsReceive(envoy, 5*time.Second)
					if err != nil {
						t.Fatal("Recv failed", err)
					}
				}
				for j := 0; j < 2; j++ {
					_, err := adsReceive(envoy, 5*time.Second)
					if err != nil {
						t.Fatal("Recv failed", err)
					}
				}
			}
			wrapper := getConfigDump(t, s.EnvoyXdsServer, tt.proxyID, tt.wantCode)
			if wrapper != nil {
				if rs, err := wrapper.GetDynamicRouteDump(false); err != nil || len(rs.DynamicRouteConfigs) == 0 {
					t.Errorf("routes were present, must have received an older connection's dump")
				}
			} else if tt.wantCode < 400 {
				t.Error("expected a non-nil wrapper with successful status code")
			}
		})
	}
}

func getConfigDump(t *testing.T, s *v2.DiscoveryServer, proxyID string, wantCode int) *configdump.Wrapper {
	path := "/config_dump"
	if proxyID != "" {
		path += fmt.Sprintf("?proxyID=%v", proxyID)
	}
	req, err := http.NewRequest("GET", path, nil)
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	syncz := http.HandlerFunc(s.ConfigDump)
	syncz.ServeHTTP(rr, req)
	if rr.Code != wantCode {
		t.Errorf("wanted response code %v, got %v", wantCode, rr.Code)
	}
	if wantCode > 399 {
		return nil
	}
	got := &configdump.Wrapper{}
	if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
		t.Fatalf(err.Error())
	}
	return got
}
<|endoftext|>


<commit_before>package whoson

import (
	"fmt"
	"net"
	"net/textproto"
	"strings"
	"time"

	"github.com/pkg/errors"
)

type Session struct {
	protocol ProtocolType
	id       uint64

	udpconn    *net.UDPConn
	remoteAddr *net.UDPAddr
	b          *Buffer

	tcpserver *TCPServer
	conn      net.Conn
	tp        *textproto.Conn
	tpid      uint

	cmdMethod MethodType
	cmdIp     net.IP
	cmdArgs   string
}

func NewSessionUDP(c *net.UDPConn, r *net.UDPAddr, b *Buffer) (*Session, error) {
	id, err := IDGenerator.NextID()
	if err != nil {
		return nil, err
	}

	return &Session{
		protocol:   pUDP,
		id:         id,
		udpconn:    c,
		remoteAddr: r,
		b:          b,
	}, nil
}

func NewSessionTCP(s *TCPServer, c net.Conn) (*Session, error) {
	id, err := IDGenerator.NextID()
	if err != nil {
		return nil, err
	}

	return &Session{
		protocol:  pTCP,
		id:        id,
		tcpserver: s,
		conn:      c,
		tp:        textproto.NewConn(c),
	}, nil
}

func (ses *Session) setTpId() {
	ses.tpid = ses.tp.Next()
}

func (ses *Session) methodType(m string) MethodType {
	if v, ok := methodFromString[m]; ok {
		return v
	} else {
		return mUnkownMethod
	}
}

func (ses *Session) parseCmd(line string) error {
	var cmd []string

	if strings.TrimSpace(line) == "" {
		return errors.New("command parse error")
	}

	w := strings.Split(line, " ")
	for i := range w {
		if w[i] != "" {
			cmd = append(cmd, strings.TrimSpace(w[i]))
		}
	}

	ses.cmdMethod = ses.methodType(strings.ToUpper(cmd[0]))
	switch ses.cmdMethod {
	case mLogin, mLogout, mQuery:
		if ses.cmdIp = net.ParseIP(cmd[1]); ses.cmdIp == nil {
			return errors.New("command parse error")
		}
		ses.cmdArgs = strings.Join(cmd[2:], " ")
	case mQuit:
		//pp.Println("Quit")
		ses.cmdArgs = strings.Join(cmd[1:], " ")
	default:
		return errors.New("command not found")
	}
	return nil
}

func (ses *Session) readLine() (string, error) {
	ses.tp.StartRequest(ses.tpid)
	l1, err := ses.tp.ReadLine()
	if err != nil {
		return "", err
	}

	l2, err := ses.tp.ReadLine()
	if err != nil {
		return "", err
	}
	ses.tp.EndRequest(ses.tpid)

	if l1 != "" && l2 == "" {
		return l1, nil
	} else {
		return "", errors.New("session read error")
	}
}

func (ses *Session) sendLine(str string) error {
	var err error
	if ses.protocol == pTCP {
		ses.tp.StartResponse(ses.tpid)
		err = ses.tp.PrintfLine(str + CRLF)
		ses.tp.EndResponse(ses.tpid)
	} else {
		b := []byte(str + CRLF + CRLF)
		_, err = ses.udpconn.WriteToUDP(b, ses.remoteAddr)
	}
	return err
}

func (ses *Session) sendResponsePositive(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rPositive], str))
}

func (ses *Session) sendResponseNegative(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rNegative], str))
}

func (ses *Session) sendResponseBadRequest(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rBadRequest], str))
}

func (ses *Session) resetCmd() {
	ses.cmdMethod = mUnkownMethod
	ses.cmdIp = nil
	ses.cmdArgs = ""
}

func (ses *Session) startHandler() bool {
	defer ses.resetCmd()
	var err error

	if ses.protocol == pTCP {
		ses.setTpId()

		line, err := ses.readLine()
		if err != nil {
			if opError, ok := err.(*net.OpError); ok && opError.Timeout() {
				return false
			}
			if err.Error() == "EOF" {
				return false
			} else {
				ses.sendResponseBadRequest(err.Error())
				return true
			}
		}
		err = ses.parseCmd(line)
		if err != nil {
			ses.sendResponseBadRequest(err.Error())
			return true
		}
	} else {
		err = ses.parseCmd(string(ses.b.buf[:ses.b.count]))
		if err != nil {
			ses.sendResponseBadRequest(err.Error())
			return true
		}
	}

	switch ses.cmdMethod {
	case mLogin:
		ses.methodLogin()
	case mLogout:
		ses.methodLogout()
	case mQuery:
		ses.methodQuery()
	case mQuit:
		ses.methodQuit()
	default:
		err := errors.New("handler error")
		ses.sendResponseBadRequest(err.Error())
	}
	Log("debug", "SessionHandler", ses, err)
	return true
}

func (ses *Session) methodLogin() {
	sd := &StoreData{
		Expire: time.Now().Add(StoreDataExpire),
		IP:     ses.cmdIp,
		Data:   ses.cmdArgs,
	}
	MainStore.Set(sd.Key(), sd)
	ses.sendResponsePositive("LOGIN OK")
}

func (ses *Session) methodLogout() {
	ok := MainStore.Del(ses.cmdIp.String())
	if ok {
		ses.sendResponsePositive("LOGOUT record deleted")
	} else {
		ses.sendResponsePositive("LOGOUT no such record, nothing done")
	}
}

func (ses *Session) methodQuery() {
	sd, err := MainStore.Get(ses.cmdIp.String())
	if err != nil {
		ses.sendResponseNegative("Not Logged in")
	} else {
		ses.sendResponsePositive(sd.Data)
	}
}

func (ses *Session) methodQuit() {
	ses.sendResponsePositive("QUIT OK")
	if ses.protocol == pTCP {
		ses.conn.Close()
	}
}

func (ses *Session) close() {
	if ses.protocol == pUDP {
		ses.b.Free()
	}
}
<commit_msg>Fix connection reset by peer<commit_after>package whoson

import (
	"fmt"
	"net"
	"net/textproto"
	"os"
	"strings"
	"syscall"
	"time"

	"github.com/pkg/errors"
)

type Session struct {
	protocol ProtocolType
	id       uint64

	udpconn    *net.UDPConn
	remoteAddr *net.UDPAddr
	b          *Buffer

	tcpserver *TCPServer
	conn      net.Conn
	tp        *textproto.Conn
	tpid      uint

	cmdMethod MethodType
	cmdIp     net.IP
	cmdArgs   string
}

func NewSessionUDP(c *net.UDPConn, r *net.UDPAddr, b *Buffer) (*Session, error) {
	id, err := IDGenerator.NextID()
	if err != nil {
		return nil, err
	}

	return &Session{
		protocol:   pUDP,
		id:         id,
		udpconn:    c,
		remoteAddr: r,
		b:          b,
	}, nil
}

func NewSessionTCP(s *TCPServer, c net.Conn) (*Session, error) {
	id, err := IDGenerator.NextID()
	if err != nil {
		return nil, err
	}

	return &Session{
		protocol:  pTCP,
		id:        id,
		tcpserver: s,
		conn:      c,
		tp:        textproto.NewConn(c),
	}, nil
}

func (ses *Session) setTpId() {
	ses.tpid = ses.tp.Next()
}

func (ses *Session) methodType(m string) MethodType {
	if v, ok := methodFromString[m]; ok {
		return v
	} else {
		return mUnkownMethod
	}
}

func (ses *Session) parseCmd(line string) error {
	var cmd []string

	if strings.TrimSpace(line) == "" {
		return errors.New("command parse error")
	}

	w := strings.Split(line, " ")
	for i := range w {
		if w[i] != "" {
			cmd = append(cmd, strings.TrimSpace(w[i]))
		}
	}

	ses.cmdMethod = ses.methodType(strings.ToUpper(cmd[0]))
	switch ses.cmdMethod {
	case mLogin, mLogout, mQuery:
		if ses.cmdIp = net.ParseIP(cmd[1]); ses.cmdIp == nil {
			return errors.New("command parse error")
		}
		ses.cmdArgs = strings.Join(cmd[2:], " ")
	case mQuit:
		//pp.Println("Quit")
		ses.cmdArgs = strings.Join(cmd[1:], " ")
	default:
		return errors.New("command not found")
	}
	return nil
}

func (ses *Session) readLine() (string, error) {
	ses.tp.StartRequest(ses.tpid)
	l1, err := ses.tp.ReadLine()
	if err != nil {
		return "", err
	}

	l2, err := ses.tp.ReadLine()
	if err != nil {
		return "", err
	}
	ses.tp.EndRequest(ses.tpid)

	if l1 != "" && l2 == "" {
		return l1, nil
	} else {
		return "", errors.New("session read error")
	}
}

func (ses *Session) sendLine(str string) error {
	var err error
	if ses.protocol == pTCP {
		ses.tp.StartResponse(ses.tpid)
		err = ses.tp.PrintfLine(str + CRLF)
		ses.tp.EndResponse(ses.tpid)
	} else {
		b := []byte(str + CRLF + CRLF)
		_, err = ses.udpconn.WriteToUDP(b, ses.remoteAddr)
	}
	return err
}

func (ses *Session) sendResponsePositive(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rPositive], str))
}

func (ses *Session) sendResponseNegative(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rNegative], str))
}

func (ses *Session) sendResponseBadRequest(str string) error {
	return ses.sendLine(fmt.Sprintf("%s%s", result[rBadRequest], str))
}

func (ses *Session) resetCmd() {
	ses.cmdMethod = mUnkownMethod
	ses.cmdIp = nil
	ses.cmdArgs = ""
}

func (ses *Session) startHandler() bool {
	defer ses.resetCmd()
	var err error

	if ses.protocol == pTCP {
		ses.setTpId()

		line, err := ses.readLine()
		if err != nil {
			if opError, ok := err.(*net.OpError); ok && opError.Timeout() {
				return false
			} else if ok {
				if opError2, ok2 := opError.Err.(*os.SyscallError); ok2 && opError2.Err == syscall.ECONNRESET {
					return false
				}
			} else if err.Error() == "EOF" {
				return false
			}
			ses.sendResponseBadRequest(err.Error())
			return true
		}
		err = ses.parseCmd(line)
		if err != nil {
			ses.sendResponseBadRequest(err.Error())
			return true
		}
	} else {
		err = ses.parseCmd(string(ses.b.buf[:ses.b.count]))
		if err != nil {
			ses.sendResponseBadRequest(err.Error())
			return true
		}
	}

	switch ses.cmdMethod {
	case mLogin:
		ses.methodLogin()
	case mLogout:
		ses.methodLogout()
	case mQuery:
		ses.methodQuery()
	case mQuit:
		ses.methodQuit()
	default:
		err := errors.New("handler error")
		ses.sendResponseBadRequest(err.Error())
	}
	Log("debug", "SessionHandler", ses, err)
	return true
}

func (ses *Session) methodLogin() {
	sd := &StoreData{
		Expire: time.Now().Add(StoreDataExpire),
		IP:     ses.cmdIp,
		Data:   ses.cmdArgs,
	}
	MainStore.Set(sd.Key(), sd)
	ses.sendResponsePositive("LOGIN OK")
}

func (ses *Session) methodLogout() {
	ok := MainStore.Del(ses.cmdIp.String())
	if ok {
		ses.sendResponsePositive("LOGOUT record deleted")
	} else {
		ses.sendResponsePositive("LOGOUT no such record, nothing done")
	}
}

func (ses *Session) methodQuery() {
	sd, err := MainStore.Get(ses.cmdIp.String())
	if err != nil {
		ses.sendResponseNegative("Not Logged in")
	} else {
		ses.sendResponsePositive(sd.Data)
	}
}

func (ses *Session) methodQuit() {
	ses.sendResponsePositive("QUIT OK")
	if ses.protocol == pTCP {
		ses.conn.Close()
	}
}

func (ses *Session) close() {
	if ses.protocol == pUDP {
		ses.b.Free()
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 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 aggregator

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"reflect"
	"regexp"
	"strings"
	"testing"
	"time"

	"github.com/go-openapi/spec"
	fuzz "github.com/google/gofuzz"
	"k8s.io/kube-openapi/pkg/util/sets"
)

func TestReplaceReferences(t *testing.T) {
	re, err := regexp.Compile("\"\\$ref\":\"(http://ref-[^\"]*)\"")
	if err != nil {
		t.Fatalf("failed to compile ref regex: %v", err)
	}

	for i := 0; i < 100; i++ {
		f := fuzz.New()
		seed := time.Now().UnixNano()
		//seed = int64(1548861570869173000)
		f.RandSource(rand.New(rand.NewSource(seed)))

		refNum := 0
		f.Funcs(
			func(ref *spec.Ref, c fuzz.Continue) {
				r, err := spec.NewRef(fmt.Sprintf("http://ref-%d", refNum))
				if err != nil {
					t.Fatalf("failed to fuzz ref: %v", err)
				}
				*ref = r
				refNum++
			},
			func(sa *spec.SchemaOrStringArray, c fuzz.Continue) {
				*sa = spec.SchemaOrStringArray{}
				if c.RandBool() {
					c.Fuzz(&sa.Schema)
				} else {
					c.Fuzz(&sa.Property)
				}
				if sa.Schema == nil && len(sa.Property) == 0 {
					*sa = spec.SchemaOrStringArray{Schema: &spec.Schema{}}
				}
			},
			func(url *spec.SchemaURL, c fuzz.Continue) {
				*url = spec.SchemaURL("http://url")
			},
			func(s *spec.Swagger, c fuzz.Continue) {
				// only fuzz those fields we walk into (we skip some like extensions)
				c.Fuzz(&s.Parameters)
				c.Fuzz(&s.Responses)
				c.Fuzz(&s.Definitions)
				c.Fuzz(&s.Paths)
			},
			func(p *spec.Parameter, c fuzz.Continue) {
				// only fuzz those fields we walk into
				c.Fuzz(&p.Ref)
				c.Fuzz(&p.Schema)
				if c.RandBool() {
					p.Items = &spec.Items{}
					c.Fuzz(&p.Items.Ref)
				}
			},
			func(s *spec.Response, c fuzz.Continue) {
				c.FuzzNoCustom(s)
				// we don't walk into headers
				s.Headers = nil
			},
			func(s *spec.Dependencies, c fuzz.Continue) {
				c.FuzzNoCustom(s)
				// we don't walk into dependencies
				*s = nil
			},
			func(i *interface{}, c fuzz.Continue) {
				// do nothing for examples and defaults.
			},
		)
		f.NilChance(0.92)
		f.NumElements(0, 3)

		fuzzedRefs := sets.NewString()
		var s *spec.Swagger
		for {
			// create random swagger spec with random URL references, but at least one ref
			s = &spec.Swagger{}
			f.Fuzz(s)

			// clone spec to normalize (fuzz might generate objects which do not roundtrip json marshalling
			var err error
			s, err = cloneSwagger(s)
			if err != nil {
				t.Fatalf("failed to normalize swagger after fuzzing: %v", err)
			}

			// find refs
			bs, err := json.Marshal(s)
			if err != nil {
				t.Fatalf("failed to marshal swagger: %v", err)
			}
			findings := re.FindAllStringSubmatch(string(bs), -1)
			if len(findings) > 0 {
				for _, m := range findings {
					fuzzedRefs.Insert(m[1])
				}
				break
			}
		}

		t.Run(fmt.Sprintf("iteration %d", i), func(t *testing.T) {
			mutatedRef := fuzzedRefs.List()[rand.Intn(fuzzedRefs.Len())]
			origString, err := json.Marshal(s)
			if err != nil {
				t.Fatalf("failed to marshal swagger: %v", err)
			}
			t.Logf("created schema with %d refs, mutating %q, seed %d: %s", fuzzedRefs.Len(), mutatedRef, seed, string(origString))

			// convert to json string, replace one of the refs, and unmarshal back
			mutatedString := strings.Replace(string(origString), "\""+mutatedRef+"\"", "\"http://mutated-ref\"", -1)
			mutatedViaJSON := &spec.Swagger{}
			if err := json.Unmarshal([]byte(mutatedString), mutatedViaJSON); err != nil {
				t.Fatalf("failed to unmarshal mutated spec: %v", err)
			}

			// replay the same mutation using the mutating walker
			seenRefs := sets.NewString()
			walker := mutatingReferenceWalker{
				walkRefCallback: func(ref *spec.Ref) *spec.Ref {
					seenRefs.Insert(ref.String())
					if ref.String() == mutatedRef {
						r, err := spec.NewRef("http://mutated-ref")
						if err != nil {
							t.Fatalf("failed to create ref: %v", err)
						}
						return &r
					}
					return ref
				},
			}
			mutatedViaWalker := walker.Start(s)

			// compare that we got the same
			if !reflect.DeepEqual(mutatedViaJSON, mutatedViaWalker) {
				t.Errorf("mutation via walker differ from JSON text replacement (got A, expected B): %s", objectDiff(mutatedViaWalker, mutatedViaJSON))
			}
			if !seenRefs.Equal(fuzzedRefs) {
				t.Errorf("expected to see the same refs in the walker as during fuzzing. Not seen: %v", fuzzedRefs.Difference(seenRefs).List())
			}
		})
	}
}

func cloneSwagger(orig *spec.Swagger) (*spec.Swagger, error) {
	bs, err := json.Marshal(orig)
	if err != nil {
		return nil, err
	}
	s := &spec.Swagger{}
	if err := json.Unmarshal(bs, s); err != nil {
		return nil, err
	}
	return s, nil
}

// stringDiff diffs a and b and returns a human readable diff.
func stringDiff(a, b string) string {
	ba := []byte(a)
	bb := []byte(b)
	out := []byte{}
	i := 0
	for ; i < len(ba) && i < len(bb); i++ {
		if ba[i] != bb[i] {
			break
		}
		out = append(out, ba[i])
	}
	out = append(out, []byte("\n\nA: ")...)
	out = append(out, ba[i:]...)
	out = append(out, []byte("\n\nB: ")...)
	out = append(out, bb[i:]...)
	out = append(out, []byte("\n\n")...)
	return string(out)
}

// objectDiff writes the two objects out as JSON and prints out the identical part of
// the objects followed by the remaining part of 'a' and finally the remaining part of 'b'.
// For debugging tests.
func objectDiff(a, b interface{}) string {
	ab, err := json.Marshal(a)
	if err != nil {
		panic(fmt.Sprintf("a: %v", err))
	}
	bb, err := json.Marshal(b)
	if err != nil {
		panic(fmt.Sprintf("b: %v", err))
	}
	return stringDiff(string(ab), string(bb))
}
<commit_msg>aggregator: add fuzzer completeness test<commit_after>/*
Copyright 2019 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 aggregator

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"reflect"
	"regexp"
	"strings"
	"testing"
	"time"

	"github.com/go-openapi/spec"
	fuzz "github.com/google/gofuzz"
	"k8s.io/kube-openapi/pkg/util/sets"
)

func fuzzFuncs(f *fuzz.Fuzzer, refFunc func(ref *spec.Ref, c fuzz.Continue, visible bool)) {
	invisible := 0 // == 0 means visible, > 0 means invisible
	f.Funcs(
		func(ref *spec.Ref, c fuzz.Continue) {
			refFunc(ref, c, invisible == 0)
		},
		func(sa *spec.SchemaOrStringArray, c fuzz.Continue) {
			*sa = spec.SchemaOrStringArray{}
			if c.RandBool() {
				c.Fuzz(&sa.Schema)
			} else {
				c.Fuzz(&sa.Property)
			}
			if sa.Schema == nil && len(sa.Property) == 0 {
				*sa = spec.SchemaOrStringArray{Schema: &spec.Schema{}}
			}
		},
		func(url *spec.SchemaURL, c fuzz.Continue) {
			*url = spec.SchemaURL("http://url")
		},
		func(s *spec.Swagger, c fuzz.Continue) {
			// fuzz everything first with invisible==true
			invisible++
			c.FuzzNoCustom(s)
			invisible--

			// only fuzz those fields we walk into with invisible==false
			c.Fuzz(&s.Parameters)
			c.Fuzz(&s.Responses)
			c.Fuzz(&s.Definitions)
			c.Fuzz(&s.Paths)
		},
		func(p *spec.Parameter, c fuzz.Continue) {
			// fuzz everything first with invisible==true
			invisible++
			c.FuzzNoCustom(p)
			invisible--

			// only fuzz those fields we walk into with invisible==false
			c.Fuzz(&p.Ref)
			c.Fuzz(&p.Schema)
			if c.RandBool() {
				p.Items = &spec.Items{}
				c.Fuzz(&p.Items.Ref)
			} else {
				p.Items = nil
			}
		},
		func(s *spec.Response, c fuzz.Continue) {
			// fuzz everything first with invisible==true
			invisible++
			c.FuzzNoCustom(s)
			invisible--

			// only fuzz those fields we walk into with invisible==false
			c.Fuzz(&s.Ref)
			c.Fuzz(&s.Description)
			c.Fuzz(&s.Schema)
			c.Fuzz(&s.Examples)
		},
		func(s *spec.Dependencies, c fuzz.Continue) {
			// fuzz everything first with invisible==true
			invisible++
			c.FuzzNoCustom(s)
			invisible--

			// and nothing with invisible==false
		},
		func(i *interface{}, c fuzz.Continue) {
			// do nothing for examples and defaults. These are free form JSON fields.
		},
	)
}

func TestReplaceReferences(t *testing.T) {
	visibleRE, err := regexp.Compile("\"\\$ref\":\"(http://ref-[^\"]*)\"")
	if err != nil {
		t.Fatalf("failed to compile ref regex: %v", err)
	}
	invisibleRE, err := regexp.Compile("\"\\$ref\":\"(http://invisible-[^\"]*)\"")
	if err != nil {
		t.Fatalf("failed to compile ref regex: %v", err)
	}

	for i := 0; i < 1000; i++ {
		var visibleRefs, invisibleRefs sets.String
		var seed int64
		var s *spec.Swagger
		for {
			visibleRefs = sets.NewString()
			invisibleRefs = sets.NewString()

			f := fuzz.New()
			seed = time.Now().UnixNano()
			//seed = int64(1548953540354558000)
			f.RandSource(rand.New(rand.NewSource(seed)))

			fuzzFuncs(f,
				func(ref *spec.Ref, c fuzz.Continue, visible bool) {
					var url string
					if visible {
						// this is a ref that is seen by the walker (we have some exceptions where we don't walk into)
						url = fmt.Sprintf("http://ref-%d", visibleRefs.Len())
					} else {
						// this is a ref that is not seen by the walker (we have some exceptions where we don't walk into)
						url = fmt.Sprintf("http://invisible-%d", invisibleRefs.Len())
					}

					r, err := spec.NewRef(url)
					if err != nil {
						t.Fatalf("failed to fuzz ref: %v", err)
					}
					*ref = r
				},
			)
			f.NilChance(0.92)
			f.NumElements(0, 3)

			// create random swagger spec with random URL references, but at least one ref
			s = &spec.Swagger{}
			f.Fuzz(s)

			// clone spec to normalize (fuzz might generate objects which do not roundtrip json marshalling
			var err error
			s, err = cloneSwagger(s)
			if err != nil {
				t.Fatalf("failed to normalize swagger after fuzzing: %v", err)
			}

			// find refs
			bs, err := json.Marshal(s)
			if err != nil {
				t.Fatalf("failed to marshal swagger: %v", err)
			}
			for _, m := range invisibleRE.FindAllStringSubmatch(string(bs), -1) {
				invisibleRefs.Insert(m[1])
			}
			if res := visibleRE.FindAllStringSubmatch(string(bs), -1); len(res) > 0 {
				for _, m := range res {
					visibleRefs.Insert(m[1])
				}
				break
			}
		}

		t.Run(fmt.Sprintf("iteration %d", i), func(t *testing.T) {
			mutatedRef := visibleRefs.List()[rand.Intn(visibleRefs.Len())]
			origString, err := json.Marshal(s)
			if err != nil {
				t.Fatalf("failed to marshal swagger: %v", err)
			}
			t.Logf("created schema with %d walked refs, %d invisible refs, mutating %q, seed %d: %s", visibleRefs.Len(), invisibleRefs.Len(), mutatedRef, seed, string(origString))

			// convert to json string, replace one of the refs, and unmarshal back
			mutatedString := strings.Replace(string(origString), "\""+mutatedRef+"\"", "\"http://mutated-ref\"", -1)
			mutatedViaJSON := &spec.Swagger{}
			if err := json.Unmarshal([]byte(mutatedString), mutatedViaJSON); err != nil {
				t.Fatalf("failed to unmarshal mutated spec: %v", err)
			}

			// replay the same mutation using the mutating walker
			seenRefs := sets.NewString()
			walker := mutatingReferenceWalker{
				walkRefCallback: func(ref *spec.Ref) *spec.Ref {
					seenRefs.Insert(ref.String())
					if ref.String() == mutatedRef {
						r, err := spec.NewRef("http://mutated-ref")
						if err != nil {
							t.Fatalf("failed to create ref: %v", err)
						}
						return &r
					}
					return ref
				},
			}
			mutatedViaWalker := walker.Start(s)

			// compare that we got the same
			if !reflect.DeepEqual(mutatedViaJSON, mutatedViaWalker) {
				t.Errorf("mutation via walker differ from JSON text replacement (got A, expected B): %s", objectDiff(mutatedViaWalker, mutatedViaJSON))
			}
			if !seenRefs.HasAll(visibleRefs.List()...) {
				t.Errorf("expected to see the same refs in the walker as during fuzzing. Not seen: %v", visibleRefs.Difference(seenRefs).List())
			}
			if shouldNotSee := seenRefs.Intersection(invisibleRefs); shouldNotSee.Len() > 0 {
				t.Errorf("refs seen that the walker is not expected to see: %v", shouldNotSee.List())
			}
		})
	}
}

func cloneSwagger(orig *spec.Swagger) (*spec.Swagger, error) {
	bs, err := json.Marshal(orig)
	if err != nil {
		return nil, err
	}
	s := &spec.Swagger{}
	if err := json.Unmarshal(bs, s); err != nil {
		return nil, err
	}
	return s, nil
}

// stringDiff diffs a and b and returns a human readable diff.
func stringDiff(a, b string) string {
	ba := []byte(a)
	bb := []byte(b)
	out := []byte{}
	i := 0
	for ; i < len(ba) && i < len(bb); i++ {
		if ba[i] != bb[i] {
			break
		}
		out = append(out, ba[i])
	}
	out = append(out, []byte("\n\nA: ")...)
	out = append(out, ba[i:]...)
	out = append(out, []byte("\n\nB: ")...)
	out = append(out, bb[i:]...)
	out = append(out, []byte("\n\n")...)
	return string(out)
}

// objectDiff writes the two objects out as JSON and prints out the identical part of
// the objects followed by the remaining part of 'a' and finally the remaining part of 'b'.
// For debugging tests.
func objectDiff(a, b interface{}) string {
	ab, err := json.Marshal(a)
	if err != nil {
		panic(fmt.Sprintf("a: %v", err))
	}
	bb, err := json.Marshal(b)
	if err != nil {
		panic(fmt.Sprintf("b: %v", err))
	}
	return stringDiff(string(ab), string(bb))
}
<|endoftext|>