<commit_before>package gogl

import (
	"fmt"
	"reflect"
)

/* Vertex structures */

// As a rule, gogl tries to place as low a requirement on its vertices as
// possible. This is because, from a purely graph theoretic perspective,
// vertices are inert. Boring, even. Graphs are more about the topology, the
// characteristics of the edges connecting the points than the points
// themselves. Your use case cares about the content of your vertices, but gogl
// does not.  Consequently, anything can act as a vertex.
type Vertex interface{}
type VertexList []Vertex

// VertexSet uses maps to express a value-less (empty struct), indexed
// unordered list. See
// https://groups.google.com/forum/#!searchin/golang-nuts/map/golang-nuts/H2cXpwisEUE/1X2FV-rODfIJ
type VertexSet map[Vertex]struct{}

// However, as a practical, internal matter, some approaches to representing
// graphs may benefit significantly (in terms of memory use) from having a uint
// that uniquely identifies each vertex. This is essentially an implementation
// detail, but if your use case merits it (large graph processing is busting
// memory), you can trade off a bit of speed for potentially nontrivial memory
// savings.
// TODO implement a datastructure that does this, and test these outlandish claims!
type IdentifiableVertex interface {
	id() uint64
}

/* Edge structures */

// A graph's behaviors is primarily a product of the constraints and
// capabilities it places on its edges. These constraints and capabilities
// determine whether certain types of operations are possible on the graph, as
// well as the efficiencies for various operations.

// gogl aims to provide a diverse range of graph implementations that can meet
// the varying constraints and implementation needs, but still achieve optimal
// performance given those constraints.

// TODO totally unclear whether or not defining capabilities in a bitfield like
// this will actually help us achieve the goal
const (
	E_DIRECTED, EM_DIRECTED = 1 << iota, 1<<iota - 1
	E_UNDIRECTED, EM_UNDIRECTED
	E_WEIGHTED, EM_WEIGHTED
	E_TYPED, EM_TYPED
	E_SIGNED, EM_SIGNED
	E_LOOPS, EM_LOOPS
	E_MULTIGRAPH, EM_MULTIGRAPH
)

type Edge interface {
	Source() Vertex
	Target() Vertex
	Both() (Vertex, Vertex)
}

type WeightedEdge interface {
	Edge
	Weight() int
}

type Path []Edge

// BaseEdge is a struct used internally to represent edges and meet the Edge
// interface requirements. It uses the standard notation, (u,v), for vertex
// pairs in an edge.
type BaseEdge struct {
	U Vertex
	V Vertex
}

func (e BaseEdge) Source() Vertex {
	return e.U
}

func (e BaseEdge) Target() Vertex {
	return e.V
}

func (e BaseEdge) Both() (Vertex, Vertex) {
	return e.U, e.V
}

type BaseWeightedEdge struct {
	BaseEdge
	W int
}

func (e BaseWeightedEdge) Weight() int {
	return e.W
}

/* Graph structures */

type Graph interface {
	EachVertex(f func(vertex Vertex))
	EachEdge(f func(edge Edge))
	EachAdjacent(vertex Vertex, f func(adjacent Vertex))
	HasVertex(vertex Vertex) bool
	Order() int
	Size() int
	InDegree(vertex Vertex) (int, bool)
	OutDegree(vertex Vertex) (int, bool)
}

type MutableGraph interface {
	Graph
	EnsureVertex(vertices ...Vertex)
	RemoveVertex(vertices ...Vertex)
	AddEdges(edges ...Edge)
	RemoveEdges(edges ...Edge)
}

// A simple graph is in opposition to a multigraph: it disallows loops and
// parallel edges.
type SimpleGraph interface {
	Graph
	Density() float64
}

type DirectedGraph interface {
	Graph
	Transpose() DirectedGraph
	IsAcyclic() bool
	GetCycles() [][]Vertex
}

type WeightedGraph interface {
	Graph
	EachWeightedEdge(f func(edge WeightedEdge))
}

type MutableWeightedGraph interface {
	WeightedGraph
	EnsureVertex(vertices ...Vertex)
	RemoveVertex(vertices ...Vertex)
	AddEdges(edges ...WeightedEdge)
	RemoveEdges(edges ...WeightedEdge)
}

/* Initialization for immutable graphs */

type IGInitializer interface {
	EnsureVertex(vertex ...Vertex)
	AddEdges(edges ...Edge) bool
	GetGraph() Graph
}

type ImmutableGraph interface {
	Graph
	EnsureVertex(vertex ...Vertex)
	AddEdges(edges ...Edge)
}

var immutableGraphs map[string]ImmutableGraph

func CreateImmutableGraph(name string) (*ImmutableGraphInitializer, error) {
	template := immutableGraphs[name]
	if template == nil {
		return nil, fmt.Errorf("gogl: Unregistered graph type %s", name)
	}

	// Use reflection to make a copy of the graph template
	v := reflect.New(reflect.Indirect(reflect.ValueOf(template)).Type()).Interface()
	graph, ok := v.(ImmutableGraph)
	if !ok {
		panic(fmt.Sprintf("gogl: Unable to copy graph template: %s (%v)", name, reflect.ValueOf(v).Kind().String()))
	}

	initializer := &ImmutableGraphInitializer{
		Graph: graph,
	}

	return initializer, nil
}

// A ImmutableGraphInitializer provides write-only methods to populate an
// immutable graph.
type ImmutableGraphInitializer struct {
	Graph ImmutableGraph
}

func (gi *ImmutableGraphInitializer) EnsureVertex(vertices ...Vertex) {
	gi.Graph.EnsureVertex(vertices...)
}

func (gi *ImmutableGraphInitializer) AddEdges(edges ...Edge) {
	gi.Graph.AddEdges(edges...)
}

func (gi *ImmutableGraphInitializer) GetGraph() Graph {
	defer func() { gi.Graph = nil }()
	return gi.Graph
}

func init() {
	immutableGraphs = map[string]ImmutableGraph{
		"ual": NewUndirected(),
	}
}
<commit_msg>Remove detritus that was offering no benefit.<commit_after>package gogl

import (
	"fmt"
	"reflect"
)

/* Vertex structures */

// As a rule, gogl tries to place as low a requirement on its vertices as
// possible. This is because, from a purely graph theoretic perspective,
// vertices are inert. Boring, even. Graphs are more about the topology, the
// characteristics of the edges connecting the points than the points
// themselves. Your use case cares about the content of your vertices, but gogl
// does not.  Consequently, anything can act as a vertex.
type Vertex interface{}

/* Edge structures */

// A graph's behaviors is primarily a product of the constraints and
// capabilities it places on its edges. These constraints and capabilities
// determine whether certain types of operations are possible on the graph, as
// well as the efficiencies for various operations.

// gogl aims to provide a diverse range of graph implementations that can meet
// the varying constraints and implementation needs, but still achieve optimal
// performance given those constraints.

type Edge interface {
	Source() Vertex
	Target() Vertex
	Both() (Vertex, Vertex)
}

type WeightedEdge interface {
	Edge
	Weight() int
}

// BaseEdge is a struct used internally to represent edges and meet the Edge
// interface requirements. It uses the standard notation, (u,v), for vertex
// pairs in an edge.
type BaseEdge struct {
	U Vertex
	V Vertex
}

func (e BaseEdge) Source() Vertex {
	return e.U
}

func (e BaseEdge) Target() Vertex {
	return e.V
}

func (e BaseEdge) Both() (Vertex, Vertex) {
	return e.U, e.V
}

type BaseWeightedEdge struct {
	BaseEdge
	W int
}

func (e BaseWeightedEdge) Weight() int {
	return e.W
}

/* Graph structures */

type Graph interface {
	EachVertex(f func(vertex Vertex))
	EachEdge(f func(edge Edge))
	EachAdjacent(vertex Vertex, f func(adjacent Vertex))
	HasVertex(vertex Vertex) bool
	Order() int
	Size() int
	InDegree(vertex Vertex) (int, bool)
	OutDegree(vertex Vertex) (int, bool)
}

type MutableGraph interface {
	Graph
	EnsureVertex(vertices ...Vertex)
	RemoveVertex(vertices ...Vertex)
	AddEdges(edges ...Edge)
	RemoveEdges(edges ...Edge)
}

// A simple graph is in opposition to a multigraph: it disallows loops and
// parallel edges.
type SimpleGraph interface {
	Graph
	Density() float64
}

type DirectedGraph interface {
	Graph
	Transpose() DirectedGraph
	IsAcyclic() bool
	GetCycles() [][]Vertex
}

type WeightedGraph interface {
	Graph
	EachWeightedEdge(f func(edge WeightedEdge))
}

type MutableWeightedGraph interface {
	WeightedGraph
	EnsureVertex(vertices ...Vertex)
	RemoveVertex(vertices ...Vertex)
	AddEdges(edges ...WeightedEdge)
	RemoveEdges(edges ...WeightedEdge)
}

/* Initialization for immutable graphs */

type IGInitializer interface {
	EnsureVertex(vertex ...Vertex)
	AddEdges(edges ...Edge) bool
	GetGraph() Graph
}

type ImmutableGraph interface {
	Graph
	EnsureVertex(vertex ...Vertex)
	AddEdges(edges ...Edge)
}

var immutableGraphs map[string]ImmutableGraph

func CreateImmutableGraph(name string) (*ImmutableGraphInitializer, error) {
	template := immutableGraphs[name]
	if template == nil {
		return nil, fmt.Errorf("gogl: Unregistered graph type %s", name)
	}

	// Use reflection to make a copy of the graph template
	v := reflect.New(reflect.Indirect(reflect.ValueOf(template)).Type()).Interface()
	graph, ok := v.(ImmutableGraph)
	if !ok {
		panic(fmt.Sprintf("gogl: Unable to copy graph template: %s (%v)", name, reflect.ValueOf(v).Kind().String()))
	}

	initializer := &ImmutableGraphInitializer{
		Graph: graph,
	}

	return initializer, nil
}

// A ImmutableGraphInitializer provides write-only methods to populate an
// immutable graph.
type ImmutableGraphInitializer struct {
	Graph ImmutableGraph
}

func (gi *ImmutableGraphInitializer) EnsureVertex(vertices ...Vertex) {
	gi.Graph.EnsureVertex(vertices...)
}

func (gi *ImmutableGraphInitializer) AddEdges(edges ...Edge) {
	gi.Graph.AddEdges(edges...)
}

func (gi *ImmutableGraphInitializer) GetGraph() Graph {
	defer func() { gi.Graph = nil }()
	return gi.Graph
}

func init() {
	immutableGraphs = map[string]ImmutableGraph{
		"ual": NewUndirected(),
	}
}
<|endoftext|>


<commit_before>package newznab

import (
	"encoding/json"
	"encoding/xml"
	"time"
)

// NZB represents an NZB found on the index
type NZB struct {
	ID          string    `json:"id,omitempty"`
	Title       string    `json:"title,omitempty"`
	Description string    `json:"description,omitempty"`
	Size        int64     `json:"size,omitempty"`
	AirDate     time.Time `json:"air_date,omitempty"`
	PubDate     time.Time `json:"pub_date,omitempty"`
	UsenetDate  time.Time `json:"usenet_date,omitempty"`
	NumGrabs    int       `json:"num_grabs,omitempty"`
	NumComments int       `json:"num_comments,omitempty"`
	Comments    []Comment `json:"comments,omitempty"`

	SourceEndpoint string `json:"source_endpoint"`
	SourceAPIKey   string `json:"source_apikey"`

	Category []string `json:"category,omitempty"`
	Info     string   `json:"info,omitempty"`
	Genre    string   `json:"genre,omitempty"`

	// TV Specific stuff
	TVDBID   string `json:"genre,omitempty"`
	TVRageID string `json:"genre,omitempty"`
	Season   string `json:"season,omitempty"`
	Episode  string `json:"episode,omitempty"`
	TVTitle  string `json:"tvtitle,omitempty"`
	Rating   int    `json:"tvtitle,omitempty"`

	// Movie Specific stuff
	IMDBID    string  `json:"imdb,omitempty"`
	IMDBTitle string  `json:"imdbtitle,omitempty"`
	IMDBYear  int     `json:"imdbyear,omitempty"`
	IMDBScore float32 `json:"imdbscore,omitempty"`
	CoverURL  string  `json:"coverurl,omitempty"`

	// Torznab specific stuff
	Seeders     int    `json:"seeders,omitempty"`
	Peers       int    `json:"peers,omitempty"`
	InfoHash    string `json:"infohash,omitempty"`
	DownloadURL string `json:"download_url,omitempty"`
	IsTorrent   bool   `json:"is_torrent,omitempty"`
}

