<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 command

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSuccess(t *testing.T) {
	res, err := New("echo", "hi").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessPipe(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat").
		Pipe("cat").
		Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Equal(t, "hi", res.Output())
}

func TestFailurePipeWrongCommand(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("wrong").
		Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestFailurePipeWrongArgument(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat", "--wrong").
		Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Empty(t, res.Output())
	require.Contains(t, res.Error(), "unrecognized option")
}

func TestSuccessWithWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/", "ls", "-1").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestFailureWithWrongWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/should/not/exist", "ls", "-1").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessSilent(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSepareted(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSingleArgument(t *testing.T) {
	res, err := New("echo").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessNoArgument(t *testing.T) {
	res, err := New("").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hello world").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.Output())
}

func TestSuccessError(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.Empty(t, res.Output())
	require.Contains(t, res.Error(), "No such file")
}

func TestSuccessOutputSeparated(t *testing.T) {
	res, err := New("echo", "-n", "hello").Run()
	require.Nil(t, err)
	require.Equal(t, "hello", res.Output())
}

func TestFailureStdErr(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Equal(t, res.ExitCode(), 1)
}

func TestFailureNotExisting(t *testing.T) {
	res, err := New("/not/valid").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessExecute(t *testing.T) {
	err := Execute("echo", "-n", "hi", "ho")
	require.Nil(t, err)
}

func TestFailureExecute(t *testing.T) {
	err := Execute("cat", "/not/invalid")
	require.NotNil(t, err)
}

func TestAvailableSuccessValidCommand(t *testing.T) {
	res := Available("echo")
	require.True(t, res)
}

func TestAvailableSuccessEmptyCommands(t *testing.T) {
	res := Available()
	require.True(t, res)
}

func TestAvailableFailure(t *testing.T) {
	res := Available("echo", "this-command-should-not-exist")
	require.False(t, res)
}

func TestSuccessRunSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSuccess())
}

func TestFailureRunSuccess(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSuccess())
}

func TestSuccessRunSilentSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSilentSuccess())
}

func TestFailureRunSuccessSilent(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSilentSuccess())
}
<commit_msg>Fix unit tests for macOS<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 command

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSuccess(t *testing.T) {
	res, err := New("echo", "hi").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessPipe(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat").
		Pipe("cat").
		Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Equal(t, "hi", res.Output())
}

func TestFailurePipeWrongCommand(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("wrong").
		Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestFailurePipeWrongArgument(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat", "--wrong").
		Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Empty(t, res.Output())
	require.NotEmpty(t, res.Error())
}

func TestSuccessWithWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/", "ls", "-1").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestFailureWithWrongWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/should/not/exist", "ls", "-1").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessSilent(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSepareted(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSingleArgument(t *testing.T) {
	res, err := New("echo").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessNoArgument(t *testing.T) {
	res, err := New("").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hello world").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.Output())
}

func TestSuccessError(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.Empty(t, res.Output())
	require.Contains(t, res.Error(), "No such file")
}

func TestSuccessOutputSeparated(t *testing.T) {
	res, err := New("echo", "-n", "hello").Run()
	require.Nil(t, err)
	require.Equal(t, "hello", res.Output())
}

func TestFailureStdErr(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Equal(t, res.ExitCode(), 1)
}

func TestFailureNotExisting(t *testing.T) {
	res, err := New("/not/valid").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessExecute(t *testing.T) {
	err := Execute("echo", "-n", "hi", "ho")
	require.Nil(t, err)
}

func TestFailureExecute(t *testing.T) {
	err := Execute("cat", "/not/invalid")
	require.NotNil(t, err)
}

func TestAvailableSuccessValidCommand(t *testing.T) {
	res := Available("echo")
	require.True(t, res)
}

func TestAvailableSuccessEmptyCommands(t *testing.T) {
	res := Available()
	require.True(t, res)
}

func TestAvailableFailure(t *testing.T) {
	res := Available("echo", "this-command-should-not-exist")
	require.False(t, res)
}

func TestSuccessRunSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSuccess())
}

func TestFailureRunSuccess(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSuccess())
}

func TestSuccessRunSilentSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSilentSuccess())
}

func TestFailureRunSuccessSilent(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSilentSuccess())
}
<|endoftext|>


<commit_before>package rss

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"sort"
	"strings"
	"time"
)

func parseRSS2(data []byte, read *db) (*Feed, error) {
	warnings := false
	feed := rss2_0Feed{}
	p := xml.NewDecoder(bytes.NewReader(data))
	p.DefaultSpace = "RssDefault"
	p.CharsetReader = charsetReader
	err := p.Decode(&feed)
	if err != nil {
		return nil, err
	}
	if feed.Channel == nil {
		return nil, fmt.Errorf("Error: no channel found in %q.", string(data))
	}

	channel := feed.Channel

	out := new(Feed)
	out.Title = channel.Title
	out.Description = channel.Description
	for _, link := range channel.Link {
		if link.Rel == "" && link.Type == "" && link.Href == "" && link.Chardata != "" {
			out.Link = link.Chardata
			break
		}
	}
	out.Image = channel.Image.Image()
	if channel.MinsToLive != 0 {
		sort.Ints(channel.SkipHours)
		next := time.Now().Add(time.Duration(channel.MinsToLive) * time.Minute)
		for _, hour := range channel.SkipHours {
			if hour == next.Hour() {
				next.Add(time.Duration(60-next.Minute()) * time.Minute)
			}
		}
		trying := true
		for trying {
			trying = false
			for _, day := range channel.SkipDays {
				if strings.Title(day) == next.Weekday().String() {
					next.Add(time.Duration(24-next.Hour()) * time.Hour)
					trying = true
					break
				}
			}
		}

		out.Refresh = next
	}

	if out.Refresh.IsZero() {
		out.Refresh = time.Now().Add(10 * time.Minute)
	}

	if channel.Items == nil {
		return nil, fmt.Errorf("Error: no feeds found in %q.", string(data))
	}

	out.Items = make([]*Item, 0, len(channel.Items))
	out.ItemMap = make(map[string]struct{})

	// Process items.
	for _, item := range channel.Items {
		fmt.Printf("%+v", item)
		if strings.Trim(item.Link, " ") == "" {
			fmt.Println("Empty Item Link")
			//item.Link = item.AtomLink[0].Href
		} else {
			fmt.Printf("ItemLink %s\n", item.Link)
		}
		if item.ID == "" {
			if item.Link == "" {
				if debug {
					fmt.Printf("[w] Item %q has no ID or link and will be ignored.\n", item.Title)
					fmt.Printf("[w] %#v\n", item)
				}
				warnings = true
				continue
			}
			item.ID = item.Link
		}

		// Skip items already known.
		if read.req <- item.ID; <-read.res {
			continue
		}

		next := new(Item)
		doc := scrapeURL(item.Link)
		next.Title = getTitleRss2(item, doc)
		next.Summary = getSummaryRss2(item, doc)
		next.Origin = out.Title

		next.Image = getImageRss2(item, doc)
		next.Content = item.Content
		next.Link = item.Link
		if item.Date != "" {
			next.Date, err = parseTime(item.Date)
			if time.Now().Before(next.Date) {
				next.Date = time.Now()
			}
			if err != nil {
				return nil, err
			}
		} else if item.PubDate != "" {
			next.Date, err = parseTime(item.PubDate)
			if time.Now().Before(next.Date) {
				next.Date = time.Now()
			}
			if err != nil {
				return nil, err
			}
		}
		next.ID = item.ID
		if len(item.Enclosures) > 0 {
			next.Enclosures = make([]*Enclosure, len(item.Enclosures))
			for i := range item.Enclosures {
				next.Enclosures[i] = item.Enclosures[i].Enclosure()
			}
		}
		next.Read = false

		if _, ok := out.ItemMap[next.ID]; ok {
			if debug {
				fmt.Printf("[w] Item %q has duplicate ID.\n", next.Title)
				fmt.Printf("[w] %#v\n", next)
			}
			warnings = true
			continue
		}

		out.Items = append(out.Items, next)
		out.ItemMap[next.ID] = struct{}{}
		out.Unread++
	}

	if warnings && debug {
		fmt.Printf("[i] Encountered warnings:\n%s\n", data)
	}

	return out, nil
}

type rss2_0Feed struct {
	XMLName xml.Name       `xml:"rss"`
	Channel *rss2_0Channel `xml:"channel"`
}

type rss2_0Channel struct {
	XMLName     xml.Name     `xml:"channel"`
	Title       string       `xml:"title"`
	Description string       `xml:"description"`
	Link        []rss2_0Link `xml:"link"`
	Image       rss2_0Image  `xml:"image"`
	Items       []rss2_0Item `xml:"item"`
	MinsToLive  int          `xml:"ttl"`
	SkipHours   []int        `xml:"skipHours>hour"`
	SkipDays    []string     `xml:"skipDays>day"`
}

