<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

const (
	elasticHost     = "elk-102.ix.km"
	clusterStatusOk = "green"
	excludeFile     = "./elastic_exlude.txt"
)

type myCluster struct {
	Status string `json:"status"`
}

type myConfig struct {
	ExcludedFileNames []string
}

// type myIndicies struct {
// 	indices map[string]map[string]string `json: indices`
// }

var (
	cluster myCluster
	config  myConfig
	f       interface{}
)

func main() {
	bytes, err := ioutil.ReadFile(excludeFile)
	if err != nil {
		log.Fatalln(err)
	}
	err = json.Unmarshal(bytes, &config)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	if len(config.ExcludedFileNames) == 0 {
		log.Fatalln("Exclude file is empty")
	}

	ClusterStatusUrl := fmt.Sprint("http://" + elasticHost + ":9200/_cluster/health?pretty")
	resp, err := http.Get(ClusterStatusUrl)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Response status: %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Couldn't read data: %v", body)
	}
	err = json.Unmarshal(body, &cluster)
	if err != nil {
		log.Fatalf("error: %s", err)
	}
	if cluster.Status != clusterStatusOk {
		log.Fatalf("Cluster status is: %s!!! Do nothing ", cluster.Status)
	}

	ClusterIndicesUrl := fmt.Sprint("http://" + elasticHost + ":9200/_stats?pretty")
	resp, err = http.Get(ClusterIndicesUrl)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Response status: %v", resp.Status)
	}
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Couldn't read data: %v", body)
	}
	fmt.Println(string(body))

	err = json.Unmarshal(body, &f)
	if err != nil {
		log.Fatalf("error:", err)
	}
	fmt.Println(f)
}
<commit_msg>Changed url<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

const (
	elasticHost     = "elk-102.ix.km"
	clusterStatusOk = "green"
	excludeFile     = "./elastic_exlude.txt"
)

type myCluster struct {
	Status string `json:"status"`
}

type myConfig struct {
	ExcludedFileNames []string
}

type myIndices struct {
	Indices map[string]interface{}
}

var (
	cluster myCluster
	config  myConfig
	parsed  map[string]interface{}
	a       []string
	indices []string

//	f       interface{}
)

func main() {
	bytes, err := ioutil.ReadFile(excludeFile)
	if err != nil {
		log.Fatalln(err)
	}
	err = json.Unmarshal(bytes, &config)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	if len(config.ExcludedFileNames) == 0 {
		log.Fatalln("Exclude file is empty")
	}

	ClusterStatusUrl := fmt.Sprint("http://" + elasticHost + ":9200/_cluster/health?pretty")
	resp, err := http.Get(ClusterStatusUrl)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Response status: %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Couldn't read data: %v", body)
	}
	err = json.Unmarshal(body, &cluster)
	if err != nil {
		log.Fatalf("error: %s", err)
	}
	if cluster.Status != clusterStatusOk {
		log.Fatalf("Cluster status is: %s!!! Do nothing ", cluster.Status)
	}

	ClusterIndicesUrl := fmt.Sprint("http://" + elasticHost + ":9200/_cat/indices")
	resp, err = http.Get(ClusterIndicesUrl)
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Response status: %v", resp.Status)
	}
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Couldn't read data: %v", body)
	}
	fmt.Println(string(body))

	s := string(body)
	tmp := strings.Split(s, "\n")
	fmt.Println(tmp)
	//a:=[]string

	for i := 0; i < len(tmp)-1; i++ {
		a = strings.Split(tmp[i], " ")
		indices[i] = a[1]
	}
	//fmt.Println(a)
	// f := myIndices{}
	// err = json.Unmarshal(body, &f)
	// if err != nil {
	// 	log.Fatalf("error:", err)
	// }
	// fmt.Println(f)

}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net/http"
	"strings"
)

type Port struct {
}

func (_ *Port) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	port := strings.Split(r.Host,":")[1]

	w.Write([]byte(fmt.Sprintf("%s", port)))
}
<commit_msg>/ports handles case when port is not available<commit_after>package handlers

import (
	"fmt"
	"net/http"
	"strings"
)

type Port struct {
}

func (_ *Port) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ports := strings.Split(r.Host,":")
	if len(ports) < 2 {
		w.Write([]byte(fmt.Sprintf("0")))
		return
	}

	w.Write([]byte(fmt.Sprintf("%s", ports[1])))
}
<|endoftext|>


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

package schema

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/pkg/errors"
	"github.com/xeipuuv/gojsonschema"
)

// Validator wraps a media type string identifier
// and implements validation against a JSON schema.
type Validator string

// ValidationError contains all the errors that happened during validation.
type ValidationError struct {
	Errs []error
}

func (e ValidationError) Error() string {
	return fmt.Sprintf("%v", e.Errs)
}

// Validate validates the given reader against the schema of the wrapped media type.
func (v Validator) Validate(src io.Reader) error {
	buf, err := ioutil.ReadAll(src)
	if err != nil {
		return errors.Wrap(err, "unable to read the document file")
	}

	sl := gojsonschema.NewReferenceLoaderFileSystem("file:///"+specs[v], fs)
	ml := gojsonschema.NewStringLoader(string(buf))

	result, err := gojsonschema.Validate(sl, ml)
	if err != nil {
		return errors.Wrapf(
			WrapSyntaxError(bytes.NewReader(buf), err),
			"schema %s: unable to validate", v)
	}

	if result.Valid() {
		return nil
	}

	errs := make([]error, 0, len(result.Errors()))
	for _, desc := range result.Errors() {
		errs = append(errs, fmt.Errorf("%s", desc))
	}

	return ValidationError{
		Errs: errs,
	}
}

type unimplemented string

func (v unimplemented) Validate(src io.Reader) error {
	return fmt.Errorf("%s: unimplemented", v)
}
<commit_msg>validate media type of manifest descendants<commit_after>// Copyright 2016 The Linux Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package schema

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"github.com/xeipuuv/gojsonschema"
)

// Validator wraps a media type string identifier
// and implements validation against a JSON schema.
type Validator string

type validateDescendantsFunc func(r io.Reader) error

var mapValidateDescendants = map[Validator]validateDescendantsFunc{
	MediaTypeManifest: validateManifestDescendants,
}

// ValidationError contains all the errors that happened during validation.
type ValidationError struct {
	Errs []error
}

func (e ValidationError) Error() string {
	return fmt.Sprintf("%v", e.Errs)
}

// Validate validates the given reader against the schema of the wrapped media type.
func (v Validator) Validate(src io.Reader) error {
	buf, err := ioutil.ReadAll(src)
	if err != nil {
		return errors.Wrap(err, "unable to read the document file")
	}

	if f, ok := mapValidateDescendants[v]; ok {
		if f == nil {
			return fmt.Errorf("internal error: mapValidateDescendents[%q] is nil", v)
		}
		err = f(bytes.NewReader(buf))
		if err != nil {
			return err
		}
	}

	sl := gojsonschema.NewReferenceLoaderFileSystem("file:///"+specs[v], fs)
	ml := gojsonschema.NewStringLoader(string(buf))

	result, err := gojsonschema.Validate(sl, ml)
	if err != nil {
		return errors.Wrapf(
			WrapSyntaxError(bytes.NewReader(buf), err),
			"schema %s: unable to validate", v)
	}

	if result.Valid() {
		return nil
	}

	errs := make([]error, 0, len(result.Errors()))
	for _, desc := range result.Errors() {
		errs = append(errs, fmt.Errorf("%s", desc))
	}

	return ValidationError{
		Errs: errs,
	}
}

type unimplemented string

func (v unimplemented) Validate(src io.Reader) error {
	return fmt.Errorf("%s: unimplemented", v)
}