// Comment represents a user comment left on an NZB record
type Comment struct {
	Title   string    `json:"title,omitempty"`
	Content string    `json:"content,omitempty"`
	PubDate time.Time `json:"pub_date,omitempty"`
}

// JSONString returns a JSON string representation of this NZB
func (n NZB) JSONString() string {
	jsonString, _ := json.MarshalIndent(n, "", "  ")
	return string(jsonString)
}

// JSONString returns a JSON string representation of this Comment
func (c Comment) JSONString() string {
	jsonString, _ := json.MarshalIndent(c, "", "  ")
	return string(jsonString)
}

// SearchResponse is a RSS version of the response.
type SearchResponse struct {
	Version   string `xml:"version,attr"`
	ErrorCode int    `xml:"code,attr"`
	ErrorDesc string `xml:"description,attr"`
	Channel   struct {
		Title string `xml:"title"`
		Link  struct {
			Href string `xml:"href,attr"`
			Rel  string `xml:"rel,attr"`
			Type string `xml:"type,attr"`
		} `xml:"http://www.w3.org/2005/Atom link"`
		Description string `xml:"description"`
		Language    string `xml:"language,omitempty"`
		Webmaster   string `xml:"webmaster,omitempty"`
		Category    string `xml:"category,omitempty"`
		Image       struct {
			URL         string `xml:"url"`
			Title       string `xml:"title"`
			Link        string `xml:"link"`
			Description string `xml:"description,omitempty"`
			Width       int    `xml:"width,omitempty"`
			Height      int    `xml:"height,omitempty"`
		} `xml:"image"`

		Response struct {
			Offset int `xml:"offset,attr"`
			Total  int `xml:"total,attr"`
		} `xml:"http://www.newznab.com/DTD/2010/feeds/attributes/ response"`

		// All NZBs that match the search query, up to the response limit.
		NZBs []RawNZB `xml:"item"`
	} `xml:"channel"`
}

// RawNZB represents a single NZB item in search results.
type RawNZB struct {
	Title    string `xml:"title,omitempty"`
	Link     string `xml:"link,omitempty"`
	Size     int64  `xml:"size,omitempty"`
	Category struct {
		Domain string `xml:"domain,attr"`
		Value  string `xml:",chardata"`
	} `xml:"category,omitempty"`

	GUID struct {
		GUID        string `xml:",chardata"`
		IsPermaLink bool   `xml:"isPermaLink,attr"`
	} `xml:"guid,omitempty"`

	Comments    string `xml:"comments"`
	Description string `xml:"description"`
	Author      string `xml:"author,omitempty"`

	Source struct {
		URL   string `xml:"url,attr"`
		Value string `xml:",chardata"`
	} `xml:"source,omitempty"`

	Date Time `xml:"pubDate,omitempty"`

	Enclosure struct {
		URL    string `xml:"url,attr"`
		Length string `xml:"length,attr"`
		Type   string `xml:"type,attr"`
	} `xml:"enclosure,omitempty"`

	Attributes []struct {
		XMLName xml.Name
		Name    string `xml:"name,attr"`
		Value   string `xml:"value,attr"`
	} `xml:"attr"`
}

type Time struct {
	time.Time
}

func (t *Time) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	e.EncodeToken(start)
	e.EncodeToken(xml.CharData([]byte(t.UTC().Format(time.RFC822))))
	e.EncodeToken(xml.EndElement{start.Name})
	return nil
}

func (t *Time) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var raw string

	err := d.DecodeElement(&raw, &start)
	if err != nil {
		return err
	}
	date, err := time.Parse(time.RFC1123Z, raw)

	if err != nil {
		return err
	}

	*t = Time{date}
	return nil

}
<commit_msg>symmetric marshalling of date<commit_after>package newznab

import (
	"encoding/json"
	"encoding/xml"
	"time"
)

// NZB represents an NZB found on the index
type NZB struct {
	ID          string    `json:"id,omitempty"`
	Title       string    `json:"title,omitempty"`
	Description string    `json:"description,omitempty"`
	Size        int64     `json:"size,omitempty"`
	AirDate     time.Time `json:"air_date,omitempty"`
	PubDate     time.Time `json:"pub_date,omitempty"`
	UsenetDate  time.Time `json:"usenet_date,omitempty"`
	NumGrabs    int       `json:"num_grabs,omitempty"`
	NumComments int       `json:"num_comments,omitempty"`
	Comments    []Comment `json:"comments,omitempty"`

	SourceEndpoint string `json:"source_endpoint"`
	SourceAPIKey   string `json:"source_apikey"`

	Category []string `json:"category,omitempty"`
	Info     string   `json:"info,omitempty"`
	Genre    string   `json:"genre,omitempty"`

	// TV Specific stuff
	TVDBID   string `json:"genre,omitempty"`
	TVRageID string `json:"genre,omitempty"`
	Season   string `json:"season,omitempty"`
	Episode  string `json:"episode,omitempty"`
	TVTitle  string `json:"tvtitle,omitempty"`
	Rating   int    `json:"tvtitle,omitempty"`

	// Movie Specific stuff
	IMDBID    string  `json:"imdb,omitempty"`
	IMDBTitle string  `json:"imdbtitle,omitempty"`
	IMDBYear  int     `json:"imdbyear,omitempty"`
	IMDBScore float32 `json:"imdbscore,omitempty"`
	CoverURL  string  `json:"coverurl,omitempty"`

	// Torznab specific stuff
	Seeders     int    `json:"seeders,omitempty"`
	Peers       int    `json:"peers,omitempty"`
	InfoHash    string `json:"infohash,omitempty"`
	DownloadURL string `json:"download_url,omitempty"`
	IsTorrent   bool   `json:"is_torrent,omitempty"`
}

// Comment represents a user comment left on an NZB record
type Comment struct {
	Title   string    `json:"title,omitempty"`
	Content string    `json:"content,omitempty"`
	PubDate time.Time `json:"pub_date,omitempty"`
}

// JSONString returns a JSON string representation of this NZB
func (n NZB) JSONString() string {
	jsonString, _ := json.MarshalIndent(n, "", "  ")
	return string(jsonString)
}

// JSONString returns a JSON string representation of this Comment
func (c Comment) JSONString() string {
	jsonString, _ := json.MarshalIndent(c, "", "  ")
	return string(jsonString)
}

// SearchResponse is a RSS version of the response.
type SearchResponse struct {
	Version   string `xml:"version,attr"`
	ErrorCode int    `xml:"code,attr"`
	ErrorDesc string `xml:"description,attr"`
	Channel   struct {
		Title string `xml:"title"`
		Link  struct {
			Href string `xml:"href,attr"`
			Rel  string `xml:"rel,attr"`
			Type string `xml:"type,attr"`
		} `xml:"http://www.w3.org/2005/Atom link"`
		Description string `xml:"description"`
		Language    string `xml:"language,omitempty"`
		Webmaster   string `xml:"webmaster,omitempty"`
		Category    string `xml:"category,omitempty"`
		Image       struct {
			URL         string `xml:"url"`
			Title       string `xml:"title"`
			Link        string `xml:"link"`
			Description string `xml:"description,omitempty"`
			Width       int    `xml:"width,omitempty"`
			Height      int    `xml:"height,omitempty"`
		} `xml:"image"`

		Response struct {
			Offset int `xml:"offset,attr"`
			Total  int `xml:"total,attr"`
		} `xml:"http://www.newznab.com/DTD/2010/feeds/attributes/ response"`

		// All NZBs that match the search query, up to the response limit.
		NZBs []RawNZB `xml:"item"`
	} `xml:"channel"`
}

// RawNZB represents a single NZB item in search results.
type RawNZB struct {
	Title    string `xml:"title,omitempty"`
	Link     string `xml:"link,omitempty"`
	Size     int64  `xml:"size,omitempty"`
	Category struct {
		Domain string `xml:"domain,attr"`
		Value  string `xml:",chardata"`
	} `xml:"category,omitempty"`

	GUID struct {
		GUID        string `xml:",chardata"`
		IsPermaLink bool   `xml:"isPermaLink,attr"`
	} `xml:"guid,omitempty"`

	Comments    string `xml:"comments"`
	Description string `xml:"description"`
	Author      string `xml:"author,omitempty"`

	Source struct {
		URL   string `xml:"url,attr"`
		Value string `xml:",chardata"`
	} `xml:"source,omitempty"`

	Date Time `xml:"pubDate,omitempty"`

	Enclosure struct {
		URL    string `xml:"url,attr"`
		Length string `xml:"length,attr"`
		Type   string `xml:"type,attr"`
	} `xml:"enclosure,omitempty"`

	Attributes []struct {
		XMLName xml.Name
		Name    string `xml:"name,attr"`
		Value   string `xml:"value,attr"`
	} `xml:"attr"`
}

type Time struct {
	time.Time
}

func (t *Time) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	e.EncodeToken(start)
	e.EncodeToken(xml.CharData([]byte(t.UTC().Format(time.RFC1123Z))))
	e.EncodeToken(xml.EndElement{start.Name})
	return nil
}

func (t *Time) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var raw string

	err := d.DecodeElement(&raw, &start)
	if err != nil {
		return err
	}
	date, err := time.Parse(time.RFC1123Z, raw)

	if err != nil {
		return err
	}

	*t = Time{date}
	return nil

}
<|endoftext|>


<commit_before>/*
 * This file is part of the kubevirt project
 *
 * 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.
 *
 * Copyright 2018 Red Hat, Inc.
 *
 */

package tests_test

import (
	"flag"
	"strings"
	"time"

	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	k8sv1 "k8s.io/api/core/v1"

	"kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/log"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("Slirp", func() {

	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	var genericVmi *v1.VirtualMachineInstance
	var deadbeafVmi *v1.VirtualMachineInstance
	var container k8sv1.Container

	tests.BeforeAll(func() {
		ports := []v1.Port{{Name: "http", Port: 80}}
		genericVmi = tests.NewRandomVMIWithSlirpInterfaceEphemeralDiskAndUserdata(tests.RegistryDiskFor(tests.RegistryDiskCirros), "#!/bin/bash\necho 'hello'\n", ports)
		deadbeafVmi = tests.NewRandomVMIWithSlirpInterfaceEphemeralDiskAndUserdata(tests.RegistryDiskFor(tests.RegistryDiskCirros), "#!/bin/bash\necho 'hello'\n", ports)
		deadbeafVmi.Spec.Domain.Devices.Interfaces[0].MacAddress = "de:ad:00:00:be:af"

		for _, vmi := range []*v1.VirtualMachineInstance{genericVmi, deadbeafVmi} {
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)
			generateHelloWorldServer(vmi, virtClient, 80, "tcp")
		}
	})

	table.DescribeTable("should be able to", func(vmiRef **v1.VirtualMachineInstance) {
		By("have containerPort in the pod manifest")
		vmi := *vmiRef
		vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
		for _, containerSpec := range vmiPod.Spec.Containers {
			if containerSpec.Name == "compute" {
				container = containerSpec
				break
			}
		}
		Expect(container.Name).ToNot(Equal(""))
		Expect(container.Ports).ToNot(Equal(nil))
		Expect(container.Ports[0].Name).To(Equal("http"))
		Expect(container.Ports[0].Protocol).To(Equal(k8sv1.Protocol("TCP")))
		Expect(container.Ports[0].ContainerPort).To(Equal(int32(80)))

		By("start the virtual machine with slirp interface")
		output, err := tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"netstat", "-tnlp"},
		)
		log.Log.Infof("%v", output)
		Expect(err).ToNot(HaveOccurred())
		Expect(strings.Contains(output, "0.0.0.0:80")).To(BeTrue())

		By("return \"Hello World!\" when connecting to localhost on port 80")
		output, err = tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"curl", "-s", "--retry", "30", "--retry-delay", "30", "127.0.0.1"},
		)
		log.Log.Infof("%v", output)
		Expect(err).ToNot(HaveOccurred())
		Expect(strings.Contains(output, "Hello World!")).To(BeTrue())

		By("reject connecting to localhost and port different than 80")
		output, err = tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"curl", "127.0.0.1:9080"},
		)
		log.Log.Infof("%v", output)
		Expect(err).To(HaveOccurred())

		By("communicate with the outside world")
		expecter, _, err := tests.NewConsoleExpecter(virtClient, vmi, 10*time.Second)
		defer expecter.Close()
		Expect(err).ToNot(HaveOccurred())

		out, err := expecter.ExpectBatch([]expect.Batcher{
			&expect.BSnd{S: "\n"},
			&expect.BExp{R: "\\$ "},
			&expect.BSnd{S: "curl -o /dev/null -s -w \"%{http_code}\\n\" -k https://google.com\n"},
			&expect.BExp{R: "301"},
		}, 180*time.Second)
		log.Log.Infof("%v", out)
		Expect(err).ToNot(HaveOccurred())
	},
		table.Entry("VirtualMachineInstance with slirp interface", &genericVmi),
		table.Entry("VirtualMachineInstance with slirp interface with custom MAC address", &deadbeafVmi),
	)
})
<commit_msg>Use "/proc/net/tcp instead of netstat in slirp tests<commit_after>/*
 * This file is part of the kubevirt project
 *
 * 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.
 *
 * Copyright 2018 Red Hat, Inc.
 *
 */