type rss2_0Link struct {
	Rel      string `xml:"rel,attr"`
	Href     string `xml:"href,attr"`
	Type     string `xml:"type,attr"`
	Chardata string `xml:",chardata"`
}

type rss2_0Item struct {
	XMLName     xml.Name          `xml:"item"`
	Title       string            `xml:"title"`
	Description string            `xml:"description"`
	Content     string            `xml:"encoded"`
	Link        string            `xml:"RssDefault link"`
	PubDate     string            `xml:"pubDate"`
	Date        string            `xml:"date"`
	ID          string            `xml:"guid"`
	Enclosures  []rss2_0Enclosure `xml:"enclosure"`
}

type rss2_0Enclosure struct {
	XMLName xml.Name `xml:"enclosure"`
	Url     string   `xml:"url"`
	Type    string   `xml:"type"`
	Length  int      `xml:"length"`
}

func (r *rss2_0Enclosure) Enclosure() *Enclosure {
	out := new(Enclosure)
	out.Url = r.Url
	out.Type = r.Type
	out.Length = r.Length
	return out
}

type rss2_0Image struct {
	XMLName xml.Name `xml:"image"`
	Title   string   `xml:"title"`
	Url     string   `xml:"url"`
	Height  int      `xml:"height"`
	Width   int      `xml:"width"`
}

func (i *rss2_0Image) Image() *Image {
	out := new(Image)
	out.Title = i.Title
	out.Url = i.Url
	out.Height = uint32(i.Height)
	out.Width = uint32(i.Width)
	return out
}
<commit_msg>easy way out<commit_after>package rss

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"sort"
	"strings"
	"time"
)

func parseRSS2(data []byte, read *db) (*Feed, error) {
	warnings := false
	feed := rss2_0Feed{}
	p := xml.NewDecoder(bytes.NewReader(data))
	p.DefaultSpace = "RssDefault"
	p.CharsetReader = charsetReader
	err := p.Decode(&feed)
	if err != nil {
		return nil, err
	}
	if feed.Channel == nil {
		return nil, fmt.Errorf("Error: no channel found in %q.", string(data))
	}

	channel := feed.Channel

	out := new(Feed)
	out.Title = channel.Title
	out.Description = channel.Description
	for _, link := range channel.Link {
		if link.Rel == "" && link.Type == "" && link.Href == "" && link.Chardata != "" {
			out.Link = link.Chardata
			break
		}
	}
	out.Image = channel.Image.Image()
	if channel.MinsToLive != 0 {
		sort.Ints(channel.SkipHours)
		next := time.Now().Add(time.Duration(channel.MinsToLive) * time.Minute)
		for _, hour := range channel.SkipHours {
			if hour == next.Hour() {
				next.Add(time.Duration(60-next.Minute()) * time.Minute)
			}
		}
		trying := true
		for trying {
			trying = false
			for _, day := range channel.SkipDays {
				if strings.Title(day) == next.Weekday().String() {
					next.Add(time.Duration(24-next.Hour()) * time.Hour)
					trying = true
					break
				}
			}
		}

		out.Refresh = next
	}

	if out.Refresh.IsZero() {
		out.Refresh = time.Now().Add(10 * time.Minute)
	}

	if channel.Items == nil {
		return nil, fmt.Errorf("Error: no feeds found in %q.", string(data))
	}

	out.Items = make([]*Item, 0, len(channel.Items))
	out.ItemMap = make(map[string]struct{})

	// Process items.
	for _, item := range channel.Items {
		if strings.Trim(item.Link, " ") == "" {
			fmt.Println("Empty Item Link")
			item.Link = item.ID
		}
		if item.ID == "" {
			if item.Link == "" {
				if debug {
					fmt.Printf("[w] Item %q has no ID or link and will be ignored.\n", item.Title)
					fmt.Printf("[w] %#v\n", item)
				}
				warnings = true
				continue
			}
			item.ID = item.Link
		}

		// Skip items already known.
		if read.req <- item.ID; <-read.res {
			continue
		}

		next := new(Item)
		doc := scrapeURL(item.Link)
		next.Title = getTitleRss2(item, doc)
		next.Summary = getSummaryRss2(item, doc)
		next.Origin = out.Title

		next.Image = getImageRss2(item, doc)
		next.Content = item.Content
		next.Link = item.Link
		if item.Date != "" {
			next.Date, err = parseTime(item.Date)
			if time.Now().Before(next.Date) {
				next.Date = time.Now()
			}
			if err != nil {
				return nil, err
			}
		} else if item.PubDate != "" {
			next.Date, err = parseTime(item.PubDate)
			if time.Now().Before(next.Date) {
				next.Date = time.Now()
			}
			if err != nil {
				return nil, err
			}
		}
		next.ID = item.ID
		if len(item.Enclosures) > 0 {
			next.Enclosures = make([]*Enclosure, len(item.Enclosures))
			for i := range item.Enclosures {
				next.Enclosures[i] = item.Enclosures[i].Enclosure()
			}
		}
		next.Read = false

		if _, ok := out.ItemMap[next.ID]; ok {
			if debug {
				fmt.Printf("[w] Item %q has duplicate ID.\n", next.Title)
				fmt.Printf("[w] %#v\n", next)
			}
			warnings = true
			continue
		}

		out.Items = append(out.Items, next)
		out.ItemMap[next.ID] = struct{}{}
		out.Unread++
	}

	if warnings && debug {
		fmt.Printf("[i] Encountered warnings:\n%s\n", data)
	}

	return out, nil
}

type rss2_0Feed struct {
	XMLName xml.Name       `xml:"rss"`
	Channel *rss2_0Channel `xml:"channel"`
}

type rss2_0Channel struct {
	XMLName     xml.Name     `xml:"channel"`
	Title       string       `xml:"title"`
	Description string       `xml:"description"`
	Link        []rss2_0Link `xml:"link"`
	Image       rss2_0Image  `xml:"image"`
	Items       []rss2_0Item `xml:"item"`
	MinsToLive  int          `xml:"ttl"`
	SkipHours   []int        `xml:"skipHours>hour"`
	SkipDays    []string     `xml:"skipDays>day"`
}

type rss2_0Link struct {
	Rel      string `xml:"rel,attr"`
	Href     string `xml:"href,attr"`
	Type     string `xml:"type,attr"`
	Chardata string `xml:",chardata"`
}

type rss2_0Item struct {
	XMLName     xml.Name          `xml:"item"`
	Title       string            `xml:"title"`
	Description string            `xml:"description"`
	Content     string            `xml:"encoded"`
	Link        string            `xml:"RssDefault link"`
	PubDate     string            `xml:"pubDate"`
	Date        string            `xml:"date"`
	ID          string            `xml:"guid"`
	Enclosures  []rss2_0Enclosure `xml:"enclosure"`
}

type rss2_0Enclosure struct {
	XMLName xml.Name `xml:"enclosure"`
	Url     string   `xml:"url"`
	Type    string   `xml:"type"`
	Length  int      `xml:"length"`
}

func (r *rss2_0Enclosure) Enclosure() *Enclosure {
	out := new(Enclosure)
	out.Url = r.Url
	out.Type = r.Type
	out.Length = r.Length
	return out
}

type rss2_0Image struct {
	XMLName xml.Name `xml:"image"`
	Title   string   `xml:"title"`
	Url     string   `xml:"url"`
	Height  int      `xml:"height"`
	Width   int      `xml:"width"`
}

func (i *rss2_0Image) Image() *Image {
	out := new(Image)
	out.Title = i.Title
	out.Url = i.Url
	out.Height = uint32(i.Height)
	out.Width = uint32(i.Width)
	return out
}
<|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 command

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSuccess(t *testing.T) {
	res, err := New("echo", "hi").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessPipe(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat").
		Pipe("cat").
		Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Equal(t, "hi", res.Output())
}

func TestFailurePipeWrongCommand(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("wrong").
		Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestFailurePipeWrongArgument(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat", "--wrong").
		Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Empty(t, res.Output())
	require.NotEmpty(t, res.Error())
}

func TestSuccessVerbose(t *testing.T) {
	res, err := New("echo", "hi").Verbose().Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessWithWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/", "ls", "-1").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestFailureWithWrongWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/should/not/exist", "ls", "-1").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessSilent(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSepareted(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSingleArgument(t *testing.T) {
	res, err := New("echo").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessNoArgument(t *testing.T) {
	res, err := New("").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hello world").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.Output())
}

func TestSuccessOutputTrimNL(t *testing.T) {
	res, err := New("echo", "-n", "hello world\n").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.OutputTrimNL())
}

func TestSuccessError(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.Empty(t, res.Output())
	require.Contains(t, res.Error(), "No such file")
}

func TestSuccessOutputSeparated(t *testing.T) {
	res, err := New("echo", "-n", "hello").Run()
	require.Nil(t, err)
	require.Equal(t, "hello", res.Output())
}

func TestFailureStdErr(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Equal(t, res.ExitCode(), 1)
}

func TestFailureNotExisting(t *testing.T) {
	res, err := New("/not/valid").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessExecute(t *testing.T) {
	err := Execute("echo", "-n", "hi", "ho")
	require.Nil(t, err)
}

func TestFailureExecute(t *testing.T) {
	err := Execute("cat", "/not/invalid")
	require.NotNil(t, err)
}

func TestAvailableSuccessValidCommand(t *testing.T) {
	res := Available("echo")
	require.True(t, res)
}

func TestAvailableSuccessEmptyCommands(t *testing.T) {
	res := Available()
	require.True(t, res)
}

func TestAvailableFailure(t *testing.T) {
	res := Available("echo", "this-command-should-not-exist")
	require.False(t, res)
}

func TestSuccessRunSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSuccess())
}

func TestFailureRunSuccess(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSuccess())
}

func TestSuccessRunSilentSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSilentSuccess())
}