func validateManifestDescendants(r io.Reader) error {
	header := v1.Manifest{}

	buf, err := ioutil.ReadAll(r)
	if err != nil {
		return errors.Wrapf(err, "error reading the io stream")
	}

	err = json.Unmarshal(buf, &header)
	if err != nil {
		return errors.Wrap(err, "manifest format mismatch")
	}

	if header.Config.MediaType != string(v1.MediaTypeImageConfig) {
		fmt.Printf("warning: config %s has an unknown media type: %s\n", header.Config.Digest, header.Config.MediaType)
	}

	for _, layer := range header.Layers {
		if layer.MediaType != string(v1.MediaTypeImageLayer) &&
			layer.MediaType != string(v1.MediaTypeImageLayerNonDistributable) {
			fmt.Printf("warning: layer %s has an unknown media type: %s\n", layer.Digest, layer.MediaType)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package screenshot

import (
	"image"
	"errors"
)

// Capture screen.
// x and y represent distance from the upper-left corner of main display.
// Y-axis is downward direction. This means coordinates system is similar to Windows OS.
func Capture(x, y, width, height int) (*image.RGBA, error) {
	return nil, errors.New("screenshot.Capture not supported for linux")
}

// Get the number of active displays.
func NumActiveDisplays() int {
	return 0
}

// Get the bounds of displayIndex'th display.
// The main display is displayIndex = 0.
func GetDisplayBounds(displayIndex int) image.Rectangle {
	return image.ZR
}
<commit_msg>Support linux<commit_after>package screenshot

import (
	"image"
	"image/color"
	"github.com/BurntSushi/xgb"
	"github.com/BurntSushi/xgb/xproto"
	"github.com/BurntSushi/xgb/xinerama"
)

// Capture screen.
// x and y represent distance from the upper-left corner of main display.
// Y-axis is downward direction. This means coordinates system is similar to Windows OS.
func Capture(x, y, width, height int) (*image.RGBA, error) {
	c, err := xgb.NewConn()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	err = xinerama.Init(c)
	reply, err := xinerama.QueryScreens(c).Reply()
	if err != nil {
		return nil, err
	}

	primary := reply.ScreenInfo[0]
	x0 := int(primary.XOrg)
	y0 := int(primary.YOrg)

	screen := xproto.Setup(c).DefaultScreen(c)
	wholeScreenBounds := image.Rect(0, 0, int(screen.WidthInPixels), int(screen.HeightInPixels))
	targetBounds := image.Rect(x + x0, y + y0, x + x0 + width, y + y0 + height)
	intersect := wholeScreenBounds.Intersect(targetBounds)

	rect := image.Rect(0, 0, width, height)
	img := image.NewRGBA(rect)

	// Paint with opaque black
	index := 0
	for iy := 0; iy < height; iy++ {
		j := index
		for ix := 0; ix < width; ix++ {
			img.Pix[j + 3] = 255
			j += 4
		}
		index += img.Stride
	}

	if !intersect.Empty() {
		xImg, err := xproto.GetImage(c, xproto.ImageFormatZPixmap, xproto.Drawable(screen.Root),
					     int16(intersect.Min.X), int16(intersect.Min.Y),
					     uint16(intersect.Dx()), uint16(intersect.Dy()), 0xffffffff).Reply()
		if err != nil {
			return nil, err
		}

		// BitBlt by hand
		offset := 0
		for iy := intersect.Min.Y; iy < intersect.Max.Y; iy++ {
			for ix := intersect.Min.X; ix < intersect.Max.X; ix++ {
				r := xImg.Data[offset + 2]
				g := xImg.Data[offset + 1]
				b := xImg.Data[offset]
				img.SetRGBA(ix - (x + x0), iy - (y + y0), color.RGBA{r, g, b, 255})
				offset += 4
			}
		}
	}

	return img, nil
}

// Get the number of active displays.
func NumActiveDisplays() int {
	c, err := xgb.NewConn()
	if err != nil {
		return 0
	}
	defer c.Close()

	err = xinerama.Init(c)
	if err != nil {
		return 0
	}

	reply, err := xinerama.QueryScreens(c).Reply()
	if err != nil {
		return 0
	}

	return int(reply.Number)
}

// Get the bounds of displayIndex'th display.
// The main display is displayIndex = 0.
func GetDisplayBounds(displayIndex int) image.Rectangle {
	c, err := xgb.NewConn()
	if err != nil {
		return image.ZR
	}
	defer c.Close()

	err = xinerama.Init(c)

	reply, err := xinerama.QueryScreens(c).Reply()
	if err != nil {
		return image.ZR
	}

	if displayIndex >= int(reply.Number) {
		return image.ZR
	}

	primary := reply.ScreenInfo[0]
	x0 := int(primary.XOrg)
	y0 := int(primary.YOrg)

	screen := reply.ScreenInfo[displayIndex]
	x := int(screen.XOrg) - x0
	y := int(screen.YOrg) - y0
	w := int(screen.Width)
	h := int(screen.Height)
	return image.Rect(x, y, x + w, y + h)
}
<|endoftext|>


<commit_before>package main

import "bufio"
import "fmt"
import "math/rand"
import "net"
import "time"
import "sync"

type CacheItem struct {
    key string
    value string
}

// constants and configuration
// No constant arrays
var letters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
const verbose = false
const numThreads = 10

// 3-character keys with 26 possibilities =     17,576 keys
// 4-character keys with 26 possibilities =    456,976 keys
// 5-character keys with 26 possibilities = 11,881,376 keys
const keyLength = 4
//const numKeys = 1000000
const numKeys = 100000

// concurrency bits
var wg sync.WaitGroup
var tasks chan *CacheItem

func main() {

    rand.Seed(time.Now().UTC().UnixNano())
    tasks = make(chan *CacheItem, 64)

    // spawn worker goroutines
    for i := 0; i < numThreads; i++ {
        wg.Add(1)
        go worker(connect("localhost"))
    }

    key := ""
    value := ""
    valLen := 0

    for i := 0; i < numKeys; i++ {
        key = randString(keyLength)

        // Random length between 1k and 10k
        valLen = rand.Intn(9 * 1024) + 1024
        value = randString(valLen)

        item := new(CacheItem)
        item.key = key
        item.value = value

        tasks <- item

        if i % 10000 == 0 {
            fmt.Printf("%v\r\n", i)
        }
    }

    close(tasks)
    wg.Wait()
}

func worker(conn net.Conn) {
    for item := range tasks {
        set(conn, item.key, item.value)
        get(conn, item.key)
    }

    wg.Done()
}

func randString(n int) string {
    b := make([]rune, n)

    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }

    return string(b)
}

func connect(host string) net.Conn {
    conn, err := net.Dial("tcp", host + ":11212")

    if err != nil {
        panic(err)
    }

    println("Connected to memcached.")

    return conn
}

func set(conn net.Conn, key string, value string) {
    if verbose { println(fmt.Sprintf("Setting key %v to value of length %v", key, len(value))) }

    fmt.Fprintf(conn, "set %v 0 0 %v\r\n", key, len(value))
    fmt.Fprintf(conn, "%v\r\n", value)
    response, err := bufio.NewReader(conn).ReadString('\n')

    if err != nil { panic(err) }

    if verbose { print(response) }
}

func get(conn net.Conn, key string) {
    if verbose { println(fmt.Sprintf("Getting key %v", key)) }

    fmt.Fprintf(conn, "get %v\r\n", key)

    reader := bufio.NewReader(conn)

    // read the header line
    response, err := reader.ReadString('\n')

    if err != nil { panic(err) }

    if verbose { print(response) }

    // then read the value
    response, err = reader.ReadString('\n')

    if err != nil { panic(err) }

    //print(response)
    if verbose { println("(read the value)") }

    // then read the END
    response, err = reader.ReadString('\n')

    if err != nil { panic(err) }

    if verbose { print(response) }
}
<commit_msg>Much better set/get test. Uses a constant string and slices instead of a new random one every time. Also uses common bits.<commit_after>package main

import "bufio"
import "fmt"
import "math/rand"
import "net"
import "time"
import "sync"

import "./rend"

type CacheItem struct {
    key string
    value string
}

// constants and configuration
const verbose = true
const numWorkers = 10

// 2-character keys with 26 possibilities =        676 keys
// 3-character keys with 26 possibilities =     17,576 keys
// 4-character keys with 26 possibilities =    456,976 keys
// 5-character keys with 26 possibilities = 11,881,376 keys
const keyLength = 4
const numKeys = 100000

func main() {

    rand.Seed(time.Now().UTC().UnixNano())
    tasks := make(chan *CacheItem)
    wg := new(sync.WaitGroup)
    wg.Add(numWorkers)

    // spawn worker goroutines
    for i := 0; i < numWorkers; i++ {
        go worker(rend.Connect("localhost"), tasks, wg)
    }

    source := rend.RandString(10240)

    for i := 0; i < numKeys; i++ {
        // Random length between 1k and 10k
        valLen := rand.Intn(9 * 1024) + 1024

        item := new(CacheItem)
        item.key = rend.RandString(keyLength)
        item.value = source[:valLen]
        tasks <- item

        if i % 10000 == 0 {
            fmt.Printf("%v\r\n", i)
        }
    }

    close(tasks)
    wg.Wait()
}

func worker(conn net.Conn, tasks chan *CacheItem, wg *sync.WaitGroup) {
    reader := bufio.NewReader(conn)
    writer := bufio.NewWriter(conn)

    for item := range tasks {
        rend.Set(reader, writer, item.key, item.value)
        rend.Get(reader, writer, item.key)
    }

    wg.Done()
}
<|endoftext|>


<commit_before>package gerrit_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/andygrunwald/go-gerrit"
)

func newClient(t *testing.T, server *httptest.Server) *gerrit.Client {
	client, err := gerrit.NewClient(server.URL, nil)
	if err != nil {
		t.Error(err)
	}
	return client
}

func TestChangesService_ListReviewers(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `[{"_account_id": 1}]`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.ListReviewers("123")
	if err != nil {
		t.Error(err)
	}

	if len(*data) != 1 {
		t.Error()
	}

	if (*data)[0].AccountID != 1 {
		t.Error()
	}
}

func TestChangesService_SuggestReviewers(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/suggest_reviewers"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `[{"account": {"_account_id": 1}}]`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.SuggestReviewers("123", nil)
	if err != nil {
		t.Error(err)
	}

	if len(*data) != 1 {
		t.Error()
	}

	if (*data)[0].Account.AccountID != 1 {
		t.Error()
	}
}

func TestChangesService_GetReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `{"_account_id": 1}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.GetReviewer("123", "1")
	if err != nil {
		t.Error(err)
	}
	if data.AccountID != 1 {
		t.Error()
	}
}

func TestChangesService_AddReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		if r.Method != "POST" {
			t.Error()
		}

		fmt.Fprint(w, `{"confirm": true}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.AddReviewer("123", &gerrit.ReviewerInput{})
	if err != nil {
		t.Error(err)
	}
	if !data.Confirm {
		t.Error()
	}
}

func TestChangesService_DeleteReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		if r.Method != "DELETE" {
			t.Error()
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	_, err := client.Changes.DeleteReviewer("123", "1")
	if err != nil {
		t.Error(err)
	}
}

func TestChangesService_ListVotes(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1/votes/"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		fmt.Fprint(w, `{"Code-Review": 2, "Verified": 1}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	votes, _, err := client.Changes.ListVotes("123", "1")
	if err != nil {
		t.Error(err)
	}
	if votes["Code-Review"] != 2 {
		t.Error()
	}
	if votes["Verified"] != 1 {
		t.Error()
	}
}

func TestChangesService_DeleteVote(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1/votes/Code-Review"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		if r.Method != "DELETE" {
			t.Error()
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	_, err := client.Changes.DeleteVote("123", "1", "Code-Review", nil)
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>Go 1.6 requires arguments<commit_after>package gerrit_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/andygrunwald/go-gerrit"
)

func newClient(t *testing.T, server *httptest.Server) *gerrit.Client {
	client, err := gerrit.NewClient(server.URL, nil)
	if err != nil {
		t.Error(err)
	}
	return client
}

func TestChangesService_ListReviewers(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `[{"_account_id": 1}]`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.ListReviewers("123")
	if err != nil {
		t.Error(err)
	}

	if len(*data) != 1 {
		t.Error("Length of data !=1 ")
	}

	if (*data)[0].AccountID != 1 {
		t.Error("AccountID != 1")
	}
}

func TestChangesService_SuggestReviewers(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/suggest_reviewers"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `[{"account": {"_account_id": 1}}]`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.SuggestReviewers("123", nil)
	if err != nil {
		t.Error(err)
	}

	if len(*data) != 1 {
		t.Error("Length of data !=1 ")
	}

	if (*data)[0].Account.AccountID != 1 {
		t.Error("AccountID != 1")
	}
}

func TestChangesService_GetReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		fmt.Fprint(w, `{"_account_id": 1}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.GetReviewer("123", "1")
	if err != nil {
		t.Error(err)
	}
	if data.AccountID != 1 {
		t.Error("AccountID != 1")
	}
}

func TestChangesService_AddReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		if r.Method != "POST" {
			t.Error("Method != POST")
		}

		fmt.Fprint(w, `{"confirm": true}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	data, _, err := client.Changes.AddReviewer("123", &gerrit.ReviewerInput{})
	if err != nil {
		t.Error(err)
	}
	if !data.Confirm {
		t.Error("Confirm != true")
	}
}