package tests_test

import (
	"flag"
	"strings"
	"time"

	"github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	k8sv1 "k8s.io/api/core/v1"

	"kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/log"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("Slirp", func() {

	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	var genericVmi *v1.VirtualMachineInstance
	var deadbeafVmi *v1.VirtualMachineInstance
	var container k8sv1.Container

	tests.BeforeAll(func() {
		ports := []v1.Port{{Name: "http", Port: 80}}
		genericVmi = tests.NewRandomVMIWithSlirpInterfaceEphemeralDiskAndUserdata(tests.RegistryDiskFor(tests.RegistryDiskCirros), "#!/bin/bash\necho 'hello'\n", ports)
		deadbeafVmi = tests.NewRandomVMIWithSlirpInterfaceEphemeralDiskAndUserdata(tests.RegistryDiskFor(tests.RegistryDiskCirros), "#!/bin/bash\necho 'hello'\n", ports)
		deadbeafVmi.Spec.Domain.Devices.Interfaces[0].MacAddress = "de:ad:00:00:be:af"

		for _, vmi := range []*v1.VirtualMachineInstance{genericVmi, deadbeafVmi} {
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)
			generateHelloWorldServer(vmi, virtClient, 80, "tcp")
		}
	})

	table.DescribeTable("should be able to", func(vmiRef **v1.VirtualMachineInstance) {
		By("have containerPort in the pod manifest")
		vmi := *vmiRef
		vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
		for _, containerSpec := range vmiPod.Spec.Containers {
			if containerSpec.Name == "compute" {
				container = containerSpec
				break
			}
		}
		Expect(container.Name).ToNot(Equal(""))
		Expect(container.Ports).ToNot(Equal(nil))
		Expect(container.Ports[0].Name).To(Equal("http"))
		Expect(container.Ports[0].Protocol).To(Equal(k8sv1.Protocol("TCP")))
		Expect(container.Ports[0].ContainerPort).To(Equal(int32(80)))

		By("start the virtual machine with slirp interface")
		output, err := tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"cat", "/proc/net/tcp"},
		)
		log.Log.Infof("%v", output)
		Expect(err).ToNot(HaveOccurred())
		// :0050 is port 80, 0A is listening
		Expect(strings.Contains(output, "0: 00000000:0050 00000000:0000 0A")).To(BeTrue())

		By("return \"Hello World!\" when connecting to localhost on port 80")
		output, err = tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"curl", "-s", "--retry", "30", "--retry-delay", "30", "127.0.0.1"},
		)
		log.Log.Infof("%v", output)
		Expect(err).ToNot(HaveOccurred())
		Expect(strings.Contains(output, "Hello World!")).To(BeTrue())

		By("reject connecting to localhost and port different than 80")
		output, err = tests.ExecuteCommandOnPod(
			virtClient,
			vmiPod,
			vmiPod.Spec.Containers[1].Name,
			[]string{"curl", "127.0.0.1:9080"},
		)
		log.Log.Infof("%v", output)
		Expect(err).To(HaveOccurred())

		By("communicate with the outside world")
		expecter, _, err := tests.NewConsoleExpecter(virtClient, vmi, 10*time.Second)
		defer expecter.Close()
		Expect(err).ToNot(HaveOccurred())

		out, err := expecter.ExpectBatch([]expect.Batcher{
			&expect.BSnd{S: "\n"},
			&expect.BExp{R: "\\$ "},
			&expect.BSnd{S: "curl -o /dev/null -s -w \"%{http_code}\\n\" -k https://google.com\n"},
			&expect.BExp{R: "301"},
		}, 180*time.Second)
		log.Log.Infof("%v", out)
		Expect(err).ToNot(HaveOccurred())
	},
		table.Entry("VirtualMachineInstance with slirp interface", &genericVmi),
		table.Entry("VirtualMachineInstance with slirp interface with custom MAC address", &deadbeafVmi),
	)
})
<|endoftext|>


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

package thrift

import (
	"errors"
	"io"
)

var errTransportInterrupted = errors.New("Transport Interrupted")

type Flusher interface {
	Flush() (err error)
}

type ReadSizeProvider interface {
	RemainingBytes() (num_bytes uint64)
}

// Encapsulates the I/O layer
type Transport interface {
	io.ReadWriteCloser
	Flusher
	ReadSizeProvider

	// Opens the transport for communication
	Open() error

	// Returns true if the transport is open
	IsOpen() bool
}

type stringWriter interface {
	WriteString(s string) (n int, err error)
}

// This is "enchanced" transport with extra capabilities. You need to use one of these
// to construct protocol.
// Notably, Socket does not implement this interface, and it is always a mistake to use
// Socket directly in protocol.
type RichTransport interface {
	io.ReadWriter
	io.ByteReader
	io.ByteWriter
	stringWriter
	Flusher
	ReadSizeProvider
}

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

package thrift

import (
	"errors"
	"io"
)

var errTransportInterrupted = errors.New("Transport Interrupted")

// Flusher is the interface that wraps the basic Flush method
type Flusher interface {
	Flush() (err error)
}

// ReadSizeProvider is the interface that wraps the basic RemainingBytes method
type ReadSizeProvider interface {
	RemainingBytes() (numBytes uint64)
}

// Transport is an encapsulation of the I/O layer
type Transport interface {
	io.ReadWriteCloser
	Flusher
	ReadSizeProvider

	// Opens the transport for communication
	Open() error

	// Returns true if the transport is open
	IsOpen() bool
}

type stringWriter interface {
	WriteString(s string) (n int, err error)
}

// RichTransport is an "enhanced" transport with extra capabilities.
// You need to use one of these to construct protocol.
// Notably, Socket does not implement this interface, and it is always a mistake to use
// Socket directly in protocol.
type RichTransport interface {
	io.ReadWriter
	io.ByteReader
	io.ByteWriter
	stringWriter
	Flusher
	ReadSizeProvider
}
<|endoftext|>


<commit_before>package operation

import (
	"log"
	"os"
	"github.com/codegangsta/cli"
	"fmt"
	"github.com/stormcat24/ecs-formation/aws"
	"github.com/stormcat24/ecs-formation/service"
	"github.com/stormcat24/ecs-formation/task"
	"strings"
	"github.com/str1ngs/ansi/color"
	"github.com/stormcat24/ecs-formation/plan"
	"github.com/stormcat24/ecs-formation/util"
	"github.com/stormcat24/ecs-formation/bluegreen"
	"github.com/stormcat24/ecs-formation/logger"
)

var Commands = []cli.Command{
	commandService,
	commandTask,
	commandBluegreen,
}

var commandService = cli.Command{
	Name: "service",
	Usage: "Manage ECS services on cluster",
	Description: `
	Manage services on ECS cluster.
`,
	Action: doService,
}

var commandTask = cli.Command{
	Name: "task",
	Usage: "Manage ECS Task Definitions",
	Description: `
	Manage ECS Task Definitions.
`,
	Action: doTask,
}

var commandBluegreen = cli.Command{
	Name: "bluegreen",
	Usage: "Manage bluegreen deployment on ECS",
	Description: `
	Manage bluegreen deployment on ECS.
`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "nodeploy, nd",
			Usage: "bbb",
		},
	},
	Action: doBluegreen,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doService(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	clusterController, err := service.NewServiceController(ecsManager, projectDir, operation.TargetResource)

	plans, err := createClusterPlans(clusterController, projectDir)

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	if (operation.SubCommand == "apply") {
		clusterController.ApplyServicePlans(plans)
	}
}

func doTask(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	taskController, err := task.NewTaskDefinitionController(ecsManager, projectDir, operation.TargetResource)
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	plans := createTaskPlans(taskController, projectDir)

	if (operation.SubCommand == "apply") {
		results, errapp := taskController.ApplyTaskDefinitionPlans(plans)

		if errapp != nil {
			logger.Main.Error(color.Red(errapp.Error()))
			os.Exit(1)
		}

		for _, output := range results {
			logger.Main.Infof("Registered Task Definition '%s'", *output.TaskDefinition.Family)
			logger.Main.Info(color.Cyan(util.StringValueWithIndent(output.TaskDefinition, 1)))
		}
	}
}

func doBluegreen(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	bgController, errbgc := bluegreen.NewBlueGreenController(ecsManager, projectDir, operation.TargetResource)
	if errbgc != nil {
		logger.Main.Error(color.Red(errbgc.Error()))
		os.Exit(1)
	}

	bgPlans, err := createBlueGreenPlans(bgController)

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	// cluster check

	if (operation.SubCommand == "apply") {

		nodeploy := c.Bool("nodeploy")

		if len(bgPlans) > 0 {
			errbg := bgController.ApplyBlueGreenDeploys(bgPlans, nodeploy)
			if errbg != nil {
				logger.Main.Error(color.Red(errbg.Error()))
				os.Exit(1)
			}
		} else {
			logger.Main.Infof("Not found Blue Green Definition")

			if len(operation.TargetResource) > 0 {
				logger.Main.Infof("Try to update service '%s'", operation.TargetResource)
				doService(c)
			}

		}
	}
}

func createClusterPlans(controller *service.ServiceController, projectDir string) ([]*plan.ServiceUpdatePlan, error) {

	logger.Main.Infoln("Checking services on clusters...")
	plans, err := controller.CreateServiceUpdatePlans()

	if err != nil {
		return []*plan.ServiceUpdatePlan{}, err
	}

	for _, plan := range plans {

		fmt.Println(color.Yellow(fmt.Sprintf("Current status of ECS Cluster '%s':", plan.Name)))

		if len(plan.CurrentServices) > 0 {
			fmt.Println(color.Yellow("    Services as follows:"))
		} else {
			fmt.Println(color.Yellow("    No services are deployed."))
		}

		for _, cs := range plan.CurrentServices {
			fmt.Println(color.Yellow(fmt.Sprintf("        ServiceName = %s", *cs.ServiceName)))
			fmt.Println(color.Yellow(fmt.Sprintf("        ServiceARN = %s", *cs.ServiceARN)))
			fmt.Println(color.Yellow(fmt.Sprintf("        TaskDefinition = %s", *cs.TaskDefinition)))
			fmt.Println(color.Yellow(fmt.Sprintf("        DesiredCount = %d", *cs.DesiredCount)))
			fmt.Println(color.Yellow(fmt.Sprintf("        PendingCount = %d", *cs.PendingCount)))
			fmt.Println(color.Yellow(fmt.Sprintf("        RunningCount = %d", *cs.RunningCount)))
			for _, lb := range cs.LoadBalancers {
				fmt.Println(color.Yellow(fmt.Sprintf("        ELB = %s:", *lb.LoadBalancerName)))
				fmt.Println(color.Yellow(fmt.Sprintf("            ContainerName = %s", *lb.ContainerName)))
				fmt.Println(color.Yellow(fmt.Sprintf("            ContainerName = %d", *lb.ContainerPort)))
			}
			fmt.Println(color.Yellow(fmt.Sprintf("        STATUS = %s", *cs.Status)))
		}

		for _, add := range plan.NewServices {
			for _, lb := range add.LoadBalancers {
				logger.Main.Info(color.Cyan(fmt.Sprintf("            ELB:%s", lb.Name)))
			}
		}

		fmt.Println()
	}

	return plans, nil
}