func TestFailureRunSuccessSilent(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSilentSuccess())
}

func TestSuccessRunSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hi").RunSuccessOutput()
	require.Nil(t, err)
	require.Equal(t, "hi", res.Output())
}

func TestFailureRunSuccessOutput(t *testing.T) {
	res, err := New("cat", "/not/available").RunSuccessOutput()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessRunSilentSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hi").RunSilentSuccessOutput()
	require.Nil(t, err)
	require.Equal(t, "hi", res.Output())
}

func TestFailureRunSilentSuccessOutput(t *testing.T) {
	res, err := New("cat", "/not/available").RunSilentSuccessOutput()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessLogWriter(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("echo", "Hello World").AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
}

func TestSuccessLogWriterMultiple(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()
	b := &bytes.Buffer{}

	res, err := New("echo", "Hello World").
		AddWriter(f).
		AddWriter(b).
		RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
	require.Equal(t, res.Output(), b.String())
}

func TestSuccessLogWriterSilent(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	err = New("echo", "Hello World").AddWriter(f).RunSilentSuccess()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Empty(t, content)
}

func TestSuccessLogWriterStdErr(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo error").
		AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Error(), string(content))
}

func TestSuccessLogWriterStdErrAndStdOut(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Contains(t, string(content), res.Output())
	require.Contains(t, string(content), res.Error())
}

func TestSuccessLogWriterStdErrAndStdOutOnlyStdErr(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddErrorWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Error(), string(content))
}

func TestSuccessLogWriterStdErrAndStdOutOnlyStdOut(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddOutputWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
}

func TestCommandsSuccess(t *testing.T) {
	res, err := New("echo", "1").Verbose().
		Add("echo", "2").Add("echo", "3").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Contains(t, res.Output(), "1")
	require.Contains(t, res.Output(), "2")
	require.Contains(t, res.Output(), "3")
}

func TestCommandsFailure(t *testing.T) {
	res, err := New("echo", "1").Add("wrong").Add("echo", "3").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestStdOutStdErrSync(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "stderr-stdout-sync-test-")
	require.Nil(t, err)
	defer os.RemoveAll(tempDir)

	file := filepath.Join(tempDir, "main.go")
	require.Nil(t, ioutil.WriteFile(file, []byte(`
		package main

		import (
			"fmt"
			"os"
			"time"
		)

		func main() {
			time.Sleep(1 * time.Second)
			fmt.Fprintln(os.Stderr, "1")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stdout, "2")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stderr, "3")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stdout, "4")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stdout, "5")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stderr, "6")
			time.Sleep(10 * time.Millisecond)
			fmt.Fprintln(os.Stdout, "7")
		}
	`), os.FileMode(0o644)))

	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer os.RemoveAll(f.Name())

	require.Nil(t, New("go", "run", file).AddWriter(f).RunSuccess())
	require.Nil(t, err)

	outFileContent, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, "1\n2\n3\n4\n5\n6\n7\n", string(outFileContent))
}
<commit_msg>Remove flaking command sync unit tests<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 command

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

	"github.com/stretchr/testify/require"
)

func TestSuccess(t *testing.T) {
	res, err := New("echo", "hi").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessPipe(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat").
		Pipe("cat").
		Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Equal(t, "hi", res.Output())
}

func TestFailurePipeWrongCommand(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("wrong").
		Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestFailurePipeWrongArgument(t *testing.T) {
	res, err := New("echo", "-n", "hi").
		Pipe("cat", "--wrong").
		Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Empty(t, res.Output())
	require.NotEmpty(t, res.Error())
}

func TestSuccessVerbose(t *testing.T) {
	res, err := New("echo", "hi").Verbose().Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestSuccessWithWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/", "ls", "-1").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
}

func TestFailureWithWrongWorkingDir(t *testing.T) {
	res, err := NewWithWorkDir("/should/not/exist", "ls", "-1").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessSilent(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSepareted(t *testing.T) {
	res, err := New("echo", "hi").RunSilent()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessSingleArgument(t *testing.T) {
	res, err := New("echo").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
}

func TestSuccessNoArgument(t *testing.T) {
	res, err := New("").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hello world").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.Output())
}

func TestSuccessOutputTrimNL(t *testing.T) {
	res, err := New("echo", "-n", "hello world\n").Run()
	require.Nil(t, err)
	require.Equal(t, "hello world", res.OutputTrimNL())
}

func TestSuccessError(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.Empty(t, res.Output())
	require.Contains(t, res.Error(), "No such file")
}

func TestSuccessOutputSeparated(t *testing.T) {
	res, err := New("echo", "-n", "hello").Run()
	require.Nil(t, err)
	require.Equal(t, "hello", res.Output())
}

func TestFailureStdErr(t *testing.T) {
	res, err := New("cat", "/not/valid").Run()
	require.Nil(t, err)
	require.False(t, res.Success())
	require.Equal(t, res.ExitCode(), 1)
}

func TestFailureNotExisting(t *testing.T) {
	res, err := New("/not/valid").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessExecute(t *testing.T) {
	err := Execute("echo", "-n", "hi", "ho")
	require.Nil(t, err)
}

func TestFailureExecute(t *testing.T) {
	err := Execute("cat", "/not/invalid")
	require.NotNil(t, err)
}

func TestAvailableSuccessValidCommand(t *testing.T) {
	res := Available("echo")
	require.True(t, res)
}

func TestAvailableSuccessEmptyCommands(t *testing.T) {
	res := Available()
	require.True(t, res)
}

func TestAvailableFailure(t *testing.T) {
	res := Available("echo", "this-command-should-not-exist")
	require.False(t, res)
}

func TestSuccessRunSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSuccess())
}

func TestFailureRunSuccess(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSuccess())
}

func TestSuccessRunSilentSuccess(t *testing.T) {
	require.Nil(t, New("echo", "hi").RunSilentSuccess())
}

func TestFailureRunSuccessSilent(t *testing.T) {
	require.NotNil(t, New("cat", "/not/available").RunSilentSuccess())
}

func TestSuccessRunSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hi").RunSuccessOutput()
	require.Nil(t, err)
	require.Equal(t, "hi", res.Output())
}

func TestFailureRunSuccessOutput(t *testing.T) {
	res, err := New("cat", "/not/available").RunSuccessOutput()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessRunSilentSuccessOutput(t *testing.T) {
	res, err := New("echo", "-n", "hi").RunSilentSuccessOutput()
	require.Nil(t, err)
	require.Equal(t, "hi", res.Output())
}

func TestFailureRunSilentSuccessOutput(t *testing.T) {
	res, err := New("cat", "/not/available").RunSilentSuccessOutput()
	require.NotNil(t, err)
	require.Nil(t, res)
}

func TestSuccessLogWriter(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("echo", "Hello World").AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
}

func TestSuccessLogWriterMultiple(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()
	b := &bytes.Buffer{}

	res, err := New("echo", "Hello World").
		AddWriter(f).
		AddWriter(b).
		RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
	require.Equal(t, res.Output(), b.String())
}

func TestSuccessLogWriterSilent(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	err = New("echo", "Hello World").AddWriter(f).RunSilentSuccess()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Empty(t, content)
}

func TestSuccessLogWriterStdErr(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo error").
		AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Error(), string(content))
}

func TestSuccessLogWriterStdErrAndStdOut(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Contains(t, string(content), res.Output())
	require.Contains(t, string(content), res.Error())
}

func TestSuccessLogWriterStdErrAndStdOutOnlyStdErr(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddErrorWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Error(), string(content))
}

func TestSuccessLogWriterStdErrAndStdOutOnlyStdOut(t *testing.T) {
	f, err := ioutil.TempFile("", "log")
	require.Nil(t, err)
	defer func() { require.Nil(t, os.Remove(f.Name())) }()

	res, err := New("bash", "-c", ">&2 echo stderr; echo stdout").
		AddOutputWriter(f).RunSuccessOutput()
	require.Nil(t, err)

	content, err := ioutil.ReadFile(f.Name())
	require.Nil(t, err)
	require.Equal(t, res.Output(), string(content))
}

func TestCommandsSuccess(t *testing.T) {
	res, err := New("echo", "1").Verbose().
		Add("echo", "2").Add("echo", "3").Run()
	require.Nil(t, err)
	require.True(t, res.Success())
	require.Zero(t, res.ExitCode())
	require.Contains(t, res.Output(), "1")
	require.Contains(t, res.Output(), "2")
	require.Contains(t, res.Output(), "3")
}

func TestCommandsFailure(t *testing.T) {
	res, err := New("echo", "1").Add("wrong").Add("echo", "3").Run()
	require.NotNil(t, err)
	require.Nil(t, res)
}
<|endoftext|>


<commit_before>package config

import (
	"io/ioutil"

	log "github.com/sirupsen/logrus"
)

var initContainerTemplate = `
- name: init-pytorch
  image: busybox:1.31.0
  imagePullPolicy: IfNotPresent
  command: ['sh', '-c', 'until nslookup {{.MasterAddr}}; do echo waiting for master; sleep 2; done;']`

func init() {
	bytes, err := ioutil.ReadFile("/etc/config/initContainer.yaml")
	if err != nil {
		log.Warningf("error while read initContainerTemplate, use default. error: %s", err)
	} else {
		initContainerTemplate = string(bytes)
	}
}

func GetInitContainerTemplate() string {
	return initContainerTemplate
}
<commit_msg>Minor change in log (#213)<commit_after>package config

import (
	"io/ioutil"

	log "github.com/sirupsen/logrus"
)

var initContainerTemplate = `
- name: init-pytorch
  image: busybox:1.31.0
  imagePullPolicy: IfNotPresent
  command: ['sh', '-c', 'until nslookup {{.MasterAddr}}; do echo waiting for master; sleep 2; done;']`

func init() {
	bytes, err := ioutil.ReadFile("/etc/config/initContainer.yaml")
	if err != nil {
		log.Info("Using default init container template")
	} else {
		log.Info("Using init container template from /etc/config/initContainer.yaml")
		initContainerTemplate = string(bytes)
	}
}

func GetInitContainerTemplate() string {
	return initContainerTemplate
}
<|endoftext|>


<commit_before>package configuration

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/containerum/chkit/pkg/model"
)

type ExportFormat string

const (
	PRETTY ExportFormat = ""
	JSON   ExportFormat = "json"
	YAML   ExportFormat = "yaml"
)

type ExportConfig struct {
	Filename *string
	Format   ExportFormat
}

func ExportData(renderer model.Renderer, config ExportConfig) error {
	var data string
	var err error
	switch config.Format {
	case JSON:
		data, err = renderer.RenderJSON()
	case YAML:
		data, err = renderer.RenderYAML()
	default:
		data = renderer.RenderTable()
	}
	if err != nil {
		return err
	}
	if config.Filename == nil {
		fmt.Println(data)
		return nil
	}
	return ioutil.WriteFile(*config.Filename, []byte(data), os.ModePerm)
}
<commit_msg>change filename field type to string<commit_after>package configuration

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/containerum/chkit/pkg/model"
)