func TestChangesService_DeleteReviewer(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		if r.Method != "DELETE" {
			t.Error("Method != DELETE")
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	_, err := client.Changes.DeleteReviewer("123", "1")
	if err != nil {
		t.Error(err)
	}
}

func TestChangesService_ListVotes(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1/votes/"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}
		fmt.Fprint(w, `{"Code-Review": 2, "Verified": 1}`)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	votes, _, err := client.Changes.ListVotes("123", "1")
	if err != nil {
		t.Error(err)
	}
	if votes["Code-Review"] != 2 {
		t.Error("Code-Review != 2")
	}
	if votes["Verified"] != 1 {
		t.Error("Verified != 1")
	}
}

func TestChangesService_DeleteVote(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expected := "/changes/123/reviewers/1/votes/Code-Review"
		if r.URL.Path != expected {
			t.Errorf("%s != %s", r.URL.Path, expected)
		}

		if r.Method != "DELETE" {
			t.Error("Method != DELETE")
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer ts.Close()

	client := newClient(t, ts)
	_, err := client.Changes.DeleteVote("123", "1", "Code-Review", nil)
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/ropes/anagrams"
	"github.com/ropes/sheave/bot"
	"github.com/ropes/sheave/history"
	"github.com/ropes/sheave/parse"
)

func bootBot() {
	words, err := anagrams.ReadSystemWords()
	if err != nil {
		fmt.Println("No error reading word list")
	}
	anagrammap := anagrams.AnagramList(words)
	bot.AM = &anagrams.AnagramMap{Mapping: anagrammap}

	bot.ChannelHistory = make(map[string]*history.HistoryHeap)

	ircconfig := parse.ParseConfig("/home/ropes/.config/sheave.conf")
	bot.IRCConnect(ircconfig)
}

func main() {
	bootBot()
}
<commit_msg>Added flag to set config path for  sheave<commit_after>package main

import (
	"flag"
	"fmt"
	"log"

	"github.com/ropes/anagrams"
	"github.com/ropes/sheave/bot"
	"github.com/ropes/sheave/history"
	"github.com/ropes/sheave/parse"
)

func bootBot() {
	words, err := anagrams.ReadSystemWords()
	if err != nil {
		fmt.Println("No error reading word list")
	}
	anagrammap := anagrams.AnagramList(words)
	bot.AM = &anagrams.AnagramMap{Mapping: anagrammap}

	bot.ChannelHistory = make(map[string]*history.HistoryHeap)

	confPath := flag.String("confPath",
		"/home/ropes/.config/sheave.conf",
		"Path to config file for Sheave bot.")
	flag.Parse()

	ircconfig := parse.ParseConfig(*confPath)
	if ircconfig.UserName == "" || ircconfig.Passwd == "" {
		log.Fatal("IRC Config failed to parse important information.")
	}
	fmt.Printf("%#v\n", ircconfig)
	bot.IRCConnect(ircconfig)
}

func main() {
	bootBot()
}
<|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 noops

import (
	"fmt"

	"github.com/golang/protobuf/proto"
	"github.com/op/go-logging"

	"github.com/openblockchain/obc-peer/openchain/consensus"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/openchain/util"
	pb "github.com/openblockchain/obc-peer/protos"
)

// =============================================================================
// Init
// =============================================================================

var logger *logging.Logger // package-level logger

func init() {
	logger = logging.MustGetLogger("consensus/noops")
}

// =============================================================================
// Structures go here
// =============================================================================

// Noops is a plugin object implementing the consensus.Consenter interface.
type Noops struct {
	cpi consensus.CPI
	txQ *util.Queue
}

var iNoops consensus.Consenter

// =============================================================================
// Constructors go here
// =============================================================================

// NewNoops is a constructor returning a consensus.Consenter object.
func NewNoops(c consensus.CPI) consensus.Consenter {
	logger.Debug("Creating a NOOPS object")
	i := &Noops{}
	i.cpi = c
	i.txQ = util.NewQueue()
	return i
}

// GetNoops returns a singleton of NOOPS
func GetNoops(c consensus.CPI) consensus.Consenter {
	if iNoops == nil {
		iNoops = NewNoops(c)
	}
	return iNoops
}

// RecvMsg is called for OpenchainMessage_CHAIN_TRANSACTION and OpenchainMessage_CONSENSUS messages.
func (i *Noops) RecvMsg(msg *pb.OpenchainMessage) error {
	logger.Debug("Handling OpenchainMessage of type: %s ", msg.Type)

	if msg.Type == pb.OpenchainMessage_CHAIN_TRANSACTION {
		if err := i.broadcastConsensusMsg(msg); nil != err {
			return err
		}
	}
	if msg.Type == pb.OpenchainMessage_CONSENSUS {
		txarr, err := i.getTransactionsFromMsg(msg)
		if nil != err {
			return err
		}
		if i.canProcess(txarr) {
			i.txQ.Push(txarr)
			if err=i.doTransactions(msg); err == nil {
				//transactions succeeed, broadcast
				//spin the broadcast in go routine so
				//(a)we make RecvMsg light and
				//(b)we separate send from receive
				go i.notifyBlockAdded()
			}
			return err
		}
		i.queueTransactions(txarr)
	}
	return nil
}

func (i *Noops) broadcastConsensusMsg(msg *pb.OpenchainMessage) error {
	t := &pb.Transaction{}
	if err := proto.Unmarshal(msg.Payload, t); err != nil {
		return fmt.Errorf("Error unmarshalling payload of received OpenchainMessage:%s.", msg.Type)
	}

	// Change the msg type to consensus and broadcast to the network so that
	// other validators may execute the transaction
	msg.Type = pb.OpenchainMessage_CONSENSUS
	logger.Debug("Broadcasting %s", msg.Type)
	txs := &pb.TransactionBlock{Transactions: []*pb.Transaction{t}}
	payload, err := proto.Marshal(txs)
	if err != nil {
		return err
	}
	msg.Payload = payload
	if errs := i.cpi.Broadcast(msg, pb.PeerEndpoint_UNDEFINED); nil != errs {
		return fmt.Errorf("Failed to broadcast with errors: %v", errs)
	}
	return nil
}

func (i *Noops) getTransactionsFromMsg(msg *pb.OpenchainMessage) ([]*pb.Transaction, error) {
	txs := &pb.TransactionBlock{}
	if err := proto.Unmarshal(msg.Payload, txs); err != nil {
		return nil, err
	}
	return txs.GetTransactions(), nil
}

func (i *Noops) getTransactionsFromQueue() []*pb.Transaction {
	len := i.txQ.Size()
	if len == 1 {
		return i.txQ.Pop().([]*pb.Transaction)
	}
	txarr := make([]*pb.Transaction, len)
	for k := 0; k < len; k++ {
		txs := i.txQ.Pop().([]*pb.Transaction)
		txarr[k] = txs[0]
	}
	return txarr
}

func (i *Noops) canProcess(txarr []*pb.Transaction) bool {
	// For NOOPS, if we have completed the sync since we last connected,
	// we can assume that we are at the current state; otherwise, we need to
	// wait for the sync process to complete before we can exec the transactions

	// TODO: Ask coordinator if we need to start sync

	return true
}

func (i *Noops) doTransactions(msg *pb.OpenchainMessage) error {
	logger.Debug("Executing transactions")
	logger.Debug("Starting TX batch with timestamp: %v", msg.Timestamp)
	if err := i.cpi.BeginTxBatch(msg.Timestamp); err != nil {
		return err
	}

	// Grab all transactions from the FIFO queue and run them in order
	txarr := i.getTransactionsFromQueue()
	logger.Debug("Executing batch of %d transactions", len(txarr))
	_, errs := i.cpi.ExecTXs(txarr)

	//there are n+1 elements of errors in this array. On complete success
	//they'll all be nil. In particular, the last err will be error in
	//producing the hash, if any. That's the only error we do want to check
	if errs[len(txarr)] != nil {
		logger.Debug("Rolling back TX batch with timestamp: %v", msg.Timestamp)
		i.cpi.RollbackTxBatch(msg.Timestamp)
		return fmt.Errorf("Fail to execute transactions: %v", errs)
	}

	logger.Debug("Committing TX batch with timestamp: %v", msg.Timestamp)
	if err := i.cpi.CommitTxBatch(msg.Timestamp, txarr, nil, nil); err != nil {
		logger.Debug("Rolling back TX batch with timestamp: %v", msg.Timestamp)
		i.cpi.RollbackTxBatch(msg.Timestamp)
		return err
	}

	return nil
}

func (i *Noops) notifyBlockAdded() error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}

	// TODO: Broadcast SYNC_BLOCK_ADDED to connected NVPs
	// VPs already know about this newly added block since they participate
	// in the execution. That is, they can compare their current block with
	// the network block
	// For now, send to everyone until broadcast has better discrimination
	blockHeight := ledger.GetBlockchainSize()
	logger.Debug("Preparing to broadcast with block number %v", blockHeight)
	block, err := ledger.GetBlockByNumber(blockHeight - 1)
	if nil != err {
		return err
	}
	//delta, err := ledger.GetStateDeltaBytes(blockHeight)
	delta, err := ledger.GetStateDelta(blockHeight - 1)
	if nil != err {
		return err
	}

	//make Payload nil to reduce block size..
	//anything else to remove .. do we need StateDelta ?
	for _,tx := range block.Transactions {
		tx.Payload = nil
	}

	logger.Debug("Got the delta state of block number %v", blockHeight)
	data, err := proto.Marshal(&pb.BlockState{Block: block, StateDelta: delta.Marshal()})
	if err != nil {
		return fmt.Errorf("Fail to marshall BlockState structure: %v", err)
	}

	logger.Debug("Broadcasting OpenchainMessage_SYNC_BLOCK_ADDED to non-validators")
	msg := &pb.OpenchainMessage{Type: pb.OpenchainMessage_SYNC_BLOCK_ADDED,
		Payload: data, Timestamp: util.CreateUtcTimestamp()}
	if errs := i.cpi.Broadcast(msg, pb.PeerEndpoint_NON_VALIDATOR); nil != errs {
		return fmt.Errorf("Failed to broadcast with errors: %v", errs)
	}
	return nil
}

func (i *Noops) queueTransactions(txarr []*pb.Transaction) {
	i.txQ.Push(txarr)
	logger.Debug("Transaction queue size: %d", i.txQ.Size())
}
<commit_msg>consensus messages should be sent to validators only<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 noops