func createTaskPlans(controller *task.TaskDefinitionController, projectDir string) []*plan.TaskUpdatePlan {

	taskDefs := controller.GetTaskDefinitionMap()
	plans := controller.CreateTaskUpdatePlans(taskDefs)

	for _, plan := range plans {
		logger.Main.Infof("Task Definition '%s'", plan.Name)

		for _, add := range plan.NewContainers {
			fmt.Println(color.Cyan(fmt.Sprintf("    (+) %s", add.Name)))
			fmt.Println(color.Cyan(fmt.Sprintf("      image: %s", add.Image)))
			fmt.Println(color.Cyan(fmt.Sprintf("      ports: %s", add.Ports)))
			fmt.Println(color.Cyan(fmt.Sprintf("      environment:\n%s", util.StringValueWithIndent(add.Environment, 4))))
			fmt.Println(color.Cyan(fmt.Sprintf("      links: %s", add.Links)))
			fmt.Println(color.Cyan(fmt.Sprintf("      volumes: %s", add.Volumes)))
		}

		fmt.Println()
	}

	return plans
}

func createBlueGreenPlans(controller *bluegreen.BlueGreenController) ([]*plan.BlueGreenPlan, error) {

	bgmap := controller.GetBlueGreenMap()

	cplans, errcp := controller.ClusterController.CreateServiceUpdatePlans()
	if errcp != nil {
		return []*plan.BlueGreenPlan{}, errcp
	}

	bgplans, errbgp := controller.CreateBlueGreenPlans(bgmap, cplans)
	if errbgp != nil {
		return bgplans, errbgp
	}

	for _, bgplan := range bgplans {
		fmt.Println(color.Cyan("    Blue:"))
		fmt.Println(color.Cyan(fmt.Sprintf("        Cluster = %s", bgplan.Blue.NewService.Cluster)))
		fmt.Println(color.Cyan(fmt.Sprintf("        AutoScalingGroupARN = %s", *bgplan.Blue.AutoScalingGroup.AutoScalingGroupARN)))
		fmt.Println(color.Cyan("        Current services as follows:"))
		for _, bcs := range bgplan.Blue.ClusterUpdatePlan.CurrentServices {
			fmt.Println(color.Cyan(fmt.Sprintf("            %s:", *bcs.ServiceName)))
			fmt.Println(color.Cyan(fmt.Sprintf("                ServiceARN = %s", *bcs.ServiceARN)))
			fmt.Println(color.Cyan(fmt.Sprintf("                TaskDefinition = %s", *bcs.TaskDefinition)))
			fmt.Println(color.Cyan(fmt.Sprintf("                DesiredCount = %d", *bcs.DesiredCount)))
			fmt.Println(color.Cyan(fmt.Sprintf("                PendingCount = %d", *bcs.PendingCount)))
			fmt.Println(color.Cyan(fmt.Sprintf("                RunningCount = %d", *bcs.RunningCount)))
		}

		fmt.Println(color.Green("    Green:"))
		fmt.Println(color.Green(fmt.Sprintf("        Cluster = %s", bgplan.Green.NewService.Cluster)))
		fmt.Println(color.Green(fmt.Sprintf("        AutoScalingGroupARN = %s", *bgplan.Green.AutoScalingGroup.AutoScalingGroupARN)))
		fmt.Println(color.Green("        Current services as follows:"))
		for _, gcs := range bgplan.Green.ClusterUpdatePlan.CurrentServices {
			fmt.Println(color.Green(fmt.Sprintf("            %s:", *gcs.ServiceName)))
			fmt.Println(color.Green(fmt.Sprintf("                ServiceARN = %s", *gcs.ServiceARN)))
			fmt.Println(color.Green(fmt.Sprintf("                TaskDefinition = %s", *gcs.TaskDefinition)))
			fmt.Println(color.Green(fmt.Sprintf("                DesiredCount = %d", *gcs.DesiredCount)))
			fmt.Println(color.Green(fmt.Sprintf("                PendingCount = %d", *gcs.PendingCount)))
			fmt.Println(color.Green(fmt.Sprintf("                RunningCount = %d", *gcs.RunningCount)))
		}

		fmt.Println()
	}

	return bgplans, nil
}

func buildECSManager() (*aws.ECSManager, error) {

	accessKey := strings.Trim(os.Getenv("AWS_ACCESS_KEY"), " ")
	accessSecretKey := strings.Trim(os.Getenv("AWS_SECRET_ACCESS_KEY"), " ")
	region := strings.Trim(os.Getenv("AWS_REGION"), " ")

	if len(accessKey) == 0 {
		return nil, fmt.Errorf("'AWS_ACCESS_KEY' is not specified.")
	}

	if len(accessSecretKey) == 0 {
		return nil, fmt.Errorf("'AWS_SECRET_ACCESS_KEY' is not specified.")
	}

	if len(region) == 0 {
		return nil, fmt.Errorf("'AWS_REGION' is not specified.")
	}

	return aws.NewECSManager(accessKey, accessSecretKey, region), nil
}

func createOperation(args cli.Args) (Operation, error) {

	if len(args) == 0 {
		return Operation{}, fmt.Errorf("subcommand is not specified.")
	}

	sub := args[0]
	if sub == "plan" || sub == "apply" {

		var targetResource string
		if len(args) > 1 {
			targetResource = args[1]
		}

		return Operation{
			SubCommand: sub,
			TargetResource: targetResource,
		}, nil
	} else {
		return Operation{}, fmt.Errorf("'%s' is invalid subcommand.", sub)
	}
}

type Operation struct {
	SubCommand     string
	TargetResource string
}
<commit_msg>:bug: bugfix<commit_after>package operation

import (
	"log"
	"os"
	"github.com/codegangsta/cli"
	"fmt"
	"github.com/stormcat24/ecs-formation/aws"
	"github.com/stormcat24/ecs-formation/service"
	"github.com/stormcat24/ecs-formation/task"
	"strings"
	"github.com/str1ngs/ansi/color"
	"github.com/stormcat24/ecs-formation/plan"
	"github.com/stormcat24/ecs-formation/util"
	"github.com/stormcat24/ecs-formation/bluegreen"
	"github.com/stormcat24/ecs-formation/logger"
)

var Commands = []cli.Command{
	commandService,
	commandTask,
	commandBluegreen,
}

var commandService = cli.Command{
	Name: "service",
	Usage: "Manage ECS services on cluster",
	Description: `
	Manage services on ECS cluster.
`,
	Action: doService,
}

var commandTask = cli.Command{
	Name: "task",
	Usage: "Manage ECS Task Definitions",
	Description: `
	Manage ECS Task Definitions.
`,
	Action: doTask,
}

var commandBluegreen = cli.Command{
	Name: "bluegreen",
	Usage: "Manage bluegreen deployment on ECS",
	Description: `
	Manage bluegreen deployment on ECS.
`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "nodeploy, nd",
			Usage: "bbb",
		},
	},
	Action: doBluegreen,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doService(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	clusterController, err := service.NewServiceController(ecsManager, projectDir, operation.TargetResource)

	plans, err := createClusterPlans(clusterController, projectDir)

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	if (operation.SubCommand == "apply") {
		clusterController.ApplyServicePlans(plans)
	}
}

func doTask(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	taskController, err := task.NewTaskDefinitionController(ecsManager, projectDir, operation.TargetResource)
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	plans := createTaskPlans(taskController, projectDir)

	if (operation.SubCommand == "apply") {
		results, errapp := taskController.ApplyTaskDefinitionPlans(plans)

		if errapp != nil {
			logger.Main.Error(color.Red(errapp.Error()))
			os.Exit(1)
		}

		for _, output := range results {
			logger.Main.Infof("Registered Task Definition '%s'", *output.TaskDefinition.Family)
			logger.Main.Info(color.Cyan(util.StringValueWithIndent(output.TaskDefinition, 1)))
		}
	}
}

func doBluegreen(c *cli.Context) {

	ecsManager, err := buildECSManager()

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	operation, errSubCommand := createOperation(c.Args())

	if errSubCommand != nil {
		logger.Main.Error(color.Red(errSubCommand.Error()))
		os.Exit(1)
	}

	projectDir, err := os.Getwd()
	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	bgController, errbgc := bluegreen.NewBlueGreenController(ecsManager, projectDir, operation.TargetResource)
	if errbgc != nil {
		logger.Main.Error(color.Red(errbgc.Error()))
		os.Exit(1)
	}

	bgPlans, err := createBlueGreenPlans(bgController)

	if err != nil {
		logger.Main.Error(color.Red(err.Error()))
		os.Exit(1)
	}

	// cluster check

	if (operation.SubCommand == "apply") {

		nodeploy := c.Bool("nodeploy")

		if len(bgPlans) > 0 {
			errbg := bgController.ApplyBlueGreenDeploys(bgPlans, nodeploy)
			if errbg != nil {
				logger.Main.Error(color.Red(errbg.Error()))
				os.Exit(1)
			}
		} else {
			logger.Main.Infof("Not found Blue Green Definition")

			if len(operation.TargetResource) > 0 && !nodeploy {
				logger.Main.Infof("Try to update service '%s'", operation.TargetResource)
				doService(c)
			}

		}
	}
}

func createClusterPlans(controller *service.ServiceController, projectDir string) ([]*plan.ServiceUpdatePlan, error) {

	logger.Main.Infoln("Checking services on clusters...")
	plans, err := controller.CreateServiceUpdatePlans()

	if err != nil {
		return []*plan.ServiceUpdatePlan{}, err
	}

	for _, plan := range plans {

		fmt.Println(color.Yellow(fmt.Sprintf("Current status of ECS Cluster '%s':", plan.Name)))

		if len(plan.CurrentServices) > 0 {
			fmt.Println(color.Yellow("    Services as follows:"))
		} else {
			fmt.Println(color.Yellow("    No services are deployed."))
		}

		for _, cs := range plan.CurrentServices {
			fmt.Println(color.Yellow(fmt.Sprintf("        ServiceName = %s", *cs.ServiceName)))
			fmt.Println(color.Yellow(fmt.Sprintf("        ServiceARN = %s", *cs.ServiceARN)))
			fmt.Println(color.Yellow(fmt.Sprintf("        TaskDefinition = %s", *cs.TaskDefinition)))
			fmt.Println(color.Yellow(fmt.Sprintf("        DesiredCount = %d", *cs.DesiredCount)))
			fmt.Println(color.Yellow(fmt.Sprintf("        PendingCount = %d", *cs.PendingCount)))
			fmt.Println(color.Yellow(fmt.Sprintf("        RunningCount = %d", *cs.RunningCount)))
			for _, lb := range cs.LoadBalancers {
				fmt.Println(color.Yellow(fmt.Sprintf("        ELB = %s:", *lb.LoadBalancerName)))
				fmt.Println(color.Yellow(fmt.Sprintf("            ContainerName = %s", *lb.ContainerName)))
				fmt.Println(color.Yellow(fmt.Sprintf("            ContainerName = %d", *lb.ContainerPort)))
			}
			fmt.Println(color.Yellow(fmt.Sprintf("        STATUS = %s", *cs.Status)))
		}

		for _, add := range plan.NewServices {
			for _, lb := range add.LoadBalancers {
				logger.Main.Info(color.Cyan(fmt.Sprintf("            ELB:%s", lb.Name)))
			}
		}

		fmt.Println()
	}

	return plans, nil
}