type ExportFormat string

const (
	PRETTY ExportFormat = ""
	JSON   ExportFormat = "json"
	YAML   ExportFormat = "yaml"
)

type ExportConfig struct {
	Filename string
	Format   ExportFormat
}

func ExportData(renderer model.Renderer, config ExportConfig) error {
	var data string
	var err error
	switch config.Format {
	case JSON:
		data, err = renderer.RenderJSON()
	case YAML:
		data, err = renderer.RenderYAML()
	default:
		data = renderer.RenderTable()
	}
	if err != nil {
		return err
	}
	switch config.Filename {
	case "", "-":
		fmt.Println(data)
		return nil
	default:
		return ioutil.WriteFile(config.Filename, []byte(data), os.ModePerm)
	}
}
<|endoftext|>


<commit_before>// Copyright 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 inject

import (
	"fmt"
	"net"
	"strconv"
	"strings"

	"github.com/hashicorp/go-multierror"

	"istio.io/api/annotation"
	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pkg/config/mesh"
	"istio.io/istio/pkg/config/validation"
	"istio.io/istio/pkg/util/gogoprotomarshal"
	"istio.io/pkg/log"
)

type annotationValidationFunc func(value string) error

// per-sidecar policy and status
var (
	alwaysValidFunc = func(value string) error {
		return nil
	}

	AnnotationValidation = map[string]annotationValidationFunc{
		annotation.SidecarInject.Name:                             alwaysValidFunc,
		annotation.SidecarStatus.Name:                             alwaysValidFunc,
		annotation.SidecarRewriteAppHTTPProbers.Name:              alwaysValidFunc,
		annotation.SidecarControlPlaneAuthPolicy.Name:             alwaysValidFunc,
		annotation.SidecarDiscoveryAddress.Name:                   alwaysValidFunc,
		annotation.SidecarProxyImage.Name:                         alwaysValidFunc,
		annotation.SidecarProxyCPU.Name:                           alwaysValidFunc,
		annotation.SidecarProxyCPULimit.Name:                      alwaysValidFunc,
		annotation.SidecarProxyMemory.Name:                        alwaysValidFunc,
		annotation.SidecarProxyMemoryLimit.Name:                   alwaysValidFunc,
		annotation.SidecarInterceptionMode.Name:                   validateInterceptionMode,
		annotation.SidecarBootstrapOverride.Name:                  alwaysValidFunc,
		annotation.SidecarStatsInclusionPrefixes.Name:             alwaysValidFunc,
		annotation.SidecarStatsInclusionSuffixes.Name:             alwaysValidFunc,
		annotation.SidecarStatsInclusionRegexps.Name:              alwaysValidFunc,
		annotation.SidecarUserVolume.Name:                         alwaysValidFunc,
		annotation.SidecarUserVolumeMount.Name:                    alwaysValidFunc,
		annotation.SidecarEnableCoreDump.Name:                     validateBool,
		annotation.SidecarStatusPort.Name:                         validateStatusPort,
		annotation.SidecarStatusReadinessInitialDelaySeconds.Name: validateUInt32,
		annotation.SidecarStatusReadinessPeriodSeconds.Name:       validateUInt32,
		annotation.SidecarStatusReadinessFailureThreshold.Name:    validateUInt32,
		annotation.SidecarTrafficIncludeOutboundIPRanges.Name:     ValidateIncludeIPRanges,
		annotation.SidecarTrafficExcludeOutboundIPRanges.Name:     ValidateExcludeIPRanges,
		annotation.SidecarTrafficIncludeInboundPorts.Name:         ValidateIncludeInboundPorts,
		annotation.SidecarTrafficExcludeInboundPorts.Name:         ValidateExcludeInboundPorts,
		annotation.SidecarTrafficExcludeOutboundPorts.Name:        ValidateExcludeOutboundPorts,
		annotation.SidecarTrafficKubevirtInterfaces.Name:          alwaysValidFunc,
		annotation.PrometheusMergeMetrics.Name:                    validateBool,
		annotation.ProxyConfig.Name:                               validateProxyConfig,
		"k8s.v1.cni.cncf.io/networks":                             alwaysValidFunc,
	}
)

func validateProxyConfig(value string) error {
	config := mesh.DefaultProxyConfig()
	if err := gogoprotomarshal.ApplyYAML(value, &config); err != nil {
		return fmt.Errorf("failed to convert to apply proxy config: %v", err)
	}
	return validation.ValidateProxyConfig(&config)
}

func validateAnnotations(annotations map[string]string) (err error) {
	for name, value := range annotations {
		if v, ok := AnnotationValidation[name]; ok {
			if e := v(value); e != nil {
				err = multierror.Append(err, fmt.Errorf("invalid value '%s' for annotation '%s': %v", value, name, e))
			}
		} else if strings.Contains(name, "istio") {
			log.Warnf("Potentially misspelled annotation '%s' with value '%s' encountered", name, value)
		}
	}
	return
}

func validatePortList(parameterName, ports string) error {
	if _, err := parsePorts(ports); err != nil {
		return fmt.Errorf("%s invalid: %v", parameterName, err)
	}
	return nil
}

// validateInterceptionMode validates the interceptionMode annotation
func validateInterceptionMode(mode string) error {
	switch mode {
	case meshconfig.ProxyConfig_REDIRECT.String():
	case meshconfig.ProxyConfig_TPROXY.String():
	case string(model.InterceptionNone): // not a global mesh config - must be enabled for each sidecar
	default:
		return fmt.Errorf("interceptionMode invalid, use REDIRECT,TPROXY,NONE: %v", mode)
	}
	return nil
}