import (
	"fmt"

	"github.com/golang/protobuf/proto"
	"github.com/op/go-logging"

	"github.com/openblockchain/obc-peer/openchain/consensus"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/openchain/util"
	pb "github.com/openblockchain/obc-peer/protos"
)

// =============================================================================
// Init
// =============================================================================

var logger *logging.Logger // package-level logger

func init() {
	logger = logging.MustGetLogger("consensus/noops")
}

// =============================================================================
// Structures go here
// =============================================================================

// Noops is a plugin object implementing the consensus.Consenter interface.
type Noops struct {
	cpi consensus.CPI
	txQ *util.Queue
}

var iNoops consensus.Consenter

// =============================================================================
// Constructors go here
// =============================================================================

// NewNoops is a constructor returning a consensus.Consenter object.
func NewNoops(c consensus.CPI) consensus.Consenter {
	logger.Debug("Creating a NOOPS object")
	i := &Noops{}
	i.cpi = c
	i.txQ = util.NewQueue()
	return i
}

// GetNoops returns a singleton of NOOPS
func GetNoops(c consensus.CPI) consensus.Consenter {
	if iNoops == nil {
		iNoops = NewNoops(c)
	}
	return iNoops
}

// RecvMsg is called for OpenchainMessage_CHAIN_TRANSACTION and OpenchainMessage_CONSENSUS messages.
func (i *Noops) RecvMsg(msg *pb.OpenchainMessage) error {
	logger.Debug("Handling OpenchainMessage of type: %s ", msg.Type)

	if msg.Type == pb.OpenchainMessage_CHAIN_TRANSACTION {
		if err := i.broadcastConsensusMsg(msg); nil != err {
			return err
		}
	}
	if msg.Type == pb.OpenchainMessage_CONSENSUS {
		txarr, err := i.getTransactionsFromMsg(msg)
		if nil != err {
			return err
		}
		if i.canProcess(txarr) {
			i.txQ.Push(txarr)
			if err=i.doTransactions(msg); err == nil {
				//transactions succeeed, broadcast
				//spin the broadcast in go routine so
				//(a)we make RecvMsg light and
				//(b)we separate send from receive
				go i.notifyBlockAdded()
			}
			return err
		}
		i.queueTransactions(txarr)
	}
	return nil
}

func (i *Noops) broadcastConsensusMsg(msg *pb.OpenchainMessage) error {
	t := &pb.Transaction{}
	if err := proto.Unmarshal(msg.Payload, t); err != nil {
		return fmt.Errorf("Error unmarshalling payload of received OpenchainMessage:%s.", msg.Type)
	}

	// Change the msg type to consensus and broadcast to the network so that
	// other validators may execute the transaction
	msg.Type = pb.OpenchainMessage_CONSENSUS
	logger.Debug("Broadcasting %s", msg.Type)
	txs := &pb.TransactionBlock{Transactions: []*pb.Transaction{t}}
	payload, err := proto.Marshal(txs)
	if err != nil {
		return err
	}
	msg.Payload = payload
	if errs := i.cpi.Broadcast(msg, pb.PeerEndpoint_VALIDATOR); nil != errs {
		return fmt.Errorf("Failed to broadcast with errors: %v", errs)
	}
	return nil
}

func (i *Noops) getTransactionsFromMsg(msg *pb.OpenchainMessage) ([]*pb.Transaction, error) {
	txs := &pb.TransactionBlock{}
	if err := proto.Unmarshal(msg.Payload, txs); err != nil {
		return nil, err
	}
	return txs.GetTransactions(), nil
}

func (i *Noops) getTransactionsFromQueue() []*pb.Transaction {
	len := i.txQ.Size()
	if len == 1 {
		return i.txQ.Pop().([]*pb.Transaction)
	}
	txarr := make([]*pb.Transaction, len)
	for k := 0; k < len; k++ {
		txs := i.txQ.Pop().([]*pb.Transaction)
		txarr[k] = txs[0]
	}
	return txarr
}

func (i *Noops) canProcess(txarr []*pb.Transaction) bool {
	// For NOOPS, if we have completed the sync since we last connected,
	// we can assume that we are at the current state; otherwise, we need to
	// wait for the sync process to complete before we can exec the transactions

	// TODO: Ask coordinator if we need to start sync

	return true
}

func (i *Noops) doTransactions(msg *pb.OpenchainMessage) error {
	logger.Debug("Executing transactions")
	logger.Debug("Starting TX batch with timestamp: %v", msg.Timestamp)
	if err := i.cpi.BeginTxBatch(msg.Timestamp); err != nil {
		return err
	}

	// Grab all transactions from the FIFO queue and run them in order
	txarr := i.getTransactionsFromQueue()
	logger.Debug("Executing batch of %d transactions", len(txarr))
	_, errs := i.cpi.ExecTXs(txarr)

	//there are n+1 elements of errors in this array. On complete success
	//they'll all be nil. In particular, the last err will be error in
	//producing the hash, if any. That's the only error we do want to check
	if errs[len(txarr)] != nil {
		logger.Debug("Rolling back TX batch with timestamp: %v", msg.Timestamp)
		i.cpi.RollbackTxBatch(msg.Timestamp)
		return fmt.Errorf("Fail to execute transactions: %v", errs)
	}

	logger.Debug("Committing TX batch with timestamp: %v", msg.Timestamp)
	if err := i.cpi.CommitTxBatch(msg.Timestamp, txarr, nil, nil); err != nil {
		logger.Debug("Rolling back TX batch with timestamp: %v", msg.Timestamp)
		i.cpi.RollbackTxBatch(msg.Timestamp)
		return err
	}

	return nil
}

func (i *Noops) notifyBlockAdded() error {
	ledger, err := ledger.GetLedger()
	if err != nil {
		return fmt.Errorf("Fail to get the ledger: %v", err)
	}

	// TODO: Broadcast SYNC_BLOCK_ADDED to connected NVPs
	// VPs already know about this newly added block since they participate
	// in the execution. That is, they can compare their current block with
	// the network block
	// For now, send to everyone until broadcast has better discrimination
	blockHeight := ledger.GetBlockchainSize()
	logger.Debug("Preparing to broadcast with block number %v", blockHeight)
	block, err := ledger.GetBlockByNumber(blockHeight - 1)
	if nil != err {
		return err
	}
	//delta, err := ledger.GetStateDeltaBytes(blockHeight)
	delta, err := ledger.GetStateDelta(blockHeight - 1)
	if nil != err {
		return err
	}

	//make Payload nil to reduce block size..
	//anything else to remove .. do we need StateDelta ?
	for _,tx := range block.Transactions {
		tx.Payload = nil
	}

	logger.Debug("Got the delta state of block number %v", blockHeight)
	data, err := proto.Marshal(&pb.BlockState{Block: block, StateDelta: delta.Marshal()})
	if err != nil {
		return fmt.Errorf("Fail to marshall BlockState structure: %v", err)
	}

	logger.Debug("Broadcasting OpenchainMessage_SYNC_BLOCK_ADDED to non-validators")
	msg := &pb.OpenchainMessage{Type: pb.OpenchainMessage_SYNC_BLOCK_ADDED,
		Payload: data, Timestamp: util.CreateUtcTimestamp()}
	if errs := i.cpi.Broadcast(msg, pb.PeerEndpoint_NON_VALIDATOR); nil != errs {
		return fmt.Errorf("Failed to broadcast with errors: %v", errs)
	}
	return nil
}

func (i *Noops) queueTransactions(txarr []*pb.Transaction) {
	i.txQ.Push(txarr)
	logger.Debug("Transaction queue size: %d", i.txQ.Size())
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"

	v1alpha1 "github.com/jetstack-experimental/navigator/pkg/apis/navigator/v1alpha1"
	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	corelisters "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/record"
)

type Interface interface {
	Sync(*v1alpha1.CassandraCluster) error
}

type defaultCassandraClusterServiceControl struct {
	kubeClient    kubernetes.Interface
	serviceLister corelisters.ServiceLister
	recorder      record.EventRecorder
}

var _ Interface = &defaultCassandraClusterServiceControl{}

func NewControl(
	kubeClient kubernetes.Interface,
	serviceLister corelisters.ServiceLister,
	recorder record.EventRecorder,
) Interface {
	return &defaultCassandraClusterServiceControl{
		kubeClient:    kubeClient,
		serviceLister: serviceLister,
		recorder:      recorder,
	}
}

func (e *defaultCassandraClusterServiceControl) Sync(cluster *v1alpha1.CassandraCluster) error {
	svc := ServiceForCluster(cluster)
	client := e.kubeClient.CoreV1().Services(svc.Namespace)
	existingSvc, err := e.serviceLister.Services(cluster.Namespace).Get(svc.Name)
	if k8sErrors.IsNotFound(err) {
		_, err := client.Create(svc)
		return err
	} else if err != nil {
		return err
	}
	if !metav1.IsControlledBy(existingSvc, cluster) {
		return fmt.Errorf("Duplicate service detected: %s", svc)
	}
	_, err = client.Update(svc)
	return err
}
<commit_msg>Use the svc.Namespace<commit_after>package service

import (
	"fmt"

	v1alpha1 "github.com/jetstack-experimental/navigator/pkg/apis/navigator/v1alpha1"
	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	corelisters "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/record"
)

type Interface interface {
	Sync(*v1alpha1.CassandraCluster) error
}

type defaultCassandraClusterServiceControl struct {
	kubeClient    kubernetes.Interface
	serviceLister corelisters.ServiceLister
	recorder      record.EventRecorder
}

var _ Interface = &defaultCassandraClusterServiceControl{}

func NewControl(
	kubeClient kubernetes.Interface,
	serviceLister corelisters.ServiceLister,
	recorder record.EventRecorder,
) Interface {
	return &defaultCassandraClusterServiceControl{
		kubeClient:    kubeClient,
		serviceLister: serviceLister,
		recorder:      recorder,
	}
}

func (e *defaultCassandraClusterServiceControl) Sync(cluster *v1alpha1.CassandraCluster) error {
	svc := ServiceForCluster(cluster)
	client := e.kubeClient.CoreV1().Services(svc.Namespace)
	existingSvc, err := e.serviceLister.Services(svc.Namespace).Get(svc.Name)
	if k8sErrors.IsNotFound(err) {
		_, err := client.Create(svc)
		return err
	} else if err != nil {
		return err
	}
	if !metav1.IsControlledBy(existingSvc, cluster) {
		return fmt.Errorf("Duplicate service detected: %s", svc)
	}
	_, err = client.Update(svc)
	return err
}
<|endoftext|>