func createTaskPlans(controller *task.TaskDefinitionController, projectDir string) []*plan.TaskUpdatePlan {

	taskDefs := controller.GetTaskDefinitionMap()
	plans := controller.CreateTaskUpdatePlans(taskDefs)

	for _, plan := range plans {
		logger.Main.Infof("Task Definition '%s'", plan.Name)

		for _, add := range plan.NewContainers {
			fmt.Println(color.Cyan(fmt.Sprintf("    (+) %s", add.Name)))
			fmt.Println(color.Cyan(fmt.Sprintf("      image: %s", add.Image)))
			fmt.Println(color.Cyan(fmt.Sprintf("      ports: %s", add.Ports)))
			fmt.Println(color.Cyan(fmt.Sprintf("      environment:\n%s", util.StringValueWithIndent(add.Environment, 4))))
			fmt.Println(color.Cyan(fmt.Sprintf("      links: %s", add.Links)))
			fmt.Println(color.Cyan(fmt.Sprintf("      volumes: %s", add.Volumes)))
		}

		fmt.Println()
	}

	return plans
}

func createBlueGreenPlans(controller *bluegreen.BlueGreenController) ([]*plan.BlueGreenPlan, error) {

	bgmap := controller.GetBlueGreenMap()

	cplans, errcp := controller.ClusterController.CreateServiceUpdatePlans()
	if errcp != nil {
		return []*plan.BlueGreenPlan{}, errcp
	}

	bgplans, errbgp := controller.CreateBlueGreenPlans(bgmap, cplans)
	if errbgp != nil {
		return bgplans, errbgp
	}

	for _, bgplan := range bgplans {
		fmt.Println(color.Cyan("    Blue:"))
		fmt.Println(color.Cyan(fmt.Sprintf("        Cluster = %s", bgplan.Blue.NewService.Cluster)))
		fmt.Println(color.Cyan(fmt.Sprintf("        AutoScalingGroupARN = %s", *bgplan.Blue.AutoScalingGroup.AutoScalingGroupARN)))
		fmt.Println(color.Cyan("        Current services as follows:"))
		for _, bcs := range bgplan.Blue.ClusterUpdatePlan.CurrentServices {
			fmt.Println(color.Cyan(fmt.Sprintf("            %s:", *bcs.ServiceName)))
			fmt.Println(color.Cyan(fmt.Sprintf("                ServiceARN = %s", *bcs.ServiceARN)))
			fmt.Println(color.Cyan(fmt.Sprintf("                TaskDefinition = %s", *bcs.TaskDefinition)))
			fmt.Println(color.Cyan(fmt.Sprintf("                DesiredCount = %d", *bcs.DesiredCount)))
			fmt.Println(color.Cyan(fmt.Sprintf("                PendingCount = %d", *bcs.PendingCount)))
			fmt.Println(color.Cyan(fmt.Sprintf("                RunningCount = %d", *bcs.RunningCount)))
		}

		fmt.Println(color.Green("    Green:"))
		fmt.Println(color.Green(fmt.Sprintf("        Cluster = %s", bgplan.Green.NewService.Cluster)))
		fmt.Println(color.Green(fmt.Sprintf("        AutoScalingGroupARN = %s", *bgplan.Green.AutoScalingGroup.AutoScalingGroupARN)))
		fmt.Println(color.Green("        Current services as follows:"))
		for _, gcs := range bgplan.Green.ClusterUpdatePlan.CurrentServices {
			fmt.Println(color.Green(fmt.Sprintf("            %s:", *gcs.ServiceName)))
			fmt.Println(color.Green(fmt.Sprintf("                ServiceARN = %s", *gcs.ServiceARN)))
			fmt.Println(color.Green(fmt.Sprintf("                TaskDefinition = %s", *gcs.TaskDefinition)))
			fmt.Println(color.Green(fmt.Sprintf("                DesiredCount = %d", *gcs.DesiredCount)))
			fmt.Println(color.Green(fmt.Sprintf("                PendingCount = %d", *gcs.PendingCount)))
			fmt.Println(color.Green(fmt.Sprintf("                RunningCount = %d", *gcs.RunningCount)))
		}

		fmt.Println()
	}

	return bgplans, nil
}

func buildECSManager() (*aws.ECSManager, error) {

	accessKey := strings.Trim(os.Getenv("AWS_ACCESS_KEY"), " ")
	accessSecretKey := strings.Trim(os.Getenv("AWS_SECRET_ACCESS_KEY"), " ")
	region := strings.Trim(os.Getenv("AWS_REGION"), " ")

	if len(accessKey) == 0 {
		return nil, fmt.Errorf("'AWS_ACCESS_KEY' is not specified.")
	}

	if len(accessSecretKey) == 0 {
		return nil, fmt.Errorf("'AWS_SECRET_ACCESS_KEY' is not specified.")
	}

	if len(region) == 0 {
		return nil, fmt.Errorf("'AWS_REGION' is not specified.")
	}

	return aws.NewECSManager(accessKey, accessSecretKey, region), nil
}

func createOperation(args cli.Args) (Operation, error) {

	if len(args) == 0 {
		return Operation{}, fmt.Errorf("subcommand is not specified.")
	}

	sub := args[0]
	if sub == "plan" || sub == "apply" {

		var targetResource string
		if len(args) > 1 {
			targetResource = args[1]
		}

		return Operation{
			SubCommand: sub,
			TargetResource: targetResource,
		}, nil
	} else {
		return Operation{}, fmt.Errorf("'%s' is invalid subcommand.", sub)
	}
}

type Operation struct {
	SubCommand     string
	TargetResource string
}
<|endoftext|>


<commit_before>// Package hierr provides a simple way to return and display hierarchical
// errors.
//
// Transforms:
//
//         can't pull remote 'origin': can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*': exit status 128
//
// Into:
//
//         can't pull remote 'origin'
//         └─ can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*'
//            └─ exit status 128
package hierr

import (
	"fmt"
	"os"
	"strings"
	"unicode"
)

const (
	// BranchDelimiterASCII represents a simple ASCII delimiter for hierarchy
	// branches.
	//
	// Use: hierr.BranchDelimiter = hierr.BranchDelimiterASCII
	BranchDelimiterASCII = `\_ `

	// BranchDelimiterBox represents UTF8 delimiter for hierarchy branches.
	//
	// Use: hierr.BranchDelimiter = hierr.BranchDelimiterBox
	BranchDelimiterBox = `└─ `

	// BranchChainerASCII represents a simple ASCII chainer for hierarchy
	// branches.
	//
	// Use: hierr.BranchChainer = hierr.BranchChainerASCII
	BranchChainerASCII = `| `

	// BranchChainerBox represents UTF8 chainer for hierarchy branches.
	//
	// Use: hierr.BranchChainer = hierr.BranchChainerBox
	BranchChainerBox = `│ `

	// BranchSplitterASCII represents a simple ASCII splitter for hierarchy
	// branches.
	//
	// Use: hierr.BranchSplitter = hierr.BranchSplitterASCII
	BranchSplitterASCII = `+ `

	// BranchSplitterBox represents UTF8 splitter for hierarchy branches.
	//
	// Use: hierr.BranchSplitter = hierr.BranchSplitterBox
	BranchSplitterBox = `├─ `
)

var (
	// BranchDelimiter set delimiter each nested error text will be started
	// from.
	BranchDelimiter = BranchDelimiterBox

	// BranchChainer set chainer each nested error tree text will be started
	// from.
	BranchChainer = BranchChainerBox

	// BranchSplitter set splitter each nested errors splitted by.
	BranchSplitter = BranchSplitterBox

	// BranchIndent set number of spaces each nested error will be indented by.
	BranchIndent = 3
)

// Error represents hierarchy error, linked with nested error.
type Error struct {
	// Message is formatter error message, which will be reported when Error()
	// will be invoked.
	Message string

	// Nested error, which can be hierr.Error as well.
	Nested interface{}
}

// HierarchicalError represents interface, which methods will be used instead
// of calling String() and Error() methods.
type HierarchicalError interface {
	// HierarchicalError returns hierarhical string representation.
	HierarchicalError() string

	// GetNested returns slice of nested errors.
	GetNested() []NestedError

	// GetMessage returns top-level error message.
	GetMessage() string
}

var (
	exiter = os.Exit
)

// NestedError is either `error` or string.
type NestedError interface{}

// Errorf creates new hierarchy error.
//
// With nestedError == nil call will be equal to `fmt.Errorf()`.
func Errorf(
	nestedError NestedError,
	message string,
	args ...interface{},
) error {
	return Error{
		Message: fmt.Sprintf(message, args...),
		Nested:  nestedError,
	}
}

// Fatalf creates new hierarchy error, prints to stderr and exit 1
//
// Have same semantics as `hierr.Errorf()`.
func Fatalf(
	nestedError NestedError,
	message string,
	args ...interface{},
) {
	fmt.Fprintln(os.Stderr, Errorf(nestedError, message, args...))
	exiter(1)
}

// Error returns string representation of hierarchical error. If no nested
// error was specified, then only current error message will be returned.
func (err Error) Error() string {
	switch children := err.Nested.(type) {
	case nil:
		return err.Message

	case []NestedError:
		return formatNestedError(err, children)

	default:
		return err.Message + "\n" +
			BranchDelimiter +
			strings.Replace(
				String(err.Nested),
				"\n",
				"\n"+strings.Repeat(" ", BranchIndent),
				-1,
			)
	}
}

// GetNested returns nested errors, embedded into error.
func (err Error) GetNested() []NestedError {
	children, ok := err.Nested.([]NestedError)
	if !ok {
		children = []NestedError{}
		if err.Nested != nil {
			children = append(children, err.Nested)
		}
	}

	return children
}

// GetMessage returns top-level error message.
func (err Error) GetMessage() string {
	return err.Message
}

// HierarchicalError returns pretty hierarchical rendering.
func (err Error) HierarchicalError() string {
	return err.Error()
}

// Push creates new hierarchy error with multiple branches separated by
// separator, delimited by delimiter and prolongated by prolongator.
func Push(topError NestedError, childError ...NestedError) error {
	parent, ok := topError.(Error)
	if !ok {
		parent = Error{
			Message: String(topError),
		}
	}

	children := parent.GetNested()

	children = append(children, childError...)

	return Error{
		Message: parent.Message,
		Nested:  children,
	}
}

// String returns string representation of given object, if object implements
// HierarchicalError then will be returned result of calling
// object.HierarchicalError().
func String(object interface{}) string {
	if hierr, ok := object.(HierarchicalError); ok {
		return hierr.HierarchicalError()
	}

	if err, ok := object.(error); ok {
		return err.Error()
	}

	return fmt.Sprintf("%s", object)
}

func formatNestedError(err Error, children []NestedError) string {
	message := err.Message

	prolongate := false
	for _, child := range children {
		if childError, ok := child.(HierarchicalError); ok {
			errs := childError.GetNested()
			if len(errs) > 0 {
				prolongate = true
				break
			}
		}
	}

	for index, child := range children {
		var (
			splitter      = BranchSplitter
			chainer       = BranchChainer
			chainerLength = len([]rune(BranchChainer))
		)

		if index == len(children)-1 {
			splitter = BranchDelimiter
			chainer = strings.Repeat(" ", chainerLength)
		}

		indentation := chainer
		if BranchIndent >= chainerLength {
			indentation += strings.Repeat(" ", BranchIndent-chainerLength)
		}

		prolongator := ""
		if prolongate && index < len(children)-1 {
			prolongator = "\n" + strings.TrimRightFunc(
				chainer, unicode.IsSpace,
			)
		}

		message = message + "\n" +
			splitter +
			strings.Replace(
				String(child),
				"\n",
				"\n"+indentation,
				-1,
			) +
			prolongator
	}

	return message
}
<commit_msg>deprecate old import path<commit_after>// Package hierr provides a simple way to return and display hierarchical
// errors.
//
// Transforms:
//
//         can't pull remote 'origin': can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*': exit status 128
//
// Into:
//
//         can't pull remote 'origin'
//         └─ can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*'
//            └─ exit status 128
package hierr // import "github.com/reconquest/hierr-go"

import (
	"fmt"
	"os"
	"strings"
	"unicode"
)