// ValidateIncludeIPRanges validates the includeIPRanges parameter
func ValidateIncludeIPRanges(ipRanges string) error {
	if ipRanges != "*" {
		if e := validateCIDRList(ipRanges); e != nil {
			return fmt.Errorf("includeIPRanges invalid: %v", e)
		}
	}
	return nil
}

// ValidateExcludeIPRanges validates the excludeIPRanges parameter
func ValidateExcludeIPRanges(ipRanges string) error {
	if e := validateCIDRList(ipRanges); e != nil {
		return fmt.Errorf("excludeIPRanges invalid: %v", e)
	}
	return nil
}

// ValidateIncludeInboundPorts validates the includeInboundPorts parameter
func ValidateIncludeInboundPorts(ports string) error {
	if ports != "*" {
		return validatePortList("includeInboundPorts", ports)
	}
	return nil
}

// ValidateExcludeInboundPorts validates the excludeInboundPorts parameter
func ValidateExcludeInboundPorts(ports string) error {
	return validatePortList("excludeInboundPorts", ports)
}

// ValidateExcludeOutboundPorts validates the excludeOutboundPorts parameter
func ValidateExcludeOutboundPorts(ports string) error {
	return validatePortList("excludeOutboundPorts", ports)
}

// validateStatusPort validates the statusPort parameter
func validateStatusPort(port string) error {
	if _, e := parsePort(port); e != nil {
		return fmt.Errorf("excludeInboundPorts invalid: %v", e)
	}
	return nil
}

// validateUInt32 validates that the given annotation value is a positive integer.
func validateUInt32(value string) error {
	_, err := strconv.ParseUint(value, 10, 32)
	return err
}

// validateBool validates that the given annotation value is a boolean.
func validateBool(value string) error {
	_, err := strconv.ParseBool(value)
	return err
}

func validateCIDRList(cidrs string) error {
	if len(cidrs) > 0 {
		for _, cidr := range strings.Split(cidrs, ",") {
			if _, _, err := net.ParseCIDR(cidr); err != nil {
				return fmt.Errorf("failed parsing cidr '%s': %v", cidr, err)
			}
		}
	}
	return nil
}

func splitPorts(portsString string) []string {
	return strings.Split(portsString, ",")
}

func parsePort(portStr string) (int, error) {
	port, err := strconv.ParseUint(strings.TrimSpace(portStr), 10, 16)
	if err != nil {
		return 0, fmt.Errorf("failed parsing port '%d': %v", port, err)
	}
	return int(port), nil
}