<commit_before>package imagechecker

import (
	"context"
	"fmt"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecr"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/sync/errgroup"
	"k8s.io/apimachinery/pkg/runtime"

	"github.com/rebuy-de/kubernetes-deployment/pkg/kubeutil"
)

type set map[string]*struct{}

func (s set) add(value string) { s[value] = nil }

type Interceptor struct {
	session *session.Session
	Options Options
}

func New(session *session.Session, options Options) *Interceptor {
	return &Interceptor{
		session: session,
		Options: options,
	}
}

func (i *Interceptor) PreApply(objects []runtime.Object) error {
	images := make(set)

	for _, obj := range objects {
		template := kubeutil.PodTemplateSpecAccessor(obj)
		if template == nil {
			continue
		}

		for _, container := range template.Spec.Containers {
			images.add(container.Image)
		}

		for _, container := range template.Spec.InitContainers {
			images.add(container.Image)
		}
	}

	ctx, cancel := context.WithTimeout(context.Background(), i.Options.WaitTimeout)
	defer cancel()
	eg, ctx := errgroup.WithContext(ctx)

	for image := range images {
		image := image // https://golang.org/doc/faq#closures_and_goroutines
		eg.Go(func() error {
			return i.wait(ctx, image)
		})
	}

	return eg.Wait()
}

func (i *Interceptor) wait(ctx context.Context, image string) error {
	t := time.NewTicker(i.Options.CheckInterval)
	defer t.Stop()

	logrus.WithFields(logrus.Fields{
		"image": image,
	}).Debugf("Checking for image availability.")

	for {
		select {
		case <-t.C:
			found, err := i.check(ctx, image)
			if err != nil {
				return errors.Wrapf(err, "failed to check image %s", image)
			}
			if found {
				return nil
			}
		case <-ctx.Done():
			return fmt.Errorf("aborted")
		}
	}
}

func (i *Interceptor) check(ctx context.Context, image string) (bool, error) {
	reECR, err := regexp.Compile(`^([0-9]+).dkr.ecr.([a-z0-9-]+).amazonaws.com/([^:]+):(.*)$`)
	if err != nil {
		return false, errors.WithStack(err)
	}

	m := reECR.FindStringSubmatch(image)
	if m != nil {
		return i.checkECR(ctx, m[1], m[2], m[3], m[4])
	}

	logrus.WithField("image", image).Debugf("Unknown image provider. Assuming it exists.")
	return true, nil

}

func (i *Interceptor) checkECR(ctx context.Context, account, region, repo, tag string) (bool, error) {
	l := logrus.WithFields(logrus.Fields{
		"account": account,
		"region":  region,
		"repo":    repo,
		"tag":     tag,
	})
	l.Debugf("Checking for image on ECR.")

	sess := i.session.Copy(&aws.Config{
		Region: aws.String(region),
	})
	creds := stscreds.NewCredentials(sess, fmt.Sprintf("arn:aws:iam::%s:role/ecr-cross-access", account))

	svc := ecr.New(sess, &aws.Config{Credentials: creds})
	images, err := svc.DescribeImagesWithContext(ctx, &ecr.DescribeImagesInput{
		RegistryId:     aws.String(account),
		RepositoryName: aws.String(repo),
		ImageIds: []*ecr.ImageIdentifier{
			&ecr.ImageIdentifier{
				ImageTag: aws.String(tag),
			},
		},
	})

	if err == nil {
		image := images.ImageDetails[0]
		l.WithFields(logrus.Fields{
			"digest":    aws.StringValue(image.ImageDigest),
			"size":      aws.Int64Value(image.ImageSizeInBytes),
			"tags":      aws.StringValueSlice(image.ImageTags),
			"pushed_at": aws.TimeValue(image.ImagePushedAt),
		}).Debugf("Found image.")
		return true, nil
	}

	aerr, ok := err.(awserr.Error)
	if !ok {
		l.Debugf("Unkown error: %v", err)
		return false, errors.WithStack(err)
	}

	switch aerr.Code() {
	case ecr.ErrCodeImageNotFoundException:
		// This means the repo was found, but the image tag wasn't.
		l.Debugf("Not available, yet.")
		return false, nil
	default:
		l.Debugf("Unexpected error: %v", err)
		return false, errors.WithStack(err)
	}
}
<commit_msg>Improve logging in image check<commit_after>package imagechecker

import (
	"context"
	"fmt"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecr"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/sync/errgroup"
	"k8s.io/apimachinery/pkg/runtime"

	"github.com/rebuy-de/kubernetes-deployment/pkg/kubeutil"
)

type set map[string]*struct{}

func (s set) add(value string) { s[value] = nil }

type Interceptor struct {
	session *session.Session
	Options Options
}

func New(session *session.Session, options Options) *Interceptor {
	return &Interceptor{
		session: session,
		Options: options,
	}
}

func (i *Interceptor) PreApply(objects []runtime.Object) error {
	images := make(set)

	for _, obj := range objects {
		template := kubeutil.PodTemplateSpecAccessor(obj)
		if template == nil {
			continue
		}

		for _, container := range template.Spec.Containers {
			images.add(container.Image)
		}

		for _, container := range template.Spec.InitContainers {
			images.add(container.Image)
		}
	}

	ctx, cancel := context.WithTimeout(context.Background(), i.Options.WaitTimeout)
	defer cancel()
	eg, ctx := errgroup.WithContext(ctx)

	for image := range images {
		image := image // https://golang.org/doc/faq#closures_and_goroutines
		eg.Go(func() error {
			return i.wait(ctx, image)
		})
	}

	return eg.Wait()
}

func (i *Interceptor) wait(ctx context.Context, image string) error {
	t := time.NewTicker(i.Options.CheckInterval)
	defer t.Stop()
	try := 0

	logrus.WithFields(logrus.Fields{
		"image": image,
	}).Debugf("Checking for image availability.")

	for {
		select {
		case <-t.C:
			found, err := i.check(ctx, image)
			if err != nil {
				return errors.Wrapf(err, "failed to check image %s", image)
			}
			if found {
				return nil
			}
			if try == 0 {
				logrus.Info("Deployment is waiting for image to be built.")
				try++
				continue
			}
			if (try % 4) == 0 {
				logrus.Info("Still waiting for image to be available...")
			}
			try++
		case <-ctx.Done():
			return fmt.Errorf("Deployment aborted because image is still missing")
		}
	}
}

func (i *Interceptor) check(ctx context.Context, image string) (bool, error) {
	reECR, err := regexp.Compile(`^([0-9]+).dkr.ecr.([a-z0-9-]+).amazonaws.com/([^:]+):(.*)$`)
	if err != nil {
		return false, errors.WithStack(err)
	}

	m := reECR.FindStringSubmatch(image)
	if m != nil {
		return i.checkECR(ctx, m[1], m[2], m[3], m[4])
	}

	logrus.WithField("image", image).Debugf("Unknown image provider. Assuming it exists.")
	return true, nil

}