const (
	// BranchDelimiterASCII represents a simple ASCII delimiter for hierarchy
	// branches.
	//
	// Use: hierr.BranchDelimiter = hierr.BranchDelimiterASCII
	BranchDelimiterASCII = `\_ `

	// BranchDelimiterBox represents UTF8 delimiter for hierarchy branches.
	//
	// Use: hierr.BranchDelimiter = hierr.BranchDelimiterBox
	BranchDelimiterBox = `└─ `

	// BranchChainerASCII represents a simple ASCII chainer for hierarchy
	// branches.
	//
	// Use: hierr.BranchChainer = hierr.BranchChainerASCII
	BranchChainerASCII = `| `

	// BranchChainerBox represents UTF8 chainer for hierarchy branches.
	//
	// Use: hierr.BranchChainer = hierr.BranchChainerBox
	BranchChainerBox = `│ `

	// BranchSplitterASCII represents a simple ASCII splitter for hierarchy
	// branches.
	//
	// Use: hierr.BranchSplitter = hierr.BranchSplitterASCII
	BranchSplitterASCII = `+ `

	// BranchSplitterBox represents UTF8 splitter for hierarchy branches.
	//
	// Use: hierr.BranchSplitter = hierr.BranchSplitterBox
	BranchSplitterBox = `├─ `
)

var (
	// BranchDelimiter set delimiter each nested error text will be started
	// from.
	BranchDelimiter = BranchDelimiterBox

	// BranchChainer set chainer each nested error tree text will be started
	// from.
	BranchChainer = BranchChainerBox

	// BranchSplitter set splitter each nested errors splitted by.
	BranchSplitter = BranchSplitterBox

	// BranchIndent set number of spaces each nested error will be indented by.
	BranchIndent = 3
)

// Error represents hierarchy error, linked with nested error.
type Error struct {
	// Message is formatter error message, which will be reported when Error()
	// will be invoked.
	Message string

	// Nested error, which can be hierr.Error as well.
	Nested interface{}
}

// HierarchicalError represents interface, which methods will be used instead
// of calling String() and Error() methods.
type HierarchicalError interface {
	// HierarchicalError returns hierarhical string representation.
	HierarchicalError() string

	// GetNested returns slice of nested errors.
	GetNested() []NestedError

	// GetMessage returns top-level error message.
	GetMessage() string
}

var (
	exiter = os.Exit
)

// NestedError is either `error` or string.
type NestedError interface{}

// Errorf creates new hierarchy error.
//
// With nestedError == nil call will be equal to `fmt.Errorf()`.
func Errorf(
	nestedError NestedError,
	message string,
	args ...interface{},
) error {
	return Error{
		Message: fmt.Sprintf(message, args...),
		Nested:  nestedError,
	}
}

// Fatalf creates new hierarchy error, prints to stderr and exit 1
//
// Have same semantics as `hierr.Errorf()`.
func Fatalf(
	nestedError NestedError,
	message string,
	args ...interface{},
) {
	fmt.Fprintln(os.Stderr, Errorf(nestedError, message, args...))
	exiter(1)
}

// Error returns string representation of hierarchical error. If no nested
// error was specified, then only current error message will be returned.
func (err Error) Error() string {
	switch children := err.Nested.(type) {
	case nil:
		return err.Message

	case []NestedError:
		return formatNestedError(err, children)

	default:
		return err.Message + "\n" +
			BranchDelimiter +
			strings.Replace(
				String(err.Nested),
				"\n",
				"\n"+strings.Repeat(" ", BranchIndent),
				-1,
			)
	}
}

// GetNested returns nested errors, embedded into error.
func (err Error) GetNested() []NestedError {
	children, ok := err.Nested.([]NestedError)
	if !ok {
		children = []NestedError{}
		if err.Nested != nil {
			children = append(children, err.Nested)
		}
	}

	return children
}

// GetMessage returns top-level error message.
func (err Error) GetMessage() string {
	return err.Message
}

// HierarchicalError returns pretty hierarchical rendering.
func (err Error) HierarchicalError() string {
	return err.Error()
}

// Push creates new hierarchy error with multiple branches separated by
// separator, delimited by delimiter and prolongated by prolongator.
func Push(topError NestedError, childError ...NestedError) error {
	parent, ok := topError.(Error)
	if !ok {
		parent = Error{
			Message: String(topError),
		}
	}

	children := parent.GetNested()

	children = append(children, childError...)

	return Error{
		Message: parent.Message,
		Nested:  children,
	}
}

// String returns string representation of given object, if object implements
// HierarchicalError then will be returned result of calling
// object.HierarchicalError().
func String(object interface{}) string {
	if hierr, ok := object.(HierarchicalError); ok {
		return hierr.HierarchicalError()
	}

	if err, ok := object.(error); ok {
		return err.Error()
	}

	return fmt.Sprintf("%s", object)
}

func formatNestedError(err Error, children []NestedError) string {
	message := err.Message

	prolongate := false
	for _, child := range children {
		if childError, ok := child.(HierarchicalError); ok {
			errs := childError.GetNested()
			if len(errs) > 0 {
				prolongate = true
				break
			}
		}
	}

	for index, child := range children {
		var (
			splitter      = BranchSplitter
			chainer       = BranchChainer
			chainerLength = len([]rune(BranchChainer))
		)

		if index == len(children)-1 {
			splitter = BranchDelimiter
			chainer = strings.Repeat(" ", chainerLength)
		}

		indentation := chainer
		if BranchIndent >= chainerLength {
			indentation += strings.Repeat(" ", BranchIndent-chainerLength)
		}

		prolongator := ""
		if prolongate && index < len(children)-1 {
			prolongator = "\n" + strings.TrimRightFunc(
				chainer, unicode.IsSpace,
			)
		}

		message = message + "\n" +
			splitter +
			strings.Replace(
				String(child),
				"\n",
				"\n"+indentation,
				-1,
			) +
			prolongator
	}

	return message
}
<|endoftext|>


<commit_before>package daemon

import "github.com/subgraph/oz/ipc"

const SocketName = "@oz-control"

type OkMsg struct {
	_ string "Ok"
}

type ErrorMsg struct {
	Msg string "Error"
}

type PingMsg struct {
	Data string "Ping"
}

type GetConfigMsg struct {
	Data string "GetConfig"
}

type ListProfilesMsg struct {
	_ string "ListProfiles"
}

type Profile struct {
	Index int
	Name  string
	Path  string
}

type ListProfilesResp struct {
	Profiles []Profile "ListProfilesResp"
}

type LaunchMsg struct {
	Index  int "Launch"
	Path   string
	Name   string
	Pwd    string
	Gids   []uint32
	Args   []string
	Env    []string
	Noexec bool
}

type ListSandboxesMsg struct {
	_ string "ListSandboxes"
}

type SandboxInfo struct {
	Id      int
	Address string
	Profile string
	Mounts  []string
}

type ListSandboxesResp struct {
	Sandboxes []SandboxInfo "ListSandboxesResp"
}

type KillSandboxMsg struct {
	Id int "KillSandbox"
}

type RelaunchXpraClientMsg struct {
	Id int "RelaunchXpraClient"
}

type MountFilesMsg struct {
	Id       int "MountFiles"
	Files    []string
	ReadOnly bool
}

type UnmountFileMsg struct {
	Id   int "UnmountFile"
	File string
}

type LogsMsg struct {
	Count  int "Logs"
	Follow bool
}

type LogData struct {
	Lines []string "LogData"
}

var messageFactory = ipc.NewMsgFactory(
	new(PingMsg),
	new(OkMsg),
	new(ErrorMsg),
	new(GetConfigMsg),
	new(ListProfilesMsg),
	new(ListProfilesResp),
	new(LaunchMsg),
	new(ListSandboxesMsg),
	new(ListSandboxesResp),
	new(KillSandboxMsg),
	new(RelaunchXpraClientMsg),
	new(MountFilesMsg),
	new(UnmountFileMsg),
	new(LogsMsg),
	new(LogData),
)
<commit_msg>Backport forwarder protocol implementation<commit_after>package daemon

import "github.com/subgraph/oz/ipc"

const SocketName = "@oz-control"

type OkMsg struct {
	_ string "Ok"
}

type ErrorMsg struct {
	Msg string "Error"
}

type PingMsg struct {
	Data string "Ping"
}

type GetConfigMsg struct {
	Data string "GetConfig"
}

type ListProfilesMsg struct {
	_ string "ListProfiles"
}

type Profile struct {
	Index int
	Name  string
	Path  string
}

type ListProfilesResp struct {
	Profiles []Profile "ListProfilesResp"
}

type ListForwardersResp struct {
	Name string "ListForwardersResp"
	Forwarders []Forwarder "ListForwardersResp"
}

type LaunchMsg struct {
	Index  int "Launch"
	Path   string
	Name   string
	Pwd    string
	Gids   []uint32
	Args   []string
	Env    []string
	Noexec bool
}

type ListSandboxesMsg struct {
	_ string "ListSandboxes"
}

type SandboxInfo struct {
	Id      int
	Address string
	Profile string
	Mounts  []string
}

type ListSandboxesResp struct {
	Sandboxes []SandboxInfo "ListSandboxesResp"
}

type KillSandboxMsg struct {
	Id int "KillSandbox"
}

type RelaunchXpraClientMsg struct {
	Id int "RelaunchXpraClient"
}

type MountFilesMsg struct {
	Id       int "MountFiles"
	Files    []string
	ReadOnly bool
}

type UnmountFileMsg struct {
	Id   int "UnmountFile"
	File string
}

type LogsMsg struct {
	Count  int "Logs"
	Follow bool
}

type LogData struct {
	Lines []string "LogData"
}

type ListForwardersMsg struct {
	Id int "ListForwarders"
}

type AskForwarderMsg struct {
	Id int "AskForwarder"
	Name string
	Addr string
	Port string
}

type Forwarder struct {
	Name string "Forwarder"
	Desc string
	Target string
}

type ForwarderSuccessMsg struct {
        Proto string "ForwarderSuccess"
        Addr string
	Port string
}

var messageFactory = ipc.NewMsgFactory(
	new(PingMsg),
	new(OkMsg),
	new(ErrorMsg),
	new(GetConfigMsg),
	new(ListProfilesMsg),
	new(ListProfilesResp),
	new(LaunchMsg),
	new(ListSandboxesMsg),
	new(ListSandboxesResp),
	new(KillSandboxMsg),
	new(RelaunchXpraClientMsg),
	new(MountFilesMsg),
	new(UnmountFileMsg),
	new(LogsMsg),
	new(LogData),
	new(AskForwarderMsg),
	new(ForwarderSuccessMsg),
	new(ListForwardersMsg),
	new(ListForwardersResp),
)
<|endoftext|>


<commit_before>package parsesearch

import (
	"log"
	"os"

	"github.com/tmc/parse"
)

// RegisterHooks auto-registers the search service with a Parse Application.
func (i *Indexer) RegisterHooks(prefix string, className string) error {
	c, err := parse.NewClient(i.appID, "")
	c.TraceOn(log.New(os.Stderr, "[parse api] ", log.LstdFlags))
	if err != nil {
		return err
	}
	c = c.WithMasterKey(i.masterKey)

	err = c.CreateHookFunction(&parse.HookFunction{
		FunctionName: prefix + "search",
		URL:          os.Getenv("URL") + "/search",
	})
	if err != nil {
		return err
	}
	err = c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:    className,
		FunctionName: "afterSave",
		URL:          os.Getenv("URL") + "/index",
	})
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Fix trigger creation<commit_after>package parsesearch

import (
	"log"
	"os"
	"strings"

	"github.com/tmc/parse"
)

func squelchAlreadyExists(err error) error {
	if err, ok := err.(*parse.Error); ok {
		if strings.Contains(err.Message, "already exists") {
			return nil
		}
	}
	return err
}

// RegisterHooks auto-registers the search service with a Parse Application.
func (i *Indexer) RegisterHooks(prefix string, className string) error {
	c, err := parse.NewClient(i.appID, "")
	c.TraceOn(log.New(os.Stderr, "[parse api] ", log.LstdFlags))
	if err != nil {
		return err
	}
	c = c.WithMasterKey(i.masterKey)

	err = c.CreateHookFunction(&parse.HookFunction{
		FunctionName: prefix + "search",
		URL:          os.Getenv("URL") + "/search",
	})
	err = squelchAlreadyExists(err)
	if err != nil {
		return err
	}
	err = c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:   className,
		TriggerName: "afterSave",
		URL:         os.Getenv("URL") + "/index",
	})
	err = squelchAlreadyExists(err)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package aimg