func parsePorts(portsString string) ([]int, error) {
	portsString = strings.TrimSpace(portsString)
	ports := make([]int, 0)
	if len(portsString) > 0 {
		for _, portStr := range splitPorts(portsString) {
			port, err := parsePort(portStr)
			if err != nil {
				return nil, fmt.Errorf("failed parsing port '%d': %v", port, err)
			}
			ports = append(ports, port)
		}
	}
	return ports, nil
}
<commit_msg>Hide "unknown annotation" logs (#29926)<commit_after>// Copyright 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 inject

import (
	"fmt"
	"net"
	"strconv"
	"strings"

	"github.com/hashicorp/go-multierror"

	"istio.io/api/annotation"
	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pkg/config/mesh"
	"istio.io/istio/pkg/config/validation"
	"istio.io/istio/pkg/util/gogoprotomarshal"
)

type annotationValidationFunc func(value string) error

// per-sidecar policy and status
var (
	AnnotationValidation = map[string]annotationValidationFunc{
		annotation.SidecarInterceptionMode.Name:                   validateInterceptionMode,
		annotation.SidecarEnableCoreDump.Name:                     validateBool,
		annotation.SidecarStatusPort.Name:                         validateStatusPort,
		annotation.SidecarStatusReadinessInitialDelaySeconds.Name: validateUInt32,
		annotation.SidecarStatusReadinessPeriodSeconds.Name:       validateUInt32,
		annotation.SidecarStatusReadinessFailureThreshold.Name:    validateUInt32,
		annotation.SidecarTrafficIncludeOutboundIPRanges.Name:     ValidateIncludeIPRanges,
		annotation.SidecarTrafficExcludeOutboundIPRanges.Name:     ValidateExcludeIPRanges,
		annotation.SidecarTrafficIncludeInboundPorts.Name:         ValidateIncludeInboundPorts,
		annotation.SidecarTrafficExcludeInboundPorts.Name:         ValidateExcludeInboundPorts,
		annotation.SidecarTrafficExcludeOutboundPorts.Name:        ValidateExcludeOutboundPorts,
		annotation.PrometheusMergeMetrics.Name:                    validateBool,
		annotation.ProxyConfig.Name:                               validateProxyConfig,
	}
)

func validateProxyConfig(value string) error {
	config := mesh.DefaultProxyConfig()
	if err := gogoprotomarshal.ApplyYAML(value, &config); err != nil {
		return fmt.Errorf("failed to convert to apply proxy config: %v", err)
	}
	return validation.ValidateProxyConfig(&config)
}

func validateAnnotations(annotations map[string]string) (err error) {
	for name, value := range annotations {
		if v, ok := AnnotationValidation[name]; ok {
			if e := v(value); e != nil {
				err = multierror.Append(err, fmt.Errorf("invalid value '%s' for annotation '%s': %v", value, name, e))
			}
		}
	}
	return
}

func validatePortList(parameterName, ports string) error {
	if _, err := parsePorts(ports); err != nil {
		return fmt.Errorf("%s invalid: %v", parameterName, err)
	}
	return nil
}

// validateInterceptionMode validates the interceptionMode annotation
func validateInterceptionMode(mode string) error {
	switch mode {
	case meshconfig.ProxyConfig_REDIRECT.String():
	case meshconfig.ProxyConfig_TPROXY.String():
	case string(model.InterceptionNone): // not a global mesh config - must be enabled for each sidecar
	default:
		return fmt.Errorf("interceptionMode invalid, use REDIRECT,TPROXY,NONE: %v", mode)
	}
	return nil
}

// ValidateIncludeIPRanges validates the includeIPRanges parameter
func ValidateIncludeIPRanges(ipRanges string) error {
	if ipRanges != "*" {
		if e := validateCIDRList(ipRanges); e != nil {
			return fmt.Errorf("includeIPRanges invalid: %v", e)
		}
	}
	return nil
}

// ValidateExcludeIPRanges validates the excludeIPRanges parameter
func ValidateExcludeIPRanges(ipRanges string) error {
	if e := validateCIDRList(ipRanges); e != nil {
		return fmt.Errorf("excludeIPRanges invalid: %v", e)
	}
	return nil
}

// ValidateIncludeInboundPorts validates the includeInboundPorts parameter
func ValidateIncludeInboundPorts(ports string) error {
	if ports != "*" {
		return validatePortList("includeInboundPorts", ports)
	}
	return nil
}

// ValidateExcludeInboundPorts validates the excludeInboundPorts parameter
func ValidateExcludeInboundPorts(ports string) error {
	return validatePortList("excludeInboundPorts", ports)
}

// ValidateExcludeOutboundPorts validates the excludeOutboundPorts parameter
func ValidateExcludeOutboundPorts(ports string) error {
	return validatePortList("excludeOutboundPorts", ports)
}

// validateStatusPort validates the statusPort parameter
func validateStatusPort(port string) error {
	if _, e := parsePort(port); e != nil {
		return fmt.Errorf("excludeInboundPorts invalid: %v", e)
	}
	return nil
}

// validateUInt32 validates that the given annotation value is a positive integer.
func validateUInt32(value string) error {
	_, err := strconv.ParseUint(value, 10, 32)
	return err
}

// validateBool validates that the given annotation value is a boolean.
func validateBool(value string) error {
	_, err := strconv.ParseBool(value)
	return err
}

func validateCIDRList(cidrs string) error {
	if len(cidrs) > 0 {
		for _, cidr := range strings.Split(cidrs, ",") {
			if _, _, err := net.ParseCIDR(cidr); err != nil {
				return fmt.Errorf("failed parsing cidr '%s': %v", cidr, err)
			}
		}
	}
	return nil
}

func splitPorts(portsString string) []string {
	return strings.Split(portsString, ",")
}

func parsePort(portStr string) (int, error) {
	port, err := strconv.ParseUint(strings.TrimSpace(portStr), 10, 16)
	if err != nil {
		return 0, fmt.Errorf("failed parsing port '%d': %v", port, err)
	}
	return int(port), nil
}

func parsePorts(portsString string) ([]int, error) {
	portsString = strings.TrimSpace(portsString)
	ports := make([]int, 0)
	if len(portsString) > 0 {
		for _, portStr := range splitPorts(portsString) {
			port, err := parsePort(portStr)
			if err != nil {
				return nil, fmt.Errorf("failed parsing port '%d': %v", port, err)
			}
			ports = append(ports, port)
		}
	}
	return ports, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 config

import (
	"github.com/spf13/pflag"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ContainerRuntimeOptions struct {

	// General options.

	// ContainerRuntime is the container runtime to use.
	ContainerRuntime string
	// RuntimeCgroups that container runtime is expected to be isolated in.
	RuntimeCgroups string

	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// Enable dockershim only mode.
	ExperimentalDockershim bool
	// This flag, if set, disables use of a shared PID namespace for pods running in the docker CRI runtime.
	// A shared PID namespace is the only option in non-docker runtimes and is required by the CRI. The ability to
	// disable it for docker will be removed unless a compelling use case is discovered with widespread use.
	// TODO: Remove once we no longer support disabling shared PID namespace (https://issues.k8s.io/41938)
	DockerDisableSharedPID bool
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string
}

func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	// General settings.
	fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote', 'rkt (deprecated)'.")
	fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.")

	// Docker-specific settings.
	fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]")
	fs.MarkHidden("experimental-dockershim")
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, "Setting this to false causes Kubernetes to create pods using a shared process namespace for containers in a pod when running with Docker 1.13.1 or higher. A future Kubernetes release will make this configurable instead in the API.")
	fs.MarkDeprecated("docker-disable-shared-pid", "will be removed in a future release. This option will be replaced by PID namespace sharing that is configurable per-pod using the API. See https://features.k8s.io/495")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, "The image whose network/ipc namespaces containers in each pod will use.")
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, "Use this for the docker endpoint to communicate with")
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, "If no pulling progress is made before this deadline, the image pulling will be cancelled.")

	// Network plugin settings for Docker.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, "<Warning: Alpha feature> The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d")
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, "<Warning: Alpha feature> A comma-separated list of full paths of directories in which to search for CNI plugin binaries. Default: /opt/cni/bin")
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, "<Warning: Alpha feature> The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU.")
}
<commit_msg>add warnings for docker-only flags<commit_after>/*
Copyright 2017 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 config

import (
	"fmt"

	"github.com/spf13/pflag"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ContainerRuntimeOptions struct {

	// General options.

	// ContainerRuntime is the container runtime to use.
	ContainerRuntime string
	// RuntimeCgroups that container runtime is expected to be isolated in.
	RuntimeCgroups string

	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// Enable dockershim only mode.
	ExperimentalDockershim bool
	// This flag, if set, disables use of a shared PID namespace for pods running in the docker CRI runtime.
	// A shared PID namespace is the only option in non-docker runtimes and is required by the CRI. The ability to
	// disable it for docker will be removed unless a compelling use case is discovered with widespread use.
	// TODO: Remove once we no longer support disabling shared PID namespace (https://issues.k8s.io/41938)
	DockerDisableSharedPID bool
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string
}

func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	dockerOnlyWarning := "This docker-specific flag only works when container-runtime is set to docker."

	// General settings.
	fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote', 'rkt (deprecated)'.")
	fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.")

	// Docker-specific settings.
	fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]")
	fs.MarkHidden("experimental-dockershim")
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, fmt.Sprintf("Setting this to false causes Kubernetes to create pods using a shared process namespace for containers in a pod when running with Docker 1.13.1 or higher. A future Kubernetes release will make this configurable instead in the API. %s", dockerOnlyWarning))
	fs.MarkDeprecated("docker-disable-shared-pid", "will be removed in a future release. This option will be replaced by PID namespace sharing that is configurable per-pod using the API. See https://features.k8s.io/495")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, fmt.Sprintf("The image whose network/ipc namespaces containers in each pod will use. %s", dockerOnlyWarning))
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, fmt.Sprintf("Use this for the docker endpoint to communicate with %s", dockerOnlyWarning))
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, fmt.Sprintf("If no pulling progress is made before this deadline, the image pulling will be cancelled. %s", dockerOnlyWarning))

	// Network plugin settings for Docker.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, fmt.Sprintf("<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle. %s", dockerOnlyWarning))
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, fmt.Sprintf("<Warning: Alpha feature> The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d. %s", dockerOnlyWarning))
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, fmt.Sprintf("<Warning: Alpha feature> A comma-separated list of full paths of directories in which to search for CNI plugin binaries. Default: /opt/cni/bin. %s", dockerOnlyWarning))
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, fmt.Sprintf("<Warning: Alpha feature> The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU. %s", dockerOnlyWarning))
}
<|endoftext|>


<commit_before>package service

import (
	"context"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/containous/traefik/v2/pkg/config/dynamic"
	"github.com/containous/traefik/v2/pkg/log"
	"github.com/containous/traefik/v2/pkg/types"
)

// StatusClientClosedRequest non-standard HTTP status code for client disconnection
const StatusClientClosedRequest = 499

// StatusClientClosedRequestText non-standard HTTP status for client disconnection
const StatusClientClosedRequestText = "Client Closed Request"

func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwarding, defaultRoundTripper http.RoundTripper, bufferPool httputil.BufferPool, responseModifier func(*http.Response) error) (http.Handler, error) {
	var flushInterval types.Duration
	if responseForwarding != nil {
		err := flushInterval.Set(responseForwarding.FlushInterval)
		if err != nil {
			return nil, fmt.Errorf("error creating flush interval: %v", err)
		}
	}
	if flushInterval == 0 {
		flushInterval = types.Duration(100 * time.Millisecond)
	}

	proxy := &httputil.ReverseProxy{
		Director: func(outReq *http.Request) {
			u := outReq.URL
			if outReq.RequestURI != "" {
				parsedURL, err := url.ParseRequestURI(outReq.RequestURI)
				if err == nil {
					u = parsedURL
				}
			}

			outReq.URL.Path = u.Path
			outReq.URL.RawPath = u.RawPath
			outReq.URL.RawQuery = u.RawQuery
			outReq.RequestURI = "" // Outgoing request should not have RequestURI

			outReq.Proto = "HTTP/1.1"
			outReq.ProtoMajor = 1
			outReq.ProtoMinor = 1

			if _, ok := outReq.Header["User-Agent"]; !ok {
				outReq.Header.Set("User-Agent", "")
			}

			// Do not pass client Host header unless optsetter PassHostHeader is set.
			if passHostHeader != nil && !*passHostHeader {
				outReq.Host = outReq.URL.Host
			}

			// Even if the websocket RFC says that headers should be case-insensitive,
			// some servers need Sec-WebSocket-Key and Sec-WebSocket-Protocol to be case-sensitive.
			// https://tools.ietf.org/html/rfc6455#page-20
			outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
			outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
			delete(outReq.Header, "Sec-Websocket-Key")
			delete(outReq.Header, "Sec-Websocket-Protocol")
		},
		Transport:      defaultRoundTripper,
		FlushInterval:  time.Duration(flushInterval),
		ModifyResponse: responseModifier,
		BufferPool:     bufferPool,
		ErrorHandler: func(w http.ResponseWriter, request *http.Request, err error) {
			statusCode := http.StatusInternalServerError

			switch {
			case err == io.EOF:
				statusCode = http.StatusBadGateway
			case err == context.Canceled:
				statusCode = StatusClientClosedRequest
			default:
				if e, ok := err.(net.Error); ok {
					if e.Timeout() {
						statusCode = http.StatusGatewayTimeout
					} else {
						statusCode = http.StatusBadGateway
					}
				}
			}

			log.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err)
			w.WriteHeader(statusCode)
			_, werr := w.Write([]byte(statusText(statusCode)))
			if werr != nil {
				log.Debugf("Error while writing status code", werr)
			}
		},
	}

	return proxy, nil
}

func statusText(statusCode int) string {
	if statusCode == StatusClientClosedRequest {
		return StatusClientClosedRequestText
	}
	return http.StatusText(statusCode)
}
<commit_msg>Fix case-sensitive header Sec-Websocket-Version<commit_after>package service

import (
	"context"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/containous/traefik/v2/pkg/config/dynamic"
	"github.com/containous/traefik/v2/pkg/log"
	"github.com/containous/traefik/v2/pkg/types"
)

// StatusClientClosedRequest non-standard HTTP status code for client disconnection
const StatusClientClosedRequest = 499

// StatusClientClosedRequestText non-standard HTTP status for client disconnection
const StatusClientClosedRequestText = "Client Closed Request"

func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwarding, defaultRoundTripper http.RoundTripper, bufferPool httputil.BufferPool, responseModifier func(*http.Response) error) (http.Handler, error) {
	var flushInterval types.Duration
	if responseForwarding != nil {
		err := flushInterval.Set(responseForwarding.FlushInterval)
		if err != nil {
			return nil, fmt.Errorf("error creating flush interval: %v", err)
		}
	}
	if flushInterval == 0 {
		flushInterval = types.Duration(100 * time.Millisecond)
	}

	proxy := &httputil.ReverseProxy{
		Director: func(outReq *http.Request) {
			u := outReq.URL
			if outReq.RequestURI != "" {
				parsedURL, err := url.ParseRequestURI(outReq.RequestURI)
				if err == nil {
					u = parsedURL
				}
			}

			outReq.URL.Path = u.Path
			outReq.URL.RawPath = u.RawPath
			outReq.URL.RawQuery = u.RawQuery
			outReq.RequestURI = "" // Outgoing request should not have RequestURI

			outReq.Proto = "HTTP/1.1"
			outReq.ProtoMajor = 1
			outReq.ProtoMinor = 1

			if _, ok := outReq.Header["User-Agent"]; !ok {
				outReq.Header.Set("User-Agent", "")
			}

			// Do not pass client Host header unless optsetter PassHostHeader is set.
			if passHostHeader != nil && !*passHostHeader {
				outReq.Host = outReq.URL.Host
			}

			// Even if the websocket RFC says that headers should be case-insensitive,
			// some servers need Sec-WebSocket-Key, Sec-WebSocket-Protocol and Sec-WebSocket-Version
			// to be case-sensitive.
			// https://tools.ietf.org/html/rfc6455#page-20
			outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
			outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
			outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
			delete(outReq.Header, "Sec-Websocket-Key")
			delete(outReq.Header, "Sec-Websocket-Protocol")
			delete(outReq.Header, "Sec-Websocket-Version")
		},
		Transport:      defaultRoundTripper,
		FlushInterval:  time.Duration(flushInterval),
		ModifyResponse: responseModifier,
		BufferPool:     bufferPool,
		ErrorHandler: func(w http.ResponseWriter, request *http.Request, err error) {
			statusCode := http.StatusInternalServerError

			switch {
			case err == io.EOF:
				statusCode = http.StatusBadGateway
			case err == context.Canceled:
				statusCode = StatusClientClosedRequest
			default:
				if e, ok := err.(net.Error); ok {
					if e.Timeout() {
						statusCode = http.StatusGatewayTimeout
					} else {
						statusCode = http.StatusBadGateway
					}
				}
			}

			log.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err)
			w.WriteHeader(statusCode)
			_, werr := w.Write([]byte(statusText(statusCode)))
			if werr != nil {
				log.Debugf("Error while writing status code", werr)
			}
		},
	}

	return proxy, nil
}

func statusText(statusCode int) string {
	if statusCode == StatusClientClosedRequest {
		return StatusClientClosedRequestText
	}
	return http.StatusText(statusCode)
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The TestGrid 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 summarizer

import (
	"context"
	"regexp"

	"github.com/GoogleCloudPlatform/testgrid/internal/result"
	"github.com/GoogleCloudPlatform/testgrid/pb/state"
	summarypb "github.com/GoogleCloudPlatform/testgrid/pb/summary"
	"github.com/GoogleCloudPlatform/testgrid/pkg/summarizer/common"
)

const (
	minRuns = 0
	// DefaultInterval is the default number of days of analysis
	DefaultInterval = 7
)

var (
	infraRegex      = regexp.MustCompile(`^\w+$`)
	testMethodRegex = regexp.MustCompile(`@TESTGRID@`)
)

type flakinessAnalyzer interface {
	GetFlakiness(gridMetrics []*common.GridMetrics, minRuns int, startDate int, endDate int, tab string) *summarypb.HealthinessInfo
}

// CalculateHealthiness extracts the test run data from each row (which represents a test)
// of the Grid and then analyzes it with an implementation of flakinessAnalyzer, which has
// implementations in the subdir naive and can be injected as needed.
func CalculateHealthiness(grid *state.Grid, analyzer flakinessAnalyzer, startTime int, endTime int, tab string) *summarypb.HealthinessInfo {
	gridMetrics := parseGrid(grid, startTime, endTime)
	return analyzer.GetFlakiness(gridMetrics, minRuns, startTime, endTime, tab)
}

// CalculateTrend populates the ChangeFromLastInterval fields of each TestInfo by comparing
// the current flakiness to the flakiness calculated for the last interval. Interval length
// is a config value that is 7 days by default. The Trend enum defaults to UNKNOWN, so there
// is no need to explicitly assign UNKNOWN when a test appears in currentHealthiness but not
// in previousHealthiness.
func CalculateTrend(currentHealthiness, previousHealthiness *summarypb.HealthinessInfo) {
	previousFlakiness := map[string]float32{}
	// Create a map for faster lookup and avoiding repeated iteration through Tests
	for _, test := range previousHealthiness.Tests {
		previousFlakiness[test.DisplayName] = test.Flakiness
	}

	for i, test := range currentHealthiness.Tests {
		if value, ok := previousFlakiness[test.DisplayName]; ok {
			currentHealthiness.Tests[i].ChangeFromLastInterval = getTrend(test.Flakiness, value)
		}
	}
}

func getTrend(currentFlakiness, previousFlakiness float32) summarypb.TestInfo_Trend {
	if currentFlakiness < previousFlakiness {
		return summarypb.TestInfo_DOWN
	}
	if currentFlakiness > previousFlakiness {
		return summarypb.TestInfo_UP
	}
	return summarypb.TestInfo_NO_CHANGE
}

func parseGrid(grid *state.Grid, startTime int, endTime int) []*common.GridMetrics {
	// Get the relevant data for flakiness from each Grid (which represents
	// a dashboard tab) as a list of GridMetrics structs

	// TODO (itsazhuhere@): consider refactoring/using summary.go's gridMetrics function
	// as it does very similar data collection.

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Multiply by 1000 because currently Column.Started is in milliseconds; this is used
	// for comparisons later. startTime and endTime will be used in a Timestamp later that
	// requires seconds, so we would like to impact that at little as possible.
	startTime *= 1000
	endTime *= 1000

	// We create maps because result.Map returns a map where we can access each result
	// through the test name, and at each instance we can increment our types.Result
	// using the same key. At the end we can filter out those types.Result that had
	// 0 of all counts.
	gridMetricsMap := make(map[string]*common.GridMetrics, 0)
	gridRows := make(map[string]*state.Row)
	// Keeps track of which index of state.Row.Messages to access, because
	// it can be different for each state.Row if there are any state.Row_NO_RESULT
	rowToMessageIndex := make(map[string]int)

	for i, row := range grid.Rows {
		gridRows[row.Name] = grid.Rows[i]
		rowToMessageIndex[row.Name] = 0
		gridMetricsMap[row.Name] = common.NewGridMetrics(row.Name)
	}

	// result.Map is written in a way that assumes each test/row name is unique
	rowResults := result.Map(ctx, grid.Rows)

	for key, ch := range rowResults {
		if !isValidTestName(key) {
			continue
		}
		i := -1
		for nextRowResult := range ch {
			i++
			if i >= len(grid.Columns) {
				break
			}
			if !isWithinTimeFrame(grid.Columns[i], startTime, endTime) {
				continue
			}
			switch result.Coalesce(nextRowResult, result.IgnoreRunning) {
			case state.Row_NO_RESULT:
				continue
			case state.Row_FAIL:
				index := rowToMessageIndex[key]
				categorizeFailure(gridMetricsMap[key], gridRows[key].Messages[index])
			case state.Row_PASS:
				gridMetricsMap[key].Passed++
			case state.Row_FLAKY:
				getValueOfFlakyMetric(gridMetricsMap[key])
			}
			rowToMessageIndex[key]++
		}
	}
	gridMetrics := make([]*common.GridMetrics, 0)
	for _, metric := range gridMetricsMap {
		if metric.Failed > 0 || metric.Passed > 0 || metric.FlakyCount > 0 {
			gridMetrics = append(gridMetrics, metric)
		}
	}
	return gridMetrics
}

func categorizeFailure(resultCounts *common.GridMetrics, message string) {
	if message == "" || !infraRegex.MatchString(message) {
		resultCounts.Failed++
		return
	}
	resultCounts.FailedInfraCount++
	resultCounts.InfraFailures[message] = resultCounts.InfraFailures[message] + 1
}

func getValueOfFlakyMetric(gridMetrics *common.GridMetrics) {
	// TODO (itszhuhere@): add a way to get exact flakiness from a Row_FLAKY cell
	// For now we will leave it as 50%, because:
	// a) gridMetrics.flakiness and .flakyCount are currently not used by anything
	// and
	// b) there's no easy way to get the exact flakiness measurement from prow or whatever else
	// and potentially
	// c) GKE does not currently enable retry on flakes so it isn't as important right now
	// Keep in mind that flakiness is measured as out of 100, i.e. 23 not .23
	flakiness := 50.0
	gridMetrics.FlakyCount++
	// Formula for adding one new value to mean is mean + (newValue - mean) / newCount
	gridMetrics.AverageFlakiness += (flakiness - gridMetrics.AverageFlakiness) / float64(gridMetrics.FlakyCount)
}

func isWithinTimeFrame(column *state.Column, startTime, endTime int) bool {
	return column.Started >= float64(startTime) && column.Started <= float64(endTime)
}

func isValidTestName(name string) bool {
	// isValidTestName filters out test names, currently only tests with
	// @TESTGRID@ which would otherwise make some summaries unnecessarily large
	return !testMethodRegex.MatchString(name)
}
<commit_msg>Fix edge case in parseGrid<commit_after>/*
Copyright 2020 The TestGrid 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 summarizer

import (
	"context"
	"regexp"

	"github.com/GoogleCloudPlatform/testgrid/internal/result"
	"github.com/GoogleCloudPlatform/testgrid/pb/state"
	summarypb "github.com/GoogleCloudPlatform/testgrid/pb/summary"
	"github.com/GoogleCloudPlatform/testgrid/pkg/summarizer/common"
)

const (
	minRuns = 0
	// DefaultInterval is the default number of days of analysis
	DefaultInterval = 7
)

var (
	infraRegex      = regexp.MustCompile(`^\w+$`)
	testMethodRegex = regexp.MustCompile(`@TESTGRID@`)
)

type flakinessAnalyzer interface {
	GetFlakiness(gridMetrics []*common.GridMetrics, minRuns int, startDate int, endDate int, tab string) *summarypb.HealthinessInfo
}

// CalculateHealthiness extracts the test run data from each row (which represents a test)
// of the Grid and then analyzes it with an implementation of flakinessAnalyzer, which has
// implementations in the subdir naive and can be injected as needed.
func CalculateHealthiness(grid *state.Grid, analyzer flakinessAnalyzer, startTime int, endTime int, tab string) *summarypb.HealthinessInfo {
	gridMetrics := parseGrid(grid, startTime, endTime)
	return analyzer.GetFlakiness(gridMetrics, minRuns, startTime, endTime, tab)
}

// CalculateTrend populates the ChangeFromLastInterval fields of each TestInfo by comparing
// the current flakiness to the flakiness calculated for the last interval. Interval length
// is a config value that is 7 days by default. The Trend enum defaults to UNKNOWN, so there
// is no need to explicitly assign UNKNOWN when a test appears in currentHealthiness but not
// in previousHealthiness.
func CalculateTrend(currentHealthiness, previousHealthiness *summarypb.HealthinessInfo) {
	previousFlakiness := map[string]float32{}
	// Create a map for faster lookup and avoiding repeated iteration through Tests
	for _, test := range previousHealthiness.Tests {
		previousFlakiness[test.DisplayName] = test.Flakiness
	}

	for i, test := range currentHealthiness.Tests {
		if value, ok := previousFlakiness[test.DisplayName]; ok {
			currentHealthiness.Tests[i].ChangeFromLastInterval = getTrend(test.Flakiness, value)
		}
	}
}

func getTrend(currentFlakiness, previousFlakiness float32) summarypb.TestInfo_Trend {
	if currentFlakiness < previousFlakiness {
		return summarypb.TestInfo_DOWN
	}
	if currentFlakiness > previousFlakiness {
		return summarypb.TestInfo_UP
	}
	return summarypb.TestInfo_NO_CHANGE
}

func parseGrid(grid *state.Grid, startTime int, endTime int) []*common.GridMetrics {
	// Get the relevant data for flakiness from each Grid (which represents
	// a dashboard tab) as a list of GridMetrics structs

	// TODO (itsazhuhere@): consider refactoring/using summary.go's gridMetrics function
	// as it does very similar data collection.

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Multiply by 1000 because currently Column.Started is in milliseconds; this is used
	// for comparisons later. startTime and endTime will be used in a Timestamp later that
	// requires seconds, so we would like to impact that at little as possible.
	startTime *= 1000
	endTime *= 1000

	// We create maps because result.Map returns a map where we can access each result
	// through the test name, and at each instance we can increment our types.Result
	// using the same key. At the end we can filter out those types.Result that had
	// 0 of all counts.
	gridMetricsMap := make(map[string]*common.GridMetrics, 0)
	gridRows := make(map[string]*state.Row)

	for i, row := range grid.Rows {
		gridRows[row.Name] = grid.Rows[i]
		gridMetricsMap[row.Name] = common.NewGridMetrics(row.Name)
	}

	// result.Map is written in a way that assumes each test/row name is unique
	rowResults := result.Map(ctx, grid.Rows)

	for key, ch := range rowResults {
		if !isValidTestName(key) {
			continue
		}
		rowToMessageIndex := 0
		i := -1
		for nextRowResult := range ch {
			i++
			if i >= len(grid.Columns) {
				break
			}
			var rowResult state.Row_Result
			// 10 == CATEGORIZED_FAILURE
			if nextRowResult == 10 {
				rowResult = state.Row_FAIL
			} else {
				rowResult = result.Coalesce(nextRowResult, result.IgnoreRunning)
			}

			// We still need to increment rowToMessageIndex even if we want to skip counting
			// this column.
			if !isWithinTimeFrame(grid.Columns[i], startTime, endTime) {
				switch rowResult {
				case state.Row_NO_RESULT:
					break
				default:
					rowToMessageIndex++
				}
				continue
			}
			switch rowResult {
			case state.Row_NO_RESULT:
				continue
			case state.Row_FAIL:
				categorizeFailure(gridMetricsMap[key], gridRows[key].Messages[rowToMessageIndex])
			case state.Row_PASS:
				gridMetricsMap[key].Passed++
			case state.Row_FLAKY:
				getValueOfFlakyMetric(gridMetricsMap[key])
			}
			//fmt.Printf("Infra message for RowResult %v: %s\n", nextRowResult, gridRows[key].Messages[rowToMessageIndex])
			rowToMessageIndex++
		}
	}
	gridMetrics := make([]*common.GridMetrics, 0)
	for _, metric := range gridMetricsMap {
		if metric.Failed > 0 || metric.Passed > 0 || metric.FlakyCount > 0 {
			gridMetrics = append(gridMetrics, metric)
		}
	}
	return gridMetrics
}

func categorizeFailure(resultCounts *common.GridMetrics, message string) {
	if message == "" || !infraRegex.MatchString(message) {
		resultCounts.Failed++
		return
	}
	resultCounts.FailedInfraCount++
	resultCounts.InfraFailures[message] = resultCounts.InfraFailures[message] + 1
}

func getValueOfFlakyMetric(gridMetrics *common.GridMetrics) {
	// TODO (itszhuhere@): add a way to get exact flakiness from a Row_FLAKY cell
	// For now we will leave it as 50%, because:
	// a) gridMetrics.flakiness and .flakyCount are currently not used by anything
	// and
	// b) there's no easy way to get the exact flakiness measurement from prow or whatever else
	// and potentially
	// c) GKE does not currently enable retry on flakes so it isn't as important right now
	// Keep in mind that flakiness is measured as out of 100, i.e. 23 not .23
	flakiness := 50.0
	gridMetrics.FlakyCount++
	// Formula for adding one new value to mean is mean + (newValue - mean) / newCount
	gridMetrics.AverageFlakiness += (flakiness - gridMetrics.AverageFlakiness) / float64(gridMetrics.FlakyCount)
}

func isWithinTimeFrame(column *state.Column, startTime, endTime int) bool {
	return column.Started >= float64(startTime) && column.Started <= float64(endTime)
}

func isValidTestName(name string) bool {
	// isValidTestName filters out test names, currently only tests with
	// @TESTGRID@ which would otherwise make some summaries unnecessarily large
	return !testMethodRegex.MatchString(name)
}
<|endoftext|>


<commit_before>// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.

package windowsconsole

import (
	"io/ioutil"
	"os"
	"sync"

	ansiterm "github.com/Azure/go-ansiterm"
	"github.com/Sirupsen/logrus"
)

var logger *logrus.Logger
var initOnce sync.Once

func initLogger() {
	initOnce.Do(func() {
		logFile := ioutil.Discard

		if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
			logFile, _ = os.Create("ansiReaderWriter.log")
		}

		logger = &logrus.Logger{
			Out:       logFile,
			Formatter: new(logrus.TextFormatter),
			Level:     logrus.DebugLevel,
		}
	})
}
<commit_msg>Update logrus to v1.0.1<commit_after>// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.

package windowsconsole

import (
	"io/ioutil"
	"os"
	"sync"

	ansiterm "github.com/Azure/go-ansiterm"
	"github.com/sirupsen/logrus"
)

var logger *logrus.Logger
var initOnce sync.Once

func initLogger() {
	initOnce.Do(func() {
		logFile := ioutil.Discard

		if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
			logFile, _ = os.Create("ansiReaderWriter.log")
		}

		logger = &logrus.Logger{
			Out:       logFile,
			Formatter: new(logrus.TextFormatter),
			Level:     logrus.DebugLevel,
		}
	})
}
<|endoftext|>