func (i *Interceptor) checkECR(ctx context.Context, account, region, repo, tag string) (bool, error) {
	l := logrus.WithFields(logrus.Fields{
		"account": account,
		"region":  region,
		"repo":    repo,
		"tag":     tag,
	})
	l.Debugf("Checking for image on ECR.")

	sess := i.session.Copy(&aws.Config{
		Region: aws.String(region),
	})
	creds := stscreds.NewCredentials(sess, fmt.Sprintf("arn:aws:iam::%s:role/ecr-cross-access", account))

	svc := ecr.New(sess, &aws.Config{Credentials: creds})
	images, err := svc.DescribeImagesWithContext(ctx, &ecr.DescribeImagesInput{
		RegistryId:     aws.String(account),
		RepositoryName: aws.String(repo),
		ImageIds: []*ecr.ImageIdentifier{
			&ecr.ImageIdentifier{
				ImageTag: aws.String(tag),
			},
		},
	})

	if err == nil {
		image := images.ImageDetails[0]
		l.WithFields(logrus.Fields{
			"digest":    aws.StringValue(image.ImageDigest),
			"size":      aws.Int64Value(image.ImageSizeInBytes),
			"tags":      aws.StringValueSlice(image.ImageTags),
			"pushed_at": aws.TimeValue(image.ImagePushedAt),
		}).Debugf("Found image.")
		return true, nil
	}

	aerr, ok := err.(awserr.Error)
	if !ok {
		l.Debugf("Unkown error: %v", err)
		return false, errors.WithStack(err)
	}

	switch aerr.Code() {
	case ecr.ErrCodeImageNotFoundException:
		// This means the repo was found, but the image tag wasn't.
		l.Debugf("Not available, yet.")
		return false, nil
	default:
		l.Debugf("Unexpected error: %v", err)
		return false, errors.WithStack(err)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package testutils

import (
	"sync"
	"time"
)

// WaitFor will retry f till it returns true for a maximum of timeout.
// It returns true if f returned true, false if timeout was hit.
func WaitFor(timeout time.Duration, f func() bool) bool {
	timeoutEnd := time.Now().Add(timeout)

	const maxSleep = time.Millisecond * 50
	sleepFor := time.Millisecond
	for {
		if f() {
			return true
		}

		if time.Now().After(timeoutEnd) {
			return false
		}

		time.Sleep(sleepFor)
		if sleepFor < maxSleep {
			sleepFor *= 2
		}
	}
}

// WaitWG waits for the given WaitGroup to be complete with a timeout
// and returns whether the WaitGroup completed within the timeout.
func WaitWG(wg *sync.WaitGroup, timeout time.Duration) bool {
	wgC := make(chan struct{})

	go func() {
		wg.Wait()
		wgC <- struct{}{}
	}()
	select {
	case <-time.After(timeout):
		return false
	case <-wgC:
		return true
	}
}
<commit_msg>testutils.WaitFor should use timeout multiplier<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package testutils

import (
	"sync"
	"time"
)

// WaitFor will retry f till it returns true for a maximum of timeout.
// It returns true if f returned true, false if timeout was hit.
func WaitFor(timeout time.Duration, f func() bool) bool {
	timeoutEnd := time.Now().Add(Timeout(timeout))

	const maxSleep = time.Millisecond * 50
	sleepFor := time.Millisecond
	for {
		if f() {
			return true
		}

		if time.Now().After(timeoutEnd) {
			return false
		}

		time.Sleep(sleepFor)
		if sleepFor < maxSleep {
			sleepFor *= 2
		}
	}
}

// WaitWG waits for the given WaitGroup to be complete with a timeout
// and returns whether the WaitGroup completed within the timeout.
func WaitWG(wg *sync.WaitGroup, timeout time.Duration) bool {
	wgC := make(chan struct{})

	go func() {
		wg.Wait()
		wgC <- struct{}{}
	}()
	select {
	case <-time.After(timeout):
		return false
	case <-wgC:
		return true
	}
}
<|endoftext|>


<commit_before>package logberry

// BuildMetadata is a simple structured representation of some basic
// properties characterizing the build of a particular binary.
type BuildMetadata struct {
	Host string
	User string
	Date string

	Repositories []RepositoryMetadata
}

// RepositoryMetadata captures basic identifying properties of a
// typical source version control repository instance.
type RepositoryMetadata struct {
	Repository string
	Branch     string
	Commit     string
	Dirty      bool
	Path       string
}
<commit_msg>Utility to create map from repositories.<commit_after>package logberry

// BuildMetadata is a simple structured representation of some basic
// properties characterizing the build of a particular binary.
type BuildMetadata struct {
	Host string
	User string
	Date string

	Repositories []RepositoryMetadata
}

// RepositoryMetadata captures basic identifying properties of a
// typical source version control repository instance.
type RepositoryMetadata struct {
	Repository string
	Branch     string
	Commit     string
	Dirty      bool
	Path       string
}

func (x *BuildMetadata) Map() map[string]*RepositoryMetadata {

	m := make(map[string]*RepositoryMetadata)

	for _,r := range(x.Repositories) {
		m[r.Repository] = &r
	}

	return m

}
<|endoftext|>


<commit_before>package controllers

import (
	"geoip-webservice/models"

	"github.com/gin-gonic/gin"
	"net/http"
)

func IP2LocationController(c *gin.Context) {
	ipaddress := c.Query("ipaddress")

	geolocation := models.IP2LocationQuery(ipaddress)

	c.JSON(http.StatusOK, geolocation)
}
<commit_msg>Use config<commit_after>package controllers

import (
	"geoip-webservice/models"

	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
)

func IP2LocationController(c *gin.Context) {
	ipaddress := c.Query(viper.GetString("querystrings.ipaddress"))

	geolocation := models.IP2LocationQuery(ipaddress)

	c.JSON(http.StatusOK, geolocation)
}
<|endoftext|>


<commit_before>package promptui

import (
	"fmt"
	"io"
	"strings"
	"text/template"

	"github.com/chzyer/readline"
	"github.com/manifoldco/promptui/screenbuf"
)

// Prompt represents a single line text field input with options for validation and input masks.
type Prompt struct {
	// Label is the value displayed on the command line prompt.
	//
	// The value for Label can be a simple string or a struct that will need to be accessed by dot notation
	// inside the templates. For example, `{{ .Name }}` will display the name property of a struct.
	Label interface{}

	// Default is the initial value for the prompt. This value will be displayed next to the prompt's label
	// and the user will be able to view or change it depending on the options.
	Default string

	// AllowEdit lets the user edit the default value. If false, any key press
	// other than <Enter> automatically clears the default value.
	AllowEdit bool

	// Validate is an optional function that fill be used against the entered value in the prompt to validate it.
	Validate ValidateFunc

	// Mask is an optional rune that sets which character to display instead of the entered characters. This
	// allows hiding private information like passwords.
	Mask rune

	// Templates can be used to customize the prompt output. If nil is passed, the
	// default templates are used. See the PromptTemplates docs for more info.
	Templates *PromptTemplates

	// IsConfirm makes the prompt ask for a yes or no ([Y/N]) question rather than request an input. When set,
	// most properties related to input will be ignored.
	IsConfirm bool

	// IsVimMode enables vi-like movements (hjkl) and editing.
	IsVimMode bool

	// the Pointer defines how to render the cursor.
	Pointer Pointer

	stdin  io.ReadCloser
	stdout io.WriteCloser
}

// PromptTemplates allow a prompt to be customized following stdlib
// text/template syntax. Custom state, colors and background color are available for use inside
// the templates and are documented inside the Variable section of the docs.
//
// Examples
//
// text/templates use a special notation to display programmable content. Using the double bracket notation,
// the value can be printed with specific helper functions. For example
//
// This displays the value given to the template as pure, unstylized text.
// 	'{{ . }}'
//
// This displays the value colored in cyan
// 	'{{ . | cyan }}'
//
// This displays the value colored in red with a cyan background-color
// 	'{{ . | red | cyan }}'
//
// See the doc of text/template for more info: https://golang.org/pkg/text/template/
type PromptTemplates struct {
	// Prompt is a text/template for the prompt label displayed on the left side of the prompt.
	Prompt string

	// Prompt is a text/template for the prompt label when IsConfirm is set as true.
	Confirm string

	// Valid is a text/template for the prompt label when the value entered is valid.
	Valid string

	// Invalid is a text/template for the prompt label when the value entered is invalid.
	Invalid string

	// Success is a text/template for the prompt label when the user has pressed entered and the value has been
	// deemed valid by the validation function. The label will keep using this template even when the prompt ends
	// inside the console.
	Success string

	// Prompt is a text/template for the prompt label when the value is invalid due to an error triggered by
	// the prompt's validation function.
	ValidationError string

	// FuncMap is a map of helper functions that can be used inside of templates according to the text/template
	// documentation.
	//
	// By default, FuncMap contains the color functions used to color the text in templates. If FuncMap
	// is overridden, the colors functions must be added in the override from promptui.FuncMap to work.
	FuncMap template.FuncMap

	prompt     *template.Template
	valid      *template.Template
	invalid    *template.Template
	validation *template.Template
	success    *template.Template
}

// Run executes the prompt. Its displays the label and default value if any, asking the user to enter a value.
// Run will keep the prompt alive until it has been canceled from the command prompt or it has received a valid
// value. It will return the value and an error if any occurred during the prompt's execution.
func (p *Prompt) Run() (string, error) {
	var err error

	err = p.prepareTemplates()
	if err != nil {
		return "", err
	}

	c := &readline.Config{
		Stdin:          p.stdin,
		Stdout:         p.stdout,
		EnableMask:     p.Mask != 0,
		MaskRune:       p.Mask,
		HistoryLimit:   -1,
		VimMode:        p.IsVimMode,
		UniqueEditLine: true,
	}

	err = c.Init()
	if err != nil {
		return "", err
	}

	rl, err := readline.NewEx(c)
	if err != nil {
		return "", err
	}
	// we're taking over the cursor,  so stop showing it.
	rl.Write([]byte(hideCursor))
	sb := screenbuf.New(rl)

	validFn := func(x string) error {
		return nil
	}
	if p.Validate != nil {
		validFn = p.Validate
	}

	var inputErr error
	input := p.Default
	if p.IsConfirm {
		input = ""
	}
	eraseDefault := input != "" && !p.AllowEdit
	cur := NewCursor(input, p.Pointer, eraseDefault)

	listen := func(input []rune, pos int, key rune) ([]rune, int, bool) {
		_, _, keepOn := cur.Listen(input, pos, key)
		err := validFn(cur.Get())
		var prompt []byte

		if err != nil {
			prompt = render(p.Templates.invalid, p.Label)
		} else {
			prompt = render(p.Templates.valid, p.Label)
			if p.IsConfirm {
				prompt = render(p.Templates.prompt, p.Label)
			}
		}

		echo := cur.Format()
		if p.Mask != 0 {
			echo = cur.FormatMask(p.Mask)
		}

		prompt = append(prompt, []byte(echo)...)
		sb.Reset()
		sb.Write(prompt)
		if inputErr != nil {
			validation := render(p.Templates.validation, inputErr)
			sb.Write(validation)
			inputErr = nil
		}
		sb.Flush()
		return nil, 0, keepOn
	}

	c.SetListener(listen)

	for {
		_, err := rl.Readline()
		inputErr = validFn(cur.Get())
		if inputErr == nil {
			break
		}

		if err != nil {
			break
		}
	}

	if err != nil {
		switch err {
		case readline.ErrInterrupt:
			err = ErrInterrupt
		case io.EOF:
			err = ErrEOF
		}
		if err.Error() == "Interrupt" {
			err = ErrInterrupt
		}
		sb.Reset()
		sb.WriteString("")
		sb.Flush()
		rl.Write([]byte(showCursor))
		rl.Close()
		return "", err
	}

	echo := cur.Format()
	if p.Mask != 0 {
		echo = cur.FormatMask(p.Mask)
	}

	prompt := render(p.Templates.success, p.Label)
	prompt = append(prompt, []byte(echo)...)

	if p.IsConfirm {
		lowerDefault := strings.ToLower(p.Default)
		if strings.ToLower(cur.Get()) != "y" && (lowerDefault != "y" || (lowerDefault == "y" && cur.Get() != "")) {
			prompt = render(p.Templates.invalid, p.Label)
			err = ErrAbort
		}
	}

	sb.Reset()
	sb.Write(prompt)
	sb.Flush()
	rl.Write([]byte(showCursor))
	rl.Close()

	return cur.Get(), err
}

func (p *Prompt) prepareTemplates() error {
	tpls := p.Templates
	if tpls == nil {
		tpls = &PromptTemplates{}
	}

	if tpls.FuncMap == nil {
		tpls.FuncMap = FuncMap
	}

	bold := Styler(FGBold)

	if p.IsConfirm {
		if tpls.Confirm == "" {
			confirm := "y/N"
			if strings.ToLower(p.Default) == "y" {
				confirm = "Y/n"
			}
			tpls.Confirm = fmt.Sprintf(`{{ "%s" | bold }} {{ . | bold }}? {{ "[%s]" | faint }} `, IconInitial, confirm)
		}

		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Confirm)
		if err != nil {
			return err
		}

		tpls.prompt = tpl
	} else {
		if tpls.Prompt == "" {
			tpls.Prompt = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconInitial), bold(":"))
		}

		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Prompt)
		if err != nil {
			return err
		}

		tpls.prompt = tpl
	}

	if tpls.Valid == "" {
		tpls.Valid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":"))
	}

	tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Valid)
	if err != nil {
		return err
	}

	tpls.valid = tpl

	if tpls.Invalid == "" {
		tpls.Invalid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconBad), bold(":"))
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Invalid)
	if err != nil {
		return err
	}

	tpls.invalid = tpl

	if tpls.ValidationError == "" {
		tpls.ValidationError = `{{ ">>" | red }} {{ . | red }}`
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.ValidationError)
	if err != nil {
		return err
	}

	tpls.validation = tpl

	if tpls.Success == "" {
		tpls.Success = fmt.Sprintf("{{ . | faint }}%s ", Styler(FGFaint)(":"))
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Success)
	if err != nil {
		return err
	}

	tpls.success = tpl

	p.Templates = tpls

	return nil
}
<commit_msg>fix: Interrupt was not catched because err was out of scope (#103)<commit_after>package promptui

import (
	"fmt"
	"io"
	"strings"
	"text/template"

	"github.com/chzyer/readline"
	"github.com/manifoldco/promptui/screenbuf"
)

// Prompt represents a single line text field input with options for validation and input masks.
type Prompt struct {
	// Label is the value displayed on the command line prompt.
	//
	// The value for Label can be a simple string or a struct that will need to be accessed by dot notation
	// inside the templates. For example, `{{ .Name }}` will display the name property of a struct.
	Label interface{}

	// Default is the initial value for the prompt. This value will be displayed next to the prompt's label
	// and the user will be able to view or change it depending on the options.
	Default string

	// AllowEdit lets the user edit the default value. If false, any key press
	// other than <Enter> automatically clears the default value.
	AllowEdit bool

	// Validate is an optional function that fill be used against the entered value in the prompt to validate it.
	Validate ValidateFunc

	// Mask is an optional rune that sets which character to display instead of the entered characters. This
	// allows hiding private information like passwords.
	Mask rune

	// Templates can be used to customize the prompt output. If nil is passed, the
	// default templates are used. See the PromptTemplates docs for more info.
	Templates *PromptTemplates

	// IsConfirm makes the prompt ask for a yes or no ([Y/N]) question rather than request an input. When set,
	// most properties related to input will be ignored.
	IsConfirm bool

	// IsVimMode enables vi-like movements (hjkl) and editing.
	IsVimMode bool

	// the Pointer defines how to render the cursor.
	Pointer Pointer

	stdin  io.ReadCloser
	stdout io.WriteCloser
}

// PromptTemplates allow a prompt to be customized following stdlib
// text/template syntax. Custom state, colors and background color are available for use inside
// the templates and are documented inside the Variable section of the docs.
//
// Examples
//
// text/templates use a special notation to display programmable content. Using the double bracket notation,
// the value can be printed with specific helper functions. For example
//
// This displays the value given to the template as pure, unstylized text.
// 	'{{ . }}'
//
// This displays the value colored in cyan
// 	'{{ . | cyan }}'
//
// This displays the value colored in red with a cyan background-color
// 	'{{ . | red | cyan }}'
//
// See the doc of text/template for more info: https://golang.org/pkg/text/template/
type PromptTemplates struct {
	// Prompt is a text/template for the prompt label displayed on the left side of the prompt.
	Prompt string

	// Prompt is a text/template for the prompt label when IsConfirm is set as true.
	Confirm string

	// Valid is a text/template for the prompt label when the value entered is valid.
	Valid string

	// Invalid is a text/template for the prompt label when the value entered is invalid.
	Invalid string

	// Success is a text/template for the prompt label when the user has pressed entered and the value has been
	// deemed valid by the validation function. The label will keep using this template even when the prompt ends
	// inside the console.
	Success string

	// Prompt is a text/template for the prompt label when the value is invalid due to an error triggered by
	// the prompt's validation function.
	ValidationError string

	// FuncMap is a map of helper functions that can be used inside of templates according to the text/template
	// documentation.
	//
	// By default, FuncMap contains the color functions used to color the text in templates. If FuncMap
	// is overridden, the colors functions must be added in the override from promptui.FuncMap to work.
	FuncMap template.FuncMap

	prompt     *template.Template
	valid      *template.Template
	invalid    *template.Template
	validation *template.Template
	success    *template.Template
}

// Run executes the prompt. Its displays the label and default value if any, asking the user to enter a value.
// Run will keep the prompt alive until it has been canceled from the command prompt or it has received a valid
// value. It will return the value and an error if any occurred during the prompt's execution.
func (p *Prompt) Run() (string, error) {
	var err error

	err = p.prepareTemplates()
	if err != nil {
		return "", err
	}

	c := &readline.Config{
		Stdin:          p.stdin,
		Stdout:         p.stdout,
		EnableMask:     p.Mask != 0,
		MaskRune:       p.Mask,
		HistoryLimit:   -1,
		VimMode:        p.IsVimMode,
		UniqueEditLine: true,
	}

	err = c.Init()
	if err != nil {
		return "", err
	}

	rl, err := readline.NewEx(c)
	if err != nil {
		return "", err
	}
	// we're taking over the cursor,  so stop showing it.
	rl.Write([]byte(hideCursor))
	sb := screenbuf.New(rl)

	validFn := func(x string) error {
		return nil
	}
	if p.Validate != nil {
		validFn = p.Validate
	}

	var inputErr error
	input := p.Default
	if p.IsConfirm {
		input = ""
	}
	eraseDefault := input != "" && !p.AllowEdit
	cur := NewCursor(input, p.Pointer, eraseDefault)

	listen := func(input []rune, pos int, key rune) ([]rune, int, bool) {
		_, _, keepOn := cur.Listen(input, pos, key)
		err := validFn(cur.Get())
		var prompt []byte

		if err != nil {
			prompt = render(p.Templates.invalid, p.Label)
		} else {
			prompt = render(p.Templates.valid, p.Label)
			if p.IsConfirm {
				prompt = render(p.Templates.prompt, p.Label)
			}
		}

		echo := cur.Format()
		if p.Mask != 0 {
			echo = cur.FormatMask(p.Mask)
		}

		prompt = append(prompt, []byte(echo)...)
		sb.Reset()
		sb.Write(prompt)
		if inputErr != nil {
			validation := render(p.Templates.validation, inputErr)
			sb.Write(validation)
			inputErr = nil
		}
		sb.Flush()
		return nil, 0, keepOn
	}

	c.SetListener(listen)

	for {
		_, err = rl.Readline()
		inputErr = validFn(cur.Get())
		if inputErr == nil {
			break
		}

		if err != nil {
			break
		}
	}

	if err != nil {
		switch err {
		case readline.ErrInterrupt:
			err = ErrInterrupt
		case io.EOF:
			err = ErrEOF
		}
		if err.Error() == "Interrupt" {
			err = ErrInterrupt
		}
		sb.Reset()
		sb.WriteString("")
		sb.Flush()
		rl.Write([]byte(showCursor))
		rl.Close()
		return "", err
	}

	echo := cur.Format()
	if p.Mask != 0 {
		echo = cur.FormatMask(p.Mask)
	}

	prompt := render(p.Templates.success, p.Label)
	prompt = append(prompt, []byte(echo)...)

	if p.IsConfirm {
		lowerDefault := strings.ToLower(p.Default)
		if strings.ToLower(cur.Get()) != "y" && (lowerDefault != "y" || (lowerDefault == "y" && cur.Get() != "")) {
			prompt = render(p.Templates.invalid, p.Label)
			err = ErrAbort
		}
	}

	sb.Reset()
	sb.Write(prompt)
	sb.Flush()
	rl.Write([]byte(showCursor))
	rl.Close()

	return cur.Get(), err
}

func (p *Prompt) prepareTemplates() error {
	tpls := p.Templates
	if tpls == nil {
		tpls = &PromptTemplates{}
	}

	if tpls.FuncMap == nil {
		tpls.FuncMap = FuncMap
	}

	bold := Styler(FGBold)

	if p.IsConfirm {
		if tpls.Confirm == "" {
			confirm := "y/N"
			if strings.ToLower(p.Default) == "y" {
				confirm = "Y/n"
			}
			tpls.Confirm = fmt.Sprintf(`{{ "%s" | bold }} {{ . | bold }}? {{ "[%s]" | faint }} `, IconInitial, confirm)
		}

		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Confirm)
		if err != nil {
			return err
		}

		tpls.prompt = tpl
	} else {
		if tpls.Prompt == "" {
			tpls.Prompt = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconInitial), bold(":"))
		}

		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Prompt)
		if err != nil {
			return err
		}

		tpls.prompt = tpl
	}

	if tpls.Valid == "" {
		tpls.Valid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":"))
	}

	tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Valid)
	if err != nil {
		return err
	}

	tpls.valid = tpl

	if tpls.Invalid == "" {
		tpls.Invalid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconBad), bold(":"))
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Invalid)
	if err != nil {
		return err
	}

	tpls.invalid = tpl

	if tpls.ValidationError == "" {
		tpls.ValidationError = `{{ ">>" | red }} {{ . | red }}`
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.ValidationError)
	if err != nil {
		return err
	}

	tpls.validation = tpl

	if tpls.Success == "" {
		tpls.Success = fmt.Sprintf("{{ . | faint }}%s ", Styler(FGFaint)(":"))
	}

	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Success)
	if err != nil {
		return err
	}

	tpls.success = tpl

	p.Templates = tpls

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancepoller

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"github.com/juju/errors"
	jc "github.com/juju/testing/checkers"
	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/testing/testbase"
)

type aggregateSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&aggregateSuite{})

type testInstance struct {
	instance.Instance
	addresses []instance.Address
	status    string
	err       error
}

var _ instance.Instance = (*testInstance)(nil)

func (t *testInstance) Addresses() ([]instance.Address, error) {
	if t.err != nil {
		return nil, t.err
	}
	return t.addresses, nil
}

func (t *testInstance) Status() string {
	return t.status
}

type testInstanceGetter struct {
	// ids is set when the Instances method is called.
	ids     []instance.Id
	results []instance.Instance
	err     error
	counter int32
}

func (i *testInstanceGetter) Instances(ids []instance.Id) (result []instance.Instance, err error) {
	i.ids = ids
	atomic.AddInt32(&i.counter, 1)
	return i.results, i.err
}

func newTestInstance(status string, addresses []string) *testInstance {
	thisInstance := testInstance{status: status}
	thisInstance.addresses = instance.NewAddresses(addresses...)
	return &thisInstance
}

func (s *aggregateSuite) TestSingleRequest(c *gc.C) {
	testGetter := new(testInstanceGetter)
	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	testGetter.results = []instance.Instance{instance1}
	aggregator := newAggregator(testGetter)

	info, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.IsNil)
	c.Assert(info, gc.DeepEquals, instanceInfo{
		status:    "foobar",
		addresses: instance1.addresses,
	})
	c.Assert(testGetter.ids, gc.DeepEquals, []instance.Id{"foo"})
}