import (
	"bytes"
	"image"
	"io"
	"os"
	"strings"

	// supporting these files types
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	"github.com/stroborobo/ansirgb"
)

var (
	isUTF8 = false
)

func init() {
	isUTF8 = strings.Contains(os.Getenv("LC_ALL"), "UTF-8") ||
		strings.Contains(os.Getenv("LANG"), "UTF-8")
}

// Image represents an ANSI color code "image"
type Image struct {
	im image.Image

	// actual size
	width  int
	height int

	// display size
	cols int
	rows int

	ratio float64

	readIndex int
}

// NewImage returns an Image that will parse and print for a given width of
// columns.
func NewImage(cols int) *Image {
	return &Image{
		cols: cols,
	}
}

// Size returns the resulting size in columns and rows.
func (im *Image) Size() (rows, cols int) {
	return im.cols, im.rows / 2
}

// ActualSize returns the size of the underlying image.
func (im *Image) ActualSize() (height, width int) {
	return im.width, im.height
}

// ParseFile is a shorthand for os.Open() and ParseReader().
func (im *Image) ParseFile(fpath string) error {
	fh, err := os.Open(fpath)
	if err != nil {
		return err
	}
	defer fh.Close()
	return im.ParseReader(fh)
}

// ParseReader reads image data from the reader.
func (im *Image) ParseReader(rd io.Reader) error {
	if img, _, err := image.Decode(rd); err != nil {
		return err
	} else {
		im.im = img
	}

	im.width = im.im.Bounds().Dx()
	im.height = im.im.Bounds().Dy()

	if im.width < im.cols {
		im.cols = im.width
	}

	im.ratio = float64(im.width) / float64(im.cols)
	im.rows = int(float64(im.height) / im.ratio)

	return nil
}

// Blank returns a string containing as many newlines as needed to display the
// image.
func (im *Image) Blank() string {
	return strings.Repeat("\n", im.rows/2)
}

// BlankReset returns a string like Blank() but with an escape code to set the
// cursor to the first of the previous newlines.
func (im *Image) BlankReset() string {
	ret := im.Blank()
	return ret + cursorUp(len(ret))
}

// WriteTo writes the image data to wr.
func (im *Image) WriteTo(wr io.Writer) (int, error) {
	written := 0
	for r := 1; r < im.rows; r += 2 {
		var before *Block
		for c := 1; c < im.cols; c++ {
			x := int(im.ratio * float64(c))
			yt := int(im.ratio * float64(r-1))
			yb := int(im.ratio * float64(r))

			b := &Block{
				Top:    im.getColor(x, yt),
				Bottom: im.getColor(x, yb),
			}

			if before != nil {
				b.nocolor = b.equals(before)
			}
			before = b

			n, err := io.WriteString(wr, b.String())
			written += n
			if err != nil {
				return written, err
			}
		}
		n, err := io.WriteString(wr, newLine())
		written += n
		if err != nil {
			return written, err
		}
	}
	return written, nil
}

func (im *Image) getColor(x, y int) *ansirgb.Color {
	c := im.im.At(x, y)
	if _, _, _, a := c.RGBA(); a < 1<<14-1 {
		return &ansirgb.Color{c, -1} // default/transparent color
	}
	return ansirgb.Convert(c)
}

// String returns the Image's string representation. It's a shorthand to
// WriteTo() using a bytes.Buffer and buf.String().
func (im *Image) String() string {
	buf := &bytes.Buffer{}
	im.WriteTo(buf)
	return buf.String()
}

// Block represents two pixels or a character in a string. It contains a
// Unicode LOWER/UPPER HALF BLOCK, so the top or bottom "pixel" is the
// foreground color and the other one is the background color.
// The character used might change if transparency is needed, which is only
// possible by using the default background color.
type Block struct {
	nocolor bool
	Top     *ansirgb.Color
	Bottom  *ansirgb.Color
}

// String returns the string representation of the block. If aimg can't
// determine whether this is a UTF-8 environment, String will use a '#' instead
// of the LOWER/UPPER HALF BLOCK. If the block's color is equal to the one
// before, it'll just return a string containing a single space.
func (b *Block) String() string {
	if b.nocolor {
		return " "
	}

	// By default top is background, bottom foreground, using
	// LOWER HALF BLOCK.
	first := b.Top
	second := b.Bottom
	block := "\u2584"

	// If the bottom is transparent however switch them all
	// since transparency can only be archieved by using the default
	// background color.
	if b.Bottom.IsTransparent() {
		first, second = second, first
		block = "\u2580"
	}

	ret := first.Bg()

	// Foreground colors are lighter in some terminals. Also "transparent"
	// foreground is not a thing.  Ignore it if it's the same color anyway.
	if !first.Equals(second) {
		ret += second.Fg()
		// If it's not a UTF-8 terminal, fall back to '#'
		if isUTF8 {
			ret += block
		} else {
			ret += "#"
		}
	} else {
		ret += " "
	}

	return ret
}

func (b *Block) equals(b2 *Block) bool {
	return b.Bottom.Code == b2.Bottom.Code && b.Top.Code == b2.Top.Code
}
<commit_msg>fix idiotic errors<commit_after>package aimg

import (
	"bytes"
	"image"
	"io"
	"os"
	"strings"

	// supporting these files types
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	"github.com/stroborobo/ansirgb"
)

var (
	isUTF8 = false
)

func init() {
	isUTF8 = strings.Contains(os.Getenv("LC_ALL"), "UTF-8") ||
		strings.Contains(os.Getenv("LANG"), "UTF-8")
}

// Image represents an ANSI color code "image"
type Image struct {
	im image.Image

	// actual size
	width  int
	height int

	// display size
	cols int
	rows int

	ratio float64

	readIndex int
}

// NewImage returns an Image that will parse and print for a given width of
// columns.
func NewImage(cols int) *Image {
	return &Image{
		cols: cols,
	}
}

// Size returns the resulting size in columns and rows.
func (im *Image) Size() (rows, cols int) {
	return im.cols, im.rows / 2
}

// ActualSize returns the size of the underlying image.
func (im *Image) ActualSize() (height, width int) {
	return im.width, im.height
}

// ParseFile is a shorthand for os.Open() and ParseReader().
func (im *Image) ParseFile(fpath string) error {
	fh, err := os.Open(fpath)
	if err != nil {
		return err
	}
	defer fh.Close()
	return im.ParseReader(fh)
}

// ParseReader reads image data from the reader.
func (im *Image) ParseReader(rd io.Reader) error {
	if img, _, err := image.Decode(rd); err != nil {
		return err
	} else {
		im.im = img
	}

	im.width = im.im.Bounds().Dx()
	im.height = im.im.Bounds().Dy()

	if im.width < im.cols {
		im.cols = im.width
	}

	im.ratio = float64(im.width) / float64(im.cols)
	im.rows = int(float64(im.height) / im.ratio)

	return nil
}

// Blank returns a string containing as many newlines as needed to display the
// image.
func (im *Image) Blank() string {
	return strings.Repeat("\n", im.rows/2)
}

// BlankReset returns a string like Blank() but with an escape code to set the
// cursor to the first of the previous newlines.
func (im *Image) BlankReset() string {
	ret := im.Blank()
	return ret + cursorUp(len(ret))
}

// WriteTo writes the image data to wr.
func (im *Image) WriteTo(wr io.Writer) (int, error) {
	written := 0
	for r := 0; r < im.rows; r += 2 {
		var before *Block
		for c := 0; c < im.cols; c++ {
			x := int(im.ratio * float64(c))
			yt := int(im.ratio * float64(r))
			yb := int(im.ratio * float64(r+1))

			b := &Block{
				Top:    im.getColor(x, yt),
				Bottom: im.getColor(x, yb),
			}

			if before != nil {
				b.nocolor = b.equals(before)
			}
			before = b

			n, err := io.WriteString(wr, b.String())
			written += n
			if err != nil {
				return written, err
			}
		}
		n, err := io.WriteString(wr, newLine())
		written += n
		if err != nil {
			return written, err
		}
	}
	return written, nil
}

func (im *Image) getColor(x, y int) *ansirgb.Color {
	c := im.im.At(x, y)
	if _, _, _, a := c.RGBA(); a < 1<<14-1 {
		return &ansirgb.Color{c, -1} // default/transparent color
	}
	return ansirgb.Convert(c)
}

// String returns the Image's string representation. It's a shorthand to
// WriteTo() using a bytes.Buffer and buf.String().
func (im *Image) String() string {
	buf := &bytes.Buffer{}
	im.WriteTo(buf)
	return buf.String()
}

// Block represents two pixels or a character in a string. It contains a
// Unicode LOWER/UPPER HALF BLOCK, so the top or bottom "pixel" is the
// foreground color and the other one is the background color.
// The character used might change if transparency is needed, which is only
// possible by using the default background color.
type Block struct {
	nocolor bool
	Top     *ansirgb.Color
	Bottom  *ansirgb.Color
}

// String returns the string representation of the block. If aimg can't
// determine whether this is a UTF-8 environment, String will use a '#' instead
// of the LOWER/UPPER HALF BLOCK. If the block's color is equal to the one
// before, it'll just return a string containing a single space.
func (b *Block) String() string {
	// By default top is background, bottom foreground, using
	// LOWER HALF BLOCK.
	first := b.Top
	second := b.Bottom
	block := "\u2584"

	// If the bottom is transparent however switch them all
	// since transparency can only be archieved by using the default
	// background color.
	if b.Bottom.IsTransparent() {
		first, second = second, first
		block = "\u2580"
	}

	ret := ""
	if !b.nocolor {
		ret += first.Bg()
	}

	// Foreground colors are lighter in some terminals. Also "transparent"
	// foreground is not a thing.  Ignore it if it's the same color anyway.
	if !first.Equals(second) {
		if !b.nocolor {
			ret += second.Fg()
		}
		// If it's not a UTF-8 terminal, fall back to '#'
		if isUTF8 {
			ret += block
		} else {
			ret += "#"
		}
	} else {
		ret += " "
	}

	return ret
}

func (b *Block) equals(b2 *Block) bool {
	return b.Bottom.Code == b2.Bottom.Code && b.Top.Code == b2.Top.Code
}
<|endoftext|>


<commit_before>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"net"
	"net/url"
	"os"
)

// ArangoError is a Go error with arangodb specific error information.
type ArangoError struct {
	HasError     bool   `json:"error"`
	Code         int    `json:"code"`
	ErrorNum     int    `json:"errorNum"`
	ErrorMessage string `json:"errorMessage"`
}

// Error returns the error message of an ArangoError.
func (ae ArangoError) Error() string {
	return ae.ErrorMessage
}

// newArangoError creates a new ArangoError with given values.
func newArangoError(code, errorNum int, errorMessage string) error {
	return ArangoError{
		HasError:     true,
		Code:         code,
		ErrorNum:     errorNum,
		ErrorMessage: errorMessage,
	}
}

// IsArangoError returns true when the given error is an ArangoError.
func IsArangoError(err error) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.HasError
}

// IsArangoErrorWithCode returns true when the given error is an ArangoError and its Code field is equal to the given code.
func IsArangoErrorWithCode(err error, code int) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.Code == code
}

// IsArangoErrorWithErrorNum returns true when the given error is an ArangoError and its ErrorNum field is equal to one of the given numbers.
func IsArangoErrorWithErrorNum(err error, errorNum ...int) bool {
	ae, ok := Cause(err).(ArangoError)
	if !ok {
		return false
	}
	for _, x := range errorNum {
		if ae.ErrorNum == x {
			return true
		}
	}
	return false
}

// IsInvalidRequest returns true if the given error is an ArangoError with code 400, indicating an invalid request.
func IsInvalidRequest(err error) bool {
	return IsArangoErrorWithCode(err, 400)
}

// IsUnauthorized returns true if the given error is an ArangoError with code 401, indicating an unauthorized request.
func IsUnauthorized(err error) bool {
	return IsArangoErrorWithCode(err, 401)
}

// IsForbidden returns true if the given error is an ArangoError with code 403, indicating a forbidden request.
func IsForbidden(err error) bool {
	return IsArangoErrorWithCode(err, 403)
}

// IsNotFound returns true if the given error is an ArangoError with code 404, indicating a object not found.
func IsNotFound(err error) bool {
	return IsArangoErrorWithCode(err, 404) || IsArangoErrorWithErrorNum(err, 1202, 1203)
}

// IsConflict returns true if the given error is an ArangoError with code 409, indicating a conflict.
func IsConflict(err error) bool {
	return IsArangoErrorWithCode(err, 409) || IsArangoErrorWithErrorNum(err, 1702)
}

// IsPreconditionFailed returns true if the given error is an ArangoError with code 412, indicating a failed precondition.
func IsPreconditionFailed(err error) bool {
	return IsArangoErrorWithCode(err, 412) || IsArangoErrorWithErrorNum(err, 1200, 1210)
}

// InvalidArgumentError is returned when a go function argument is invalid.
type InvalidArgumentError struct {
	Message string
}

// Error implements the error interface for InvalidArgumentError.
func (e InvalidArgumentError) Error() string {
	return e.Message
}

// IsInvalidArgument returns true if the given error is an InvalidArgumentError.
func IsInvalidArgument(err error) bool {
	_, ok := Cause(err).(InvalidArgumentError)
	return ok
}

// NoMoreDocumentsError is returned by Cursor's, when an attempt is made to read documents when there are no more.
type NoMoreDocumentsError struct{}

// Error implements the error interface for NoMoreDocumentsError.
func (e NoMoreDocumentsError) Error() string {
	return "no more documents"
}

// IsNoMoreDocuments returns true if the given error is an NoMoreDocumentsError.
func IsNoMoreDocuments(err error) bool {
	_, ok := Cause(err).(NoMoreDocumentsError)
	return ok
}

// A ResponseError is returned when a request was completely written to a server, but
// the server did not respond, or some kind of network error occurred during the response.
type ResponseError struct {
	Err error
}

// Error returns the Error() result of the underlying error.
func (e *ResponseError) Error() string {
	return e.Err.Error()
}

// IsResponse returns true if the given error is (or is caused by) a ResponseError.
func IsResponse(err error) bool {
	return isCausedBy(err, func(e error) bool { _, ok := e.(*ResponseError); return ok })
}

// IsCanceled returns true if the given error is the result on a cancelled context.
func IsCanceled(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.Canceled })
}

// IsTimeout returns true if the given error is the result on a deadline that has been exceeded.
func IsTimeout(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.DeadlineExceeded })
}

// isCausedBy returns true if the given error returns true on the given predicate,
// unwrapping various standard library error wrappers.
func isCausedBy(err error, p func(error) bool) bool {
	if p(err) {
		return true
	}
	err = Cause(err)
	for {
		if p(err) {
			return true
		} else if err == nil {
			return false
		}
		if xerr, ok := err.(*ResponseError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*url.Error); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*net.OpError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*os.SyscallError); ok {
			err = xerr.Err
		} else {
			return false
		}
	}
}

var (
	// WithStack is called on every return of an error to add stacktrace information to the error.
	// When setting this function, also set the Cause function.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	WithStack = func(err error) error { return err }
	// Cause is used to get the root cause of the given error.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	Cause = func(err error) error { return err }
)

// ErrorSlice is a slice of errors
type ErrorSlice []error

// FirstNonNil returns the first error in the slice that is not nil.
// If all errors in the slice are nil, nil is returned.
func (l ErrorSlice) FirstNonNil() error {
	for _, e := range l {
		if e != nil {
			return e
		}
	}
	return nil
}
<commit_msg>Adding technical error message when `ErrorMessage` is empty<commit_after>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"fmt"
	"net"
	"net/url"
	"os"
)

// ArangoError is a Go error with arangodb specific error information.
type ArangoError struct {
	HasError     bool   `json:"error"`
	Code         int    `json:"code"`
	ErrorNum     int    `json:"errorNum"`
	ErrorMessage string `json:"errorMessage"`
}

// Error returns the error message of an ArangoError.
func (ae ArangoError) Error() string {
	if ae.ErrorMessage != "" {
		return ae.ErrorMessage
	}
	return fmt.Sprintf("ArangoError: Code %d, ErrorNum %d", ae.Code, ae.ErrorNum)
}

// newArangoError creates a new ArangoError with given values.
func newArangoError(code, errorNum int, errorMessage string) error {
	return ArangoError{
		HasError:     true,
		Code:         code,
		ErrorNum:     errorNum,
		ErrorMessage: errorMessage,
	}
}

// IsArangoError returns true when the given error is an ArangoError.
func IsArangoError(err error) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.HasError
}

// IsArangoErrorWithCode returns true when the given error is an ArangoError and its Code field is equal to the given code.
func IsArangoErrorWithCode(err error, code int) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.Code == code
}

// IsArangoErrorWithErrorNum returns true when the given error is an ArangoError and its ErrorNum field is equal to one of the given numbers.
func IsArangoErrorWithErrorNum(err error, errorNum ...int) bool {
	ae, ok := Cause(err).(ArangoError)
	if !ok {
		return false
	}
	for _, x := range errorNum {
		if ae.ErrorNum == x {
			return true
		}
	}
	return false
}

// IsInvalidRequest returns true if the given error is an ArangoError with code 400, indicating an invalid request.
func IsInvalidRequest(err error) bool {
	return IsArangoErrorWithCode(err, 400)
}

// IsUnauthorized returns true if the given error is an ArangoError with code 401, indicating an unauthorized request.
func IsUnauthorized(err error) bool {
	return IsArangoErrorWithCode(err, 401)
}

// IsForbidden returns true if the given error is an ArangoError with code 403, indicating a forbidden request.
func IsForbidden(err error) bool {
	return IsArangoErrorWithCode(err, 403)
}

// IsNotFound returns true if the given error is an ArangoError with code 404, indicating a object not found.
func IsNotFound(err error) bool {
	return IsArangoErrorWithCode(err, 404) || IsArangoErrorWithErrorNum(err, 1202, 1203)
}

// IsConflict returns true if the given error is an ArangoError with code 409, indicating a conflict.
func IsConflict(err error) bool {
	return IsArangoErrorWithCode(err, 409) || IsArangoErrorWithErrorNum(err, 1702)
}

// IsPreconditionFailed returns true if the given error is an ArangoError with code 412, indicating a failed precondition.
func IsPreconditionFailed(err error) bool {
	return IsArangoErrorWithCode(err, 412) || IsArangoErrorWithErrorNum(err, 1200, 1210)
}

// InvalidArgumentError is returned when a go function argument is invalid.
type InvalidArgumentError struct {
	Message string
}

// Error implements the error interface for InvalidArgumentError.
func (e InvalidArgumentError) Error() string {
	return e.Message
}

// IsInvalidArgument returns true if the given error is an InvalidArgumentError.
func IsInvalidArgument(err error) bool {
	_, ok := Cause(err).(InvalidArgumentError)
	return ok
}

// NoMoreDocumentsError is returned by Cursor's, when an attempt is made to read documents when there are no more.
type NoMoreDocumentsError struct{}

// Error implements the error interface for NoMoreDocumentsError.
func (e NoMoreDocumentsError) Error() string {
	return "no more documents"
}

// IsNoMoreDocuments returns true if the given error is an NoMoreDocumentsError.
func IsNoMoreDocuments(err error) bool {
	_, ok := Cause(err).(NoMoreDocumentsError)
	return ok
}

// A ResponseError is returned when a request was completely written to a server, but
// the server did not respond, or some kind of network error occurred during the response.
type ResponseError struct {
	Err error
}

// Error returns the Error() result of the underlying error.
func (e *ResponseError) Error() string {
	return e.Err.Error()
}

// IsResponse returns true if the given error is (or is caused by) a ResponseError.
func IsResponse(err error) bool {
	return isCausedBy(err, func(e error) bool { _, ok := e.(*ResponseError); return ok })
}

// IsCanceled returns true if the given error is the result on a cancelled context.
func IsCanceled(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.Canceled })
}

// IsTimeout returns true if the given error is the result on a deadline that has been exceeded.
func IsTimeout(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.DeadlineExceeded })
}

// isCausedBy returns true if the given error returns true on the given predicate,
// unwrapping various standard library error wrappers.
func isCausedBy(err error, p func(error) bool) bool {
	if p(err) {
		return true
	}
	err = Cause(err)
	for {
		if p(err) {
			return true
		} else if err == nil {
			return false
		}
		if xerr, ok := err.(*ResponseError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*url.Error); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*net.OpError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*os.SyscallError); ok {
			err = xerr.Err
		} else {
			return false
		}
	}
}

var (
	// WithStack is called on every return of an error to add stacktrace information to the error.
	// When setting this function, also set the Cause function.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	WithStack = func(err error) error { return err }
	// Cause is used to get the root cause of the given error.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	Cause = func(err error) error { return err }
)

// ErrorSlice is a slice of errors
type ErrorSlice []error

// FirstNonNil returns the first error in the slice that is not nil.
// If all errors in the slice are nil, nil is returned.
func (l ErrorSlice) FirstNonNil() error {
	for _, e := range l {
		if e != nil {
			return e
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package cask

import (
	"bytes"
	"fmt"
)

// Errors represents a group of errors and its context.
type Errors struct {
	// context specifies the errors context.
	context string

	// errors specify a group of errors represented as an array.
	errors []error
}

// An unexpectedTokenError represents the error that occurs when an the expected
// tokens doesn't match the actual ones.
type unexpectedTokenError struct {
	// expectedTokens specify a group of expected token types.
	expectedTokens []TokenType

	// actualToken specifies the actual token type.
	actualToken TokenType
}

// NewErrors creates a new Errors instance and returns its pointer. Requires
// both Errors.context and Errors.errors to be passed as arguments.
func NewErrors(context string, errors ...error) *Errors {
	return &Errors{context, errors}
}

// Error returns all error messages represented as a single string. All errors
// include trailing newlines and prepended context.
func (e *Errors) Error() string {
	var buffer bytes.Buffer

	fmt.Fprintf(&buffer, "%s:\n", e.context)
	for _, err := range e.errors {
		fmt.Fprintf(&buffer, "%s\n", err.Error())
	}

	return buffer.String()
}

// Error returns a string representation of the unexpectedTokenError.
func (u *unexpectedTokenError) Error() string {
	return fmt.Sprintf(
		"expected next token to be of type %s, got %s instead",
		u.expectedTokens,
		u.actualToken,
	)
}
<commit_msg>Use "%v" in unexpectedTokenError.Error()<commit_after>package cask

import (
	"bytes"
	"fmt"
)

// Errors represents a group of errors and its context.
type Errors struct {
	// context specifies the errors context.
	context string

	// errors specify a group of errors represented as an array.
	errors []error
}

// An unexpectedTokenError represents the error that occurs when an the expected
// tokens doesn't match the actual ones.
type unexpectedTokenError struct {
	// expectedTokens specify a group of expected token types.
	expectedTokens []TokenType

	// actualToken specifies the actual token type.
	actualToken TokenType
}

// NewErrors creates a new Errors instance and returns its pointer. Requires
// both Errors.context and Errors.errors to be passed as arguments.
func NewErrors(context string, errors ...error) *Errors {
	return &Errors{context, errors}
}

// Error returns all error messages represented as a single string. All errors
// include trailing newlines and prepended context.
func (e *Errors) Error() string {
	var buffer bytes.Buffer

	fmt.Fprintf(&buffer, "%s:\n", e.context)
	for _, err := range e.errors {
		fmt.Fprintf(&buffer, "%s\n", err.Error())
	}

	return buffer.String()
}

// Error returns a string representation of the unexpectedTokenError.
func (u *unexpectedTokenError) Error() string {
	return fmt.Sprintf(
		"expected next token to be of type %v, got %s instead",
		u.expectedTokens,
		u.actualToken,
	)
}
<|endoftext|>