func (s *aggregateSuite) TestMultipleResponseHandling(c *gc.C) {
	s.PatchValue(&gatherTime, 30*time.Millisecond)
	testGetter := new(testInstanceGetter)

	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	testGetter.results = []instance.Instance{instance1}
	aggregator := newAggregator(testGetter)

	replyChan := make(chan instanceInfoReply)
	req := instanceInfoReq{
		reply:  replyChan,
		instId: instance.Id("foo"),
	}
	aggregator.reqc <- req
	reply := <-replyChan
	c.Assert(reply.err, gc.IsNil)

	instance2 := newTestInstance("not foobar", []string{"192.168.1.2"})
	instance3 := newTestInstance("ok-ish", []string{"192.168.1.3"})
	testGetter.results = []instance.Instance{instance2, instance3}

	var wg sync.WaitGroup
	checkInfo := func(id instance.Id, expectStatus string) {
		info, err := aggregator.instanceInfo(id)
		c.Check(err, gc.IsNil)
		c.Check(info.status, gc.Equals, expectStatus)
		wg.Done()
	}

	wg.Add(2)
	go checkInfo("foo2", "not foobar")
	go checkInfo("foo3", "ok-ish")
	wg.Wait()

	c.Assert(len(testGetter.ids), gc.DeepEquals, 2)
}

func (s *aggregateSuite) TestBatching(c *gc.C) {
	s.PatchValue(&gatherTime, 10*time.Millisecond)
	testGetter := new(testInstanceGetter)

	aggregator := newAggregator(testGetter)
	for i := 0; i < 100; i++ {
		testGetter.results = append(testGetter.results, newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"}))
	}
	var wg sync.WaitGroup
	makeRequest := func() {
		_, err := aggregator.instanceInfo("foo")
		c.Check(err, gc.IsNil)
		wg.Done()
	}
	startTime := time.Now()
	wg.Add(100)
	for i := 0; i < 100; i++ {
		go makeRequest()
		time.Sleep(time.Millisecond)
	}
	wg.Wait()
	totalTime := time.Now().Sub(startTime)
	// +1 because we expect one extra call for the first request
	expectedMax := int32((totalTime / (10 * time.Millisecond)) + 1)
	c.Assert(testGetter.counter, jc.LessThan, expectedMax+1)
	c.Assert(testGetter.counter, jc.GreaterThan, 10)
}

func (s *aggregateSuite) TestError(c *gc.C) {
	testGetter := new(testInstanceGetter)
	ourError := fmt.Errorf("Some error")
	testGetter.err = ourError

	aggregator := newAggregator(testGetter)

	_, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.Equals, ourError)
}

func (s *aggregateSuite) TestPartialErrResponse(c *gc.C) {
	testGetter := new(testInstanceGetter)
	testGetter.err = environs.ErrPartialInstances
	testGetter.results = []instance.Instance{nil}

	aggregator := newAggregator(testGetter)
	_, err := aggregator.instanceInfo("foo")

	c.Assert(err, gc.ErrorMatches, "instance foo not found")
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}

func (s *aggregateSuite) TestAddressesError(c *gc.C) {
	testGetter := new(testInstanceGetter)
	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	ourError := fmt.Errorf("gotcha")
	instance1.err = ourError
	testGetter.results = []instance.Instance{instance1}

	aggregator := newAggregator(testGetter)
	_, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.Equals, ourError)
}

func (s *aggregateSuite) TestKillAndWait(c *gc.C) {
	testGetter := new(testInstanceGetter)
	aggregator := newAggregator(testGetter)
	aggregator.Kill()
	err := aggregator.Wait()
	c.Assert(err, gc.IsNil)
}
<commit_msg>[r=axwalk],[bug=1319652] worker/instancepoller: TestBatching less race-y<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancepoller

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"github.com/juju/errors"
	jc "github.com/juju/testing/checkers"
	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/testing/testbase"
)

type aggregateSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&aggregateSuite{})

type testInstance struct {
	instance.Instance
	addresses []instance.Address
	status    string
	err       error
}

var _ instance.Instance = (*testInstance)(nil)

func (t *testInstance) Addresses() ([]instance.Address, error) {
	if t.err != nil {
		return nil, t.err
	}
	return t.addresses, nil
}

func (t *testInstance) Status() string {
	return t.status
}

type testInstanceGetter struct {
	// ids is set when the Instances method is called.
	ids     []instance.Id
	results []instance.Instance
	err     error
	counter int32
}

func (i *testInstanceGetter) Instances(ids []instance.Id) (result []instance.Instance, err error) {
	i.ids = ids
	atomic.AddInt32(&i.counter, 1)
	return i.results, i.err
}

func newTestInstance(status string, addresses []string) *testInstance {
	thisInstance := testInstance{status: status}
	thisInstance.addresses = instance.NewAddresses(addresses...)
	return &thisInstance
}

func (s *aggregateSuite) TestSingleRequest(c *gc.C) {
	testGetter := new(testInstanceGetter)
	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	testGetter.results = []instance.Instance{instance1}
	aggregator := newAggregator(testGetter)

	info, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.IsNil)
	c.Assert(info, gc.DeepEquals, instanceInfo{
		status:    "foobar",
		addresses: instance1.addresses,
	})
	c.Assert(testGetter.ids, gc.DeepEquals, []instance.Id{"foo"})
}

func (s *aggregateSuite) TestMultipleResponseHandling(c *gc.C) {
	s.PatchValue(&gatherTime, 30*time.Millisecond)
	testGetter := new(testInstanceGetter)

	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	testGetter.results = []instance.Instance{instance1}
	aggregator := newAggregator(testGetter)

	replyChan := make(chan instanceInfoReply)
	req := instanceInfoReq{
		reply:  replyChan,
		instId: instance.Id("foo"),
	}
	aggregator.reqc <- req
	reply := <-replyChan
	c.Assert(reply.err, gc.IsNil)

	instance2 := newTestInstance("not foobar", []string{"192.168.1.2"})
	instance3 := newTestInstance("ok-ish", []string{"192.168.1.3"})
	testGetter.results = []instance.Instance{instance2, instance3}

	var wg sync.WaitGroup
	checkInfo := func(id instance.Id, expectStatus string) {
		info, err := aggregator.instanceInfo(id)
		c.Check(err, gc.IsNil)
		c.Check(info.status, gc.Equals, expectStatus)
		wg.Done()
	}

	wg.Add(2)
	go checkInfo("foo2", "not foobar")
	go checkInfo("foo3", "ok-ish")
	wg.Wait()

	c.Assert(len(testGetter.ids), gc.DeepEquals, 2)
}

type batchingInstanceGetter struct {
	testInstanceGetter
	wg         sync.WaitGroup
	aggregator *aggregator
	batchSize  int
	started    int
}

func (g *batchingInstanceGetter) Instances(ids []instance.Id) ([]instance.Instance, error) {
	insts, err := g.testInstanceGetter.Instances(ids)
	g.startRequests()
	return insts, err
}

func (g *batchingInstanceGetter) startRequests() {
	n := len(g.results) - g.started
	if n > g.batchSize {
		n = g.batchSize
	}
	for i := 0; i < n; i++ {
		g.startRequest()
	}
}

func (g *batchingInstanceGetter) startRequest() {
	g.started++
	go func() {
		_, err := g.aggregator.instanceInfo("foo")
		if err != nil {
			panic(err)
		}
		g.wg.Done()
	}()
}

func (s *aggregateSuite) TestBatching(c *gc.C) {
	s.PatchValue(&gatherTime, 10*time.Millisecond)
	var testGetter batchingInstanceGetter
	testGetter.aggregator = newAggregator(&testGetter)
	testGetter.results = make([]instance.Instance, 100)
	for i := range testGetter.results {
		testGetter.results[i] = newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	}
	testGetter.batchSize = 10
	testGetter.wg.Add(len(testGetter.results))
	testGetter.startRequest()
	testGetter.wg.Wait()
	c.Assert(testGetter.counter, gc.Equals, int32(len(testGetter.results)/testGetter.batchSize)+1)
}

func (s *aggregateSuite) TestError(c *gc.C) {
	testGetter := new(testInstanceGetter)
	ourError := fmt.Errorf("Some error")
	testGetter.err = ourError

	aggregator := newAggregator(testGetter)

	_, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.Equals, ourError)
}

func (s *aggregateSuite) TestPartialErrResponse(c *gc.C) {
	testGetter := new(testInstanceGetter)
	testGetter.err = environs.ErrPartialInstances
	testGetter.results = []instance.Instance{nil}

	aggregator := newAggregator(testGetter)
	_, err := aggregator.instanceInfo("foo")

	c.Assert(err, gc.ErrorMatches, "instance foo not found")
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}

func (s *aggregateSuite) TestAddressesError(c *gc.C) {
	testGetter := new(testInstanceGetter)
	instance1 := newTestInstance("foobar", []string{"127.0.0.1", "192.168.1.1"})
	ourError := fmt.Errorf("gotcha")
	instance1.err = ourError
	testGetter.results = []instance.Instance{instance1}

	aggregator := newAggregator(testGetter)
	_, err := aggregator.instanceInfo("foo")
	c.Assert(err, gc.Equals, ourError)
}

func (s *aggregateSuite) TestKillAndWait(c *gc.C) {
	testGetter := new(testInstanceGetter)
	aggregator := newAggregator(testGetter)
	aggregator.Kill()
	err := aggregator.Wait()
	c.Assert(err, gc.IsNil)
}
<|endoftext|>


<commit_before>package unison

import "github.com/bwmarrin/discordgo"

// Context is a type that is passed to every handler
// in a bot application.
// It can be used to refer back to main components.
type Context struct {
	Bot     *Bot
	Discord *discordgo.Session
}

func NewContext(bot *Bot, ds *discordgo.Session) *Context {
	return &Context{Bot: bot, Discord: ds}
}
<commit_msg>added interupt signal<commit_after>package unison

import (
	"os"
	"os/signal"

	"github.com/bwmarrin/discordgo"
)

// Context is a type that is passed to every handler
// in a bot application.
// It can be used to refer back to main components.
type Context struct {
	Bot                *Bot
	Discord            *discordgo.Session
	SystemInteruptChan chan struct{}
}

func NewContext(bot *Bot, ds *discordgo.Session) *Context {
	is := make(chan struct{})

	// shutdown signal
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		close(is)
	}()

	return &Context{Bot: bot, Discord: ds, SystemInteruptChan: is}
}
<|endoftext|>