<commit_before>package intercept

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"github.com/nbio/st"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

var errRead = errors.New("read error")

type errorReader struct{}

func (r *errorReader) Read(p []byte) (int, error) {
	return 0, errRead
}

type user struct {
	XMLName xml.Name `xml:"Person"`
	Name    string
}

func TestNewRequestModifier(t *testing.T) {
	h := http.Header{}
	h.Set("foo", "bar")
	req := &http.Request{Header: h}
	modifier := NewRequestModifier(req)
	st.Expect(t, modifier.Request, req)
	st.Expect(t, modifier.Header, h)
}

func TestReadString(t *testing.T) {
	bodyStr := `{"name":"Rick"}`
	strReader := strings.NewReader(bodyStr)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadString()
	st.Expect(t, err, nil)
	st.Expect(t, str, bodyStr)
}

func TestReadStringError(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadString()
	st.Expect(t, err, errRead)
	st.Expect(t, str, "")
}

func TestReadBytes(t *testing.T) {
	bodyBytes := []byte(`{"name":"Rick"}`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadBytes()
	st.Expect(t, err, nil)
	st.Expect(t, str, bodyBytes)
}

func TestReadBytesError(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	buf, err := modifier.ReadBytes()
	st.Expect(t, err, errRead)
	st.Expect(t, len(buf), 0)
}

func TestDecodeJSON(t *testing.T) {
	bodyBytes := []byte(`{"name":"Rick"}`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "Rick")
}

func TestDecodeJSONErrorFromReadBytes(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, errRead)
	st.Expect(t, u.Name, "")
}

func TestDecodeJSONEOF(t *testing.T) {
	bodyBytes := []byte("")
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "")
}

func TestDecodeJSONErrorFromDecode(t *testing.T) {
	bodyBytes := []byte(`/`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	_, ok := (err).(*json.SyntaxError)
	st.Expect(t, ok, true)
	st.Expect(t, err.Error(), "invalid character '/' looking for beginning of value")
	st.Expect(t, u.Name, "")
}

func TestDecodeXML(t *testing.T) {
	bodyBytes := []byte(`<Person><Name>Rick</Name></Person>`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "Rick")
}

func TestDecodeXMLErrorFromReadBytes(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, errRead)
	st.Expect(t, u.Name, "")
}

func TestDecodeXMLErrorFromDecode(t *testing.T) {
	bodyBytes := []byte(`]]>`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	_, ok := (err).(*xml.SyntaxError)
	st.Expect(t, ok, true)
	st.Expect(t, err.Error(), "XML syntax error on line 1: unescaped ]]> not in CDATA section")
	st.Expect(t, u.Name, "")
}

func TestDecodeXMLEOF(t *testing.T) {
	bodyBytes := []byte("")
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "")
}

func TestBytes(t *testing.T) {
	req := &http.Request{Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.Bytes([]byte("hello"))
	modifiedBody, err := ioutil.ReadAll(req.Body)
	st.Expect(t, err, nil)
	st.Expect(t, modifiedBody, []byte("hello"))
}

func TestStringGet(t *testing.T) {
	req := &http.Request{Method: "GET", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	st.Expect(t, req.Body, nil)
}

func TestStringHead(t *testing.T) {
	req := &http.Request{Method: "HEAD", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	st.Expect(t, req.Body, nil)
}

func TestString(t *testing.T) {
	req := &http.Request{Method: "POST", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	modifiedBody, err := ioutil.ReadAll(req.Body)
	st.Expect(t, err, nil)
	st.Expect(t, modifiedBody, []byte("hello"))
}
<commit_msg>feat(test): Add test for JSON with struct data<commit_after>package intercept

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"github.com/nbio/st"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

var errRead = errors.New("read error")

type errorReader struct{}

func (r *errorReader) Read(p []byte) (int, error) {
	return 0, errRead
}

type user struct {
	XMLName xml.Name `xml:"Person" json:"-"`
	Name    string
}

func TestNewRequestModifier(t *testing.T) {
	h := http.Header{}
	h.Set("foo", "bar")
	req := &http.Request{Header: h}
	modifier := NewRequestModifier(req)
	st.Expect(t, modifier.Request, req)
	st.Expect(t, modifier.Header, h)
}

func TestReadString(t *testing.T) {
	bodyStr := `{"name":"Rick"}`
	strReader := strings.NewReader(bodyStr)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadString()
	st.Expect(t, err, nil)
	st.Expect(t, str, bodyStr)
}

func TestReadStringError(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadString()
	st.Expect(t, err, errRead)
	st.Expect(t, str, "")
}

func TestReadBytes(t *testing.T) {
	bodyBytes := []byte(`{"name":"Rick"}`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	str, err := modifier.ReadBytes()
	st.Expect(t, err, nil)
	st.Expect(t, str, bodyBytes)
}

func TestReadBytesError(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	buf, err := modifier.ReadBytes()
	st.Expect(t, err, errRead)
	st.Expect(t, len(buf), 0)
}

func TestDecodeJSON(t *testing.T) {
	bodyBytes := []byte(`{"name":"Rick"}`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "Rick")
}

func TestDecodeJSONErrorFromReadBytes(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, errRead)
	st.Expect(t, u.Name, "")
}

func TestDecodeJSONEOF(t *testing.T) {
	bodyBytes := []byte("")
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "")
}

func TestDecodeJSONErrorFromDecode(t *testing.T) {
	bodyBytes := []byte(`/`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeJSON(&u)
	_, ok := (err).(*json.SyntaxError)
	st.Expect(t, ok, true)
	st.Expect(t, err.Error(), "invalid character '/' looking for beginning of value")
	st.Expect(t, u.Name, "")
}

func TestDecodeXML(t *testing.T) {
	bodyBytes := []byte(`<Person><Name>Rick</Name></Person>`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "Rick")
}

func TestDecodeXMLErrorFromReadBytes(t *testing.T) {
	body := ioutil.NopCloser(&errorReader{})
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, errRead)
	st.Expect(t, u.Name, "")
}

func TestDecodeXMLErrorFromDecode(t *testing.T) {
	bodyBytes := []byte(`]]>`)
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	_, ok := (err).(*xml.SyntaxError)
	st.Expect(t, ok, true)
	st.Expect(t, err.Error(), "XML syntax error on line 1: unescaped ]]> not in CDATA section")
	st.Expect(t, u.Name, "")
}

func TestDecodeXMLEOF(t *testing.T) {
	bodyBytes := []byte("")
	strReader := bytes.NewBuffer(bodyBytes)
	body := ioutil.NopCloser(strReader)
	req := &http.Request{Header: http.Header{}, Body: body}
	modifier := NewRequestModifier(req)
	u := user{}
	err := modifier.DecodeXML(&u, nil)
	st.Expect(t, err, nil)
	st.Expect(t, u.Name, "")
}

func TestBytes(t *testing.T) {
	req := &http.Request{Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.Bytes([]byte("hello"))
	modifiedBody, err := ioutil.ReadAll(req.Body)
	st.Expect(t, err, nil)
	st.Expect(t, string(modifiedBody), "hello")
}

func TestStringGet(t *testing.T) {
	req := &http.Request{Method: "GET", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	st.Expect(t, req.Body, nil)
}

func TestStringHead(t *testing.T) {
	req := &http.Request{Method: "HEAD", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	st.Expect(t, req.Body, nil)
}

func TestString(t *testing.T) {
	req := &http.Request{Method: "POST", Header: http.Header{}}
	modifier := NewRequestModifier(req)
	modifier.String("hello")
	modifiedBody, err := ioutil.ReadAll(req.Body)
	st.Expect(t, err, nil)
	st.Expect(t, string(modifiedBody), "hello")
}

func TestJSONWithStructAsParameter(t *testing.T) {
	req := &http.Request{Header: http.Header{}}
	modifier := NewRequestModifier(req)
	u := &user{Name: "Rick"}
	err := modifier.JSON(u)
	st.Expect(t, err, nil)
	modifiedBody, err := ioutil.ReadAll(req.Body)
	st.Expect(t, err, nil)
	expectedBody := "{\"Name\":\"Rick\"}\n"
	st.Expect(t, string(modifiedBody), expectedBody)
	st.Expect(t, req.ContentLength, int64(len(expectedBody)))
	st.Expect(t, req.Header.Get("Content-Type"), "application/json")
}
<|endoftext|>


<commit_before>package resp

import (
	"bytes"
	"strconv"

	"redisgreen.net/respio"
)

type MessageOp int

const (
	MSG_OP_UNCHECKED = MessageOp(iota)
	MSG_OP_AUTH
	MSG_OP_SELECT
	MSG_OP_BROKEN
	MSG_OP_OTHER
)

func (m MessageOp) String() string {
	switch m {
	case MSG_OP_AUTH:
		return "AUTH"
	case MSG_OP_SELECT:
		return "SELECT"
	case MSG_OP_OTHER:
		return "OTHER"
	default:
		return "?"
	}
}

type Msg struct {
	data []byte

	op          MessageOp
	firstArg    string
	firstArgInt int
}

func MsgFromStrings(args ...string) *Msg {
	buf := new(bytes.Buffer)
	respio.NewRESPWriter(buf).WriteCommand(args...)
	return &Msg{data: buf.Bytes()}
}

func (m *Msg) String() string {
	return string(m.data)
}

func (m *Msg) Data() []byte {
	return m.data
}

func (m *Msg) Equal(other *Msg) bool {
	return bytes.Equal(m.data, other.data)
}

////////////////////
// Message analysis.
//
// Majority of messages have no meaning to the proxy and it does not
// make any sense to parse them.

func (m *Msg) Op() MessageOp {
	m.analyse()
	return m.op
}

func (m *Msg) FirstArg() string {
	return m.firstArg
}

func (m *Msg) FirstArgInt() int {
	return m.firstArgInt
}

func (m *Msg) IsOk() bool {
	return bytes.Equal(m.data, MSG_DATA_OK)
}

var PREFIX_AUTH []byte
var PREFIX_SELECT []byte
var MSG_DATA_OK []byte

func init() {
	PREFIX_AUTH = []byte("*2\r\n$4\r\nAUTH\r\n$")
	PREFIX_SELECT = []byte("*2\r\n$6\r\nSELECT\r\n$")
	MSG_DATA_OK = []byte("+OK\r\n")
}

func (m *Msg) analyse() {
	if m.op != MSG_OP_UNCHECKED {
		return
	}

	var suff []byte

	switch {
	case bytes.EqualFold(m.data[:len(PREFIX_AUTH)], PREFIX_AUTH):
		m.op = MSG_OP_AUTH
		suff = m.data[len(PREFIX_AUTH):]

	case bytes.EqualFold(m.data[:len(PREFIX_SELECT)], PREFIX_SELECT):
		m.op = MSG_OP_SELECT
		suff = m.data[len(PREFIX_SELECT):]

	default:
		m.op = MSG_OP_OTHER
	}

	if (m.op == MSG_OP_AUTH) || (m.op == MSG_OP_SELECT) {
		end := bytes.IndexByte(suff, '\r')
		n, err := strconv.Atoi(string(suff[:end]))
		if err != nil {
			m.op = MSG_OP_BROKEN
			return
		}
		m.firstArg = string(suff[end+2 : end+2+n])
	}

	if m.op == MSG_OP_SELECT {
		var err error
		m.firstArgInt, err = strconv.Atoi(m.firstArg)
		if err != nil {
			m.op = MSG_OP_BROKEN
		}
	}
}
<commit_msg>Cleanup.<commit_after>package resp

import (
	"bytes"
	"strconv"

	"redisgreen.net/respio"
)

type MessageOp int

const (
	MSG_OP_UNCHECKED = MessageOp(iota)
	MSG_OP_AUTH
	MSG_OP_SELECT
	MSG_OP_BROKEN
	MSG_OP_OTHER
)

func (m MessageOp) String() string {
	switch m {
	case MSG_OP_AUTH:
		return "AUTH"
	case MSG_OP_SELECT:
		return "SELECT"
	case MSG_OP_OTHER:
		return "OTHER"
	default:
		return "?"
	}
}

type Msg struct {
	data []byte

	op          MessageOp
	firstArg    string
	firstArgInt int
}

func MsgFromStrings(args ...string) *Msg {
	buf := new(bytes.Buffer)
	respio.NewRESPWriter(buf).WriteCommand(args...)
	return &Msg{data: buf.Bytes()}
}

func (m *Msg) String() string {
	return string(m.data)
}

func (m *Msg) Data() []byte {
	return m.data
}

func (m *Msg) Equal(other *Msg) bool {
	return bytes.Equal(m.data, other.data)
}

////////////////////
// Message analysis.
//
// Majority of messages have no meaning to the proxy and it does not
// make any sense to parse them.

func (m *Msg) Op() MessageOp {
	m.analyse()
	return m.op
}

func (m *Msg) FirstArg() string {
	return m.firstArg
}

func (m *Msg) FirstArgInt() int {
	return m.firstArgInt
}

func (m *Msg) IsOk() bool {
	return bytes.Equal(m.data, MSG_DATA_OK)
}

var MSG_PREFIX_MAP = []struct {
	prefix []byte
	op     MessageOp
}{
	{[]byte("*2\r\n$4\r\nAUTH\r\n$"), MSG_OP_AUTH},
	{[]byte("*2\r\n$6\r\nSELECT\r\n$"), MSG_OP_SELECT},
}

var MSG_DATA_OK = []byte("+OK\r\n")

func (m *Msg) analyse() {
	if m.op != MSG_OP_UNCHECKED {
		return
	}

	m.op = MSG_OP_OTHER
	for _, def := range MSG_PREFIX_MAP {
		if bytes.EqualFold(def.prefix, m.data[:len(def.prefix)]) {
			m.op = def.op

			suff := m.data[len(def.prefix):]
			end := bytes.IndexByte(suff, '\r')
			n, err := strconv.Atoi(string(suff[:end]))
			if err != nil {
				m.op = MSG_OP_BROKEN
				return
			}
			m.firstArg = string(suff[end+2 : end+2+n])
		}
	}

	if m.op == MSG_OP_SELECT {
		var err error
		m.firstArgInt, err = strconv.Atoi(m.firstArg)
		if err != nil {
			m.op = MSG_OP_BROKEN
		}
	}
}
<|endoftext|>


<commit_before>package osdn

import (
	"fmt"

	log "github.com/golang/glog"

	"github.com/openshift/openshift-sdn/pkg/netutils"

	kapi "k8s.io/kubernetes/pkg/api"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/container"
)

const (
	// Maximum VXLAN Network Identifier as per RFC#7348
	MaxVNID = ((1 << 24) - 1)
	// VNID for the admin namespaces
	AdminVNID = uint(0)
)

func (oc *OsdnController) VnidStartMaster() error {
	nets, err := oc.Registry.GetNetNamespaces()
	if err != nil {
		return err
	}
	inUse := make([]uint, 0)
	for _, net := range nets {
		if net.NetID != AdminVNID {
			inUse = append(inUse, net.NetID)
		}
		oc.VNIDMap[net.Name] = net.NetID
	}
	// VNID: 0 reserved for default namespace and can reach any network in the cluster
	// VNID: 1 to 9 are internally reserved for any special cases in the future
	oc.netIDManager, err = netutils.NewNetIDAllocator(10, MaxVNID, inUse)
	if err != nil {
		return err
	}

	// 'default' namespace is currently always an admin namespace
	oc.adminNamespaces = append(oc.adminNamespaces, "default")

	go watchNamespaces(oc)
	return nil
}

func (oc *OsdnController) isAdminNamespace(nsName string) bool {
	for _, name := range oc.adminNamespaces {
		if name == nsName {
			return true
		}
	}
	return false
}

func (oc *OsdnController) assignVNID(namespaceName string) error {
	_, err := oc.Registry.GetNetNamespace(namespaceName)
	if err == nil {
		return nil
	}
	var netid uint
	if oc.isAdminNamespace(namespaceName) {
		netid = AdminVNID
	} else {
		var err error
		netid, err = oc.netIDManager.GetNetID()
		if err != nil {
			return err
		}
	}
	err = oc.Registry.WriteNetNamespace(namespaceName, netid)
	if err != nil {
		e := oc.netIDManager.ReleaseNetID(netid)
		if e != nil {
			log.Errorf("Error while releasing Net ID: %v", e)
		}
		return err
	}
	oc.VNIDMap[namespaceName] = netid
	log.Infof("Assigned id %d to namespace %q", netid, namespaceName)
	return nil
}

func (oc *OsdnController) revokeVNID(namespaceName string) error {
	err := oc.Registry.DeleteNetNamespace(namespaceName)
	if err != nil {
		return err
	}
	netid, found := oc.VNIDMap[namespaceName]
	if !found {
		return fmt.Errorf("Error while fetching Net ID for namespace: %s", namespaceName)
	}
	delete(oc.VNIDMap, namespaceName)

	// Skip AdminVNID as it is not part of Net ID allocation
	if netid == AdminVNID {
		return nil
	}

	// Check if this netid is used by any other namespaces
	// If not, then release the netid
	netid_inuse := false
	for name, id := range oc.VNIDMap {
		if id == netid {
			netid_inuse = true
			log.V(5).Infof("Net ID %d for namespace %q is still in use by namespace %q", netid, namespaceName, name)
			break
		}
	}
	if !netid_inuse {
		err = oc.netIDManager.ReleaseNetID(netid)
		if err != nil {
			return fmt.Errorf("Error while releasing Net ID: %v", err)
		} else {
			log.Infof("Released netid %d for namespace %q", netid, namespaceName)
		}
	}
	return nil
}

func watchNamespaces(oc *OsdnController) {
	nsevent := make(chan *NamespaceEvent)
	go oc.Registry.WatchNamespaces(nsevent)
	for {
		ev := <-nsevent
		switch ev.Type {
		case Added:
			err := oc.assignVNID(ev.Namespace.Name)
			if err != nil {
				log.Errorf("Error assigning Net ID: %v", err)
				continue
			}
		case Deleted:
			err := oc.revokeVNID(ev.Namespace.Name)
			if err != nil {
				log.Errorf("Error revoking Net ID: %v", err)
				continue
			}
		}
	}
}

func (oc *OsdnController) VnidStartNode() error {
	go watchNetNamespaces(oc)
	go watchServices(oc)
	go watchPods(oc)
	return nil
}

func (oc *OsdnController) updatePodNetwork(namespace string, netID uint) error {
	// Update OF rules for the existing/old pods in the namespace
	pods, err := oc.GetLocalPods(namespace)
	if err != nil {
		return err
	}
	for _, pod := range pods {
		err := oc.pluginHooks.UpdatePod(pod.Namespace, pod.Name, kubetypes.DockerID(GetPodContainerID(&pod)))
		if err != nil {
			return err
		}
	}

	// Update OF rules for the old services in the namespace
	services, err := oc.Registry.GetServicesForNamespace(namespace)
	if err != nil {
		return err
	}
	for _, svc := range services {
		oc.pluginHooks.DeleteServiceRules(&svc)
		oc.pluginHooks.AddServiceRules(&svc, netID)
	}
	return nil
}

func watchNetNamespaces(oc *OsdnController) {
	netNsEvent := make(chan *NetNamespaceEvent)
	go oc.Registry.WatchNetNamespaces(netNsEvent)
	for {
		ev := <-netNsEvent
		switch ev.Type {
		case Added:
			// Skip this event if the old and new network ids are same
			if oldNetID, ok := oc.VNIDMap[ev.NetNamespace.NetName]; ok && (oldNetID == ev.NetNamespace.NetID) {
				continue
			}
			oc.VNIDMap[ev.NetNamespace.Name] = ev.NetNamespace.NetID
			err := oc.updatePodNetwork(ev.NetNamespace.NetName, ev.NetNamespace.NetID)
			if err != nil {
				log.Errorf("Failed to update pod network for namespace '%s', error: %s", ev.NetNamespace.NetName, err)
			}
		case Deleted:
			err := oc.updatePodNetwork(ev.NetNamespace.NetName, AdminVNID)
			if err != nil {
				log.Errorf("Failed to update pod network for namespace '%s', error: %s", ev.NetNamespace.NetName, err)
			}
			delete(oc.VNIDMap, ev.NetNamespace.NetName)
		}
	}
}

func watchServices(oc *OsdnController) {
	svcevent := make(chan *ServiceEvent)
	go oc.Registry.WatchServices(svcevent)
	for {
		ev := <-svcevent
		var netid uint
		if ev.Type != Deleted {
			var found bool
			netid, found = oc.VNIDMap[ev.Service.Namespace]
			if !found {
				log.Errorf("Error fetching Net ID for namespace: %s, skipped serviceEvent: %v", ev.Service.Namespace, ev)
				continue
			}
		}
		switch ev.Type {
		case Added:
			oc.services[string(ev.Service.UID)] = ev.Service
			oc.pluginHooks.AddServiceRules(ev.Service, netid)
		case Deleted:
			delete(oc.services, string(ev.Service.UID))
			oc.pluginHooks.DeleteServiceRules(ev.Service)
		case Modified:
			oldsvc, exists := oc.services[string(ev.Service.UID)]
			if exists && len(oldsvc.Spec.Ports) == len(ev.Service.Spec.Ports) {
				same := true
				for i := range oldsvc.Spec.Ports {
					if oldsvc.Spec.Ports[i].Protocol != ev.Service.Spec.Ports[i].Protocol || oldsvc.Spec.Ports[i].Port != ev.Service.Spec.Ports[i].Port {
						same = false
						break
					}
				}
				if same {
					continue
				}
			}
			if exists {
				oc.pluginHooks.DeleteServiceRules(oldsvc)
			}
			oc.services[string(ev.Service.UID)] = ev.Service
			oc.pluginHooks.AddServiceRules(ev.Service, netid)
		}
	}
}

func watchPods(oc *OsdnController) {
	oc.Registry.WatchPods()
}
<commit_msg>Prepopulate VNIDMap for VnidStartMaster/VnidStartNode methods<commit_after>package osdn

import (
	"fmt"

	log "github.com/golang/glog"

	"github.com/openshift/openshift-sdn/pkg/netutils"

	kapi "k8s.io/kubernetes/pkg/api"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/container"
)

const (
	// Maximum VXLAN Network Identifier as per RFC#7348
	MaxVNID = ((1 << 24) - 1)
	// VNID for the admin namespaces
	AdminVNID = uint(0)
)

func populateVNIDMap(oc *OsdnController) error {
	nets, err := oc.Registry.GetNetNamespaces()
	if err != nil {
		return err
	}

	for _, net := range nets {
		oc.VNIDMap[net.Name] = net.NetID
	}
	return nil
}

func (oc *OsdnController) VnidStartMaster() error {
	err := populateVNIDMap(oc)
	if err != nil {
		return err
	}

	inUse := make([]uint, 0)
	for _, netid := range oc.VNIDMap {
		if netid != AdminVNID {
			inUse = append(inUse, netid)
		}
	}
	// VNID: 0 reserved for default namespace and can reach any network in the cluster
	// VNID: 1 to 9 are internally reserved for any special cases in the future
	oc.netIDManager, err = netutils.NewNetIDAllocator(10, MaxVNID, inUse)
	if err != nil {
		return err
	}

	// 'default' namespace is currently always an admin namespace
	oc.adminNamespaces = append(oc.adminNamespaces, "default")

	go watchNamespaces(oc)
	return nil
}

func (oc *OsdnController) isAdminNamespace(nsName string) bool {
	for _, name := range oc.adminNamespaces {
		if name == nsName {
			return true
		}
	}
	return false
}

func (oc *OsdnController) assignVNID(namespaceName string) error {
	_, err := oc.Registry.GetNetNamespace(namespaceName)
	if err == nil {
		return nil
	}
	var netid uint
	if oc.isAdminNamespace(namespaceName) {
		netid = AdminVNID
	} else {
		var err error
		netid, err = oc.netIDManager.GetNetID()
		if err != nil {
			return err
		}
	}
	err = oc.Registry.WriteNetNamespace(namespaceName, netid)
	if err != nil {
		e := oc.netIDManager.ReleaseNetID(netid)
		if e != nil {
			log.Errorf("Error while releasing Net ID: %v", e)
		}
		return err
	}
	oc.VNIDMap[namespaceName] = netid
	log.Infof("Assigned id %d to namespace %q", netid, namespaceName)
	return nil
}

func (oc *OsdnController) revokeVNID(namespaceName string) error {
	err := oc.Registry.DeleteNetNamespace(namespaceName)
	if err != nil {
		return err
	}
	netid, found := oc.VNIDMap[namespaceName]
	if !found {
		return fmt.Errorf("Error while fetching Net ID for namespace: %s", namespaceName)
	}
	delete(oc.VNIDMap, namespaceName)

	// Skip AdminVNID as it is not part of Net ID allocation
	if netid == AdminVNID {
		return nil
	}

	// Check if this netid is used by any other namespaces
	// If not, then release the netid
	netid_inuse := false
	for name, id := range oc.VNIDMap {
		if id == netid {
			netid_inuse = true
			log.V(5).Infof("Net ID %d for namespace %q is still in use by namespace %q", netid, namespaceName, name)
			break
		}
	}
	if !netid_inuse {
		err = oc.netIDManager.ReleaseNetID(netid)
		if err != nil {
			return fmt.Errorf("Error while releasing Net ID: %v", err)
		} else {
			log.Infof("Released netid %d for namespace %q", netid, namespaceName)
		}
	}
	return nil
}

func watchNamespaces(oc *OsdnController) {
	nsevent := make(chan *NamespaceEvent)
	go oc.Registry.WatchNamespaces(nsevent)
	for {
		ev := <-nsevent
		switch ev.Type {
		case Added:
			err := oc.assignVNID(ev.Namespace.Name)
			if err != nil {
				log.Errorf("Error assigning Net ID: %v", err)
				continue
			}
		case Deleted:
			err := oc.revokeVNID(ev.Namespace.Name)
			if err != nil {
				log.Errorf("Error revoking Net ID: %v", err)
				continue
			}
		}
	}
}

func (oc *OsdnController) VnidStartNode() error {
	err := populateVNIDMap(oc)
	if err != nil {
		return err
	}

	go watchNetNamespaces(oc)
	go watchServices(oc)
	go watchPods(oc)
	return nil
}

func (oc *OsdnController) updatePodNetwork(namespace string, netID uint) error {
	// Update OF rules for the existing/old pods in the namespace
	pods, err := oc.GetLocalPods(namespace)
	if err != nil {
		return err
	}
	for _, pod := range pods {
		err := oc.pluginHooks.UpdatePod(pod.Namespace, pod.Name, kubetypes.DockerID(GetPodContainerID(&pod)))
		if err != nil {
			return err
		}
	}

	// Update OF rules for the old services in the namespace
	services, err := oc.Registry.GetServicesForNamespace(namespace)
	if err != nil {
		return err
	}
	for _, svc := range services {
		oc.pluginHooks.DeleteServiceRules(&svc)
		oc.pluginHooks.AddServiceRules(&svc, netID)
	}
	return nil
}

func watchNetNamespaces(oc *OsdnController) {
	netNsEvent := make(chan *NetNamespaceEvent)
	go oc.Registry.WatchNetNamespaces(netNsEvent)
	for {
		ev := <-netNsEvent
		switch ev.Type {
		case Added:
			// Skip this event if the old and new network ids are same
			if oldNetID, ok := oc.VNIDMap[ev.NetNamespace.NetName]; ok && (oldNetID == ev.NetNamespace.NetID) {
				continue
			}
			oc.VNIDMap[ev.NetNamespace.Name] = ev.NetNamespace.NetID
			err := oc.updatePodNetwork(ev.NetNamespace.NetName, ev.NetNamespace.NetID)
			if err != nil {
				log.Errorf("Failed to update pod network for namespace '%s', error: %s", ev.NetNamespace.NetName, err)
			}
		case Deleted:
			err := oc.updatePodNetwork(ev.NetNamespace.NetName, AdminVNID)
			if err != nil {
				log.Errorf("Failed to update pod network for namespace '%s', error: %s", ev.NetNamespace.NetName, err)
			}
			delete(oc.VNIDMap, ev.NetNamespace.NetName)
		}
	}
}

func watchServices(oc *OsdnController) {
	svcevent := make(chan *ServiceEvent)
	go oc.Registry.WatchServices(svcevent)

	for {
		ev := <-svcevent
		var netid uint
		if ev.Type != Deleted {
			var found bool
			netid, found = oc.VNIDMap[ev.Service.Namespace]
			if !found {
				log.Errorf("Error fetching Net ID for namespace: %s, skipped serviceEvent: %v", ev.Service.Namespace, ev)
				continue
			}
		}
		switch ev.Type {
		case Added:
			oc.services[string(ev.Service.UID)] = ev.Service
			oc.pluginHooks.AddServiceRules(ev.Service, netid)
		case Deleted:
			delete(oc.services, string(ev.Service.UID))
			oc.pluginHooks.DeleteServiceRules(ev.Service)
		case Modified:
			oldsvc, exists := oc.services[string(ev.Service.UID)]
			if exists && len(oldsvc.Spec.Ports) == len(ev.Service.Spec.Ports) {
				same := true
				for i := range oldsvc.Spec.Ports {
					if oldsvc.Spec.Ports[i].Protocol != ev.Service.Spec.Ports[i].Protocol || oldsvc.Spec.Ports[i].Port != ev.Service.Spec.Ports[i].Port {
						same = false
						break
					}
				}
				if same {
					continue
				}
			}
			if exists {
				oc.pluginHooks.DeleteServiceRules(oldsvc)
			}
			oc.services[string(ev.Service.UID)] = ev.Service
			oc.pluginHooks.AddServiceRules(ev.Service, netid)
		}
	}
}

func watchPods(oc *OsdnController) {
	oc.Registry.WatchPods()
}
<|endoftext|>


<commit_before>package plugins

import (
	"time"

	"github.com/aphistic/sweet"
	"github.com/efritz/glock"
	"github.com/efritz/overcurrent"
	. "github.com/onsi/gomega"
)

type StatsSuite struct{}

var testConfig = overcurrent.BreakerConfig{
	MaxConcurrency: 50,
}

func (s *StatsSuite) TestConfig(t sweet.T) {
	stats := NewBreakerStats(testConfig)
	Expect(stats.config.MaxConcurrency).To(Equal(50))
}

func (s *StatsSuite) TestState(t sweet.T) {
	stats := NewBreakerStats(testConfig)
	stats.SetState(overcurrent.StateHalfClosed)
	Expect(stats.state).To(Equal(overcurrent.StateHalfClosed))
}

func (s *StatsSuite) TestIncrement(t sweet.T) {
	clock := glock.NewMockClock()
	stats := newBreakerStatsWithClock(testConfig, clock)

	for j := 0; j < 30; j++ {
		clock.Advance(time.Second)

		for i := 0; i < 20; i++ {
			stats.Increment(overcurrent.EventTypeSuccess)
		}
	}

	// Should be 200, not 600 due to pruning the first 20 (of 30) seconds
	Expect(stats.Freeze().counters[overcurrent.EventTypeSuccess]).To(Equal(200))
}

func (s *StatsSuite) TestIncrementDual(t sweet.T) {
	clock := glock.NewMockClock()
	stats := newBreakerStatsWithClock(testConfig, clock)

	for _, pair := range [][]int{[]int{10, 5}, []int{50, 20}, []int{10, 30}} {
		for i := 0; i < pair[0]; i++ {
			stats.Increment(overcurrent.EventTypeSemaphoreAcquired)
		}

		for i := 0; i < pair[1]; i++ {
			stats.Increment(overcurrent.EventTypeSemaphoreReleased)
		}

		clock.Advance(time.Second)
	}

	frozen1 := stats.Freeze()
	Expect(frozen1.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen1.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(55))
	Expect(frozen1.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(70))
	Expect(frozen1.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(55))

	//
	// Test behavior of expiring buckets
	//

	clock.Advance(time.Second * 7)
	frozen2 := stats.Freeze()
	Expect(frozen2.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen2.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(55))
	Expect(frozen2.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(60))
	Expect(frozen2.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(50))

	clock.Advance(time.Second * 1)
	frozen3 := stats.Freeze()
	Expect(frozen3.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen3.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(45))
	Expect(frozen3.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(10))
	Expect(frozen3.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(30))

	clock.Advance(time.Second * 1)
	frozen4 := stats.Freeze()
	Expect(frozen4.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen4.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen4.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(0))
	Expect(frozen4.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(0))
}

func (s *StatsSuite) TestAddDuration(t sweet.T) {
	// TODO
}
<commit_msg>Finish outstanding stats test.<commit_after>package plugins

import (
	"time"

	"github.com/aphistic/sweet"
	"github.com/efritz/glock"
	"github.com/efritz/overcurrent"
	. "github.com/onsi/gomega"
)

type StatsSuite struct{}

var testConfig = overcurrent.BreakerConfig{
	MaxConcurrency: 50,
}

func (s *StatsSuite) TestConfig(t sweet.T) {
	stats := NewBreakerStats(testConfig)
	Expect(stats.config.MaxConcurrency).To(Equal(50))
}

func (s *StatsSuite) TestState(t sweet.T) {
	stats := NewBreakerStats(testConfig)
	stats.SetState(overcurrent.StateHalfClosed)
	Expect(stats.state).To(Equal(overcurrent.StateHalfClosed))
}

func (s *StatsSuite) TestIncrement(t sweet.T) {
	clock := glock.NewMockClock()
	stats := newBreakerStatsWithClock(testConfig, clock)

	for j := 0; j < 30; j++ {
		clock.Advance(time.Second)

		for i := 0; i < 20; i++ {
			stats.Increment(overcurrent.EventTypeSuccess)
		}
	}

	// Should be 200, not 600 due to pruning the first 20 (of 30) seconds
	Expect(stats.Freeze().counters[overcurrent.EventTypeSuccess]).To(Equal(200))
}

func (s *StatsSuite) TestIncrementDual(t sweet.T) {
	clock := glock.NewMockClock()
	stats := newBreakerStatsWithClock(testConfig, clock)

	for _, pair := range [][]int{[]int{10, 5}, []int{50, 20}, []int{10, 30}} {
		for i := 0; i < pair[0]; i++ {
			stats.Increment(overcurrent.EventTypeSemaphoreAcquired)
		}

		for i := 0; i < pair[1]; i++ {
			stats.Increment(overcurrent.EventTypeSemaphoreReleased)
		}

		clock.Advance(time.Second)
	}

	frozen1 := stats.Freeze()
	Expect(frozen1.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen1.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(55))
	Expect(frozen1.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(70))
	Expect(frozen1.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(55))

	//
	// Test behavior of expiring buckets
	//

	clock.Advance(time.Second * 7)
	frozen2 := stats.Freeze()
	Expect(frozen2.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen2.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(55))
	Expect(frozen2.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(60))
	Expect(frozen2.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(50))

	clock.Advance(time.Second * 1)
	frozen3 := stats.Freeze()
	Expect(frozen3.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen3.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(45))
	Expect(frozen3.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(10))
	Expect(frozen3.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(30))

	clock.Advance(time.Second * 1)
	frozen4 := stats.Freeze()
	Expect(frozen4.currents[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen4.maximums[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(15))
	Expect(frozen4.counters[overcurrent.EventTypeSemaphoreAcquired]).To(Equal(0))
	Expect(frozen4.counters[overcurrent.EventTypeSemaphoreReleased]).To(Equal(0))
}

func (s *StatsSuite) TestAddDuration(t sweet.T) {
	clock := glock.NewMockClock()
	stats := newBreakerStatsWithClock(testConfig, clock)

	for j := 0; j < 30; j++ {
		clock.Advance(time.Second)

		for i := 1; i <= 20; i++ {
			stats.AddDuration(overcurrent.EventTypeRunDuration, time.Second*time.Duration(i))
		}
	}

	expected := []time.Duration{}
	for i := 1; i <= 20; i++ {
		for j := 0; j < 10; j++ {
			expected = append(expected, time.Second*time.Duration(i))
		}
	}

	// Should be sorted
	Expect(stats.Freeze().durations[overcurrent.EventTypeRunDuration]).To(Equal(expected))
}
<|endoftext|>


<commit_before>package uno

import (
	"errors"
	"strings"

	"github.com/Unknwon/com"
	"github.com/belak/go-seabird"
	"github.com/belak/go-seabird/plugins"
	"github.com/go-irc/irc"
)

func init() {
	seabird.RegisterPlugin("uno", newUnoPlugin)
}

type unoPlugin struct {
	games   map[string]*Game
	tracker *plugins.ChannelTracker

	BlacklistedChannels []string
	BlacklistedMessage  string
}

func newUnoPlugin(b *seabird.Bot, cm *seabird.CommandMux, tracker *plugins.ChannelTracker) error {
	p := &unoPlugin{
		games:   make(map[string]*Game),
		tracker: tracker,

		BlacklistedMessage: "Uno is blacklisted in this channel.",
	}

	err := b.Config("uno", p)
	if err != nil {
		return err
	}

	// TODO: Track channel parts

	cm.Channel("uno", p.unoCallback, &seabird.HelpInfo{
		Usage:       "[create|join|start|stop]",
		Description: "Flow control and stuff",
	})

	cm.Channel("hand", p.handCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Messages you your hand in an UNO game",
	})

	cm.Channel("play", p.playCallback, &seabird.HelpInfo{
		Usage:       "<hand_index>",
		Description: "Plays card from your hand at <hand_index> and ends your turn",
	})

	cm.Channel("draw", p.drawCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Draws a card and possibly ends your turn",
	})

	cm.Channel("draw_play", p.drawPlayCallback, &seabird.HelpInfo{
		Usage:       "[yes|no]",
		Description: "Used after a call to <prefix>draw to possibly play a card",
	})

	cm.Channel("color", p.colorCallback, &seabird.HelpInfo{
		Usage:       "red|yellow|green|blue",
		Description: "Selects next color to play",
	})

	cm.Channel("uno_state", p.stateCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Return the top card and current player.",
	})

	return nil
}

func (p *unoPlugin) lookupDataRaw(b *seabird.Bot, m *irc.Message) (*plugins.User, *Game) {
	user := p.tracker.LookupUser(m.Prefix.Name)
	game := p.games[m.Params[0]]

	return user, game
}

func (p *unoPlugin) lookupData(b *seabird.Bot, m *irc.Message) (*plugins.User, *Game, error) {
	user, game := p.lookupDataRaw(b, m)

	if user == nil {
		return user, game, errors.New("Couldn't find user")
	}

	if game == nil {
		return user, game, errors.New("No game in this channel")
	}

	return user, game, nil
}

// sendMessages is an abstraction around sending the uno Message
// type. This simplifies the translation between that and IRC.
func (p *unoPlugin) sendMessages(b *seabird.Bot, m *irc.Message, uMsgs []*Message) {
	for _, uMsg := range uMsgs {
		if uMsg.Target == nil {
			b.Reply(m, "%s", uMsg.Message)
		} else if uMsg.Private {
			b.Send(&irc.Message{
				Command: "NOTICE",
				Params: []string{
					uMsg.Target.Nick,
					uMsg.Message,
				},
			})
		} else {
			b.Reply(m, "%s: %s", uMsg.Target.Nick, uMsg.Message)
		}
	}
}

func (p *unoPlugin) stateCallback(b *seabird.Bot, m *irc.Message) {
	user, game := p.lookupDataRaw(b, m)
	if user == nil {
		b.MentionReply(m, "Couldn't find user")
		return
	}

	if game == nil {
		b.MentionReply(m, "There's no game in this channel")
		return
	}

	// TODO: This should pull from some State struct or similar from
	// the Game
	if game.state == stateNew {
		b.MentionReply(m, "Game hasn't been started yet")
		return
	}
	b.MentionReply(m, "Current Player: %s", game.currentPlayer().User.Nick)
	b.MentionReply(m, "Top Card: %s", game.lastPlayed())
}

func (p *unoPlugin) unoCallback(b *seabird.Bot, m *irc.Message) {
	trailing := strings.TrimSpace(m.Trailing())

	if len(trailing) == 0 {
		p.rawUnoCallback(b, m)
		return
	}

	switch trailing {
	case "create":
		p.createCallback(b, m)
	case "join":
		p.joinCallback(b, m)
	case "start":
		p.startCallback(b, m)
	case "stop":
		p.stopCallback(b, m)
	default:
		b.MentionReply(m, "Usage: <prefix>uno [create|join|start|stop]")
	}
}

func (p *unoPlugin) rawUnoCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.SayUno(user))
}

func (p *unoPlugin) createCallback(b *seabird.Bot, m *irc.Message) {
	// If the current channel is in the blacklist.
	if com.IsSliceContainsStr(p.BlacklistedChannels, m.Params[0]) {
		b.MentionReply(m, "%s", p.BlacklistedMessage)
		return
	}

	user, game := p.lookupDataRaw(b, m)
	if user == nil {
		b.MentionReply(m, "Couldn't find user")
		return
	}

	if game != nil {
		b.MentionReply(m, "There's already a game in this channel")
		return
	}

	// Create a new game, add the current user and store it.
	game, messages := NewGame(user)
	p.sendMessages(b, m, messages)
	p.games[m.Params[0]] = game
}

func (p *unoPlugin) joinCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.AddPlayer(user))
}

func (p *unoPlugin) startCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.Start(user))
}

func (p *unoPlugin) stopCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	messages, ok := game.Stop(user)

	p.sendMessages(b, m, messages)

	if ok {
		delete(p.games, m.Params[0])
	}
}

func (p *unoPlugin) handCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.GetHand(user))
}

func (p *unoPlugin) playCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	messages, done := game.Play(user, m.Trailing())
	if done {
		delete(p.games, m.Params[0])
	}

	p.sendMessages(b, m, messages)
}

func (p *unoPlugin) drawCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.Draw(user))
}

func (p *unoPlugin) drawPlayCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.DrawPlay(user, m.Trailing()))
}

func (p *unoPlugin) colorCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.SetColor(user, m.Trailing()))
}
<commit_msg>Fix help for the play command<commit_after>package uno

import (
	"errors"
	"strings"

	"github.com/Unknwon/com"
	"github.com/belak/go-seabird"
	"github.com/belak/go-seabird/plugins"
	"github.com/go-irc/irc"
)

func init() {
	seabird.RegisterPlugin("uno", newUnoPlugin)
}

type unoPlugin struct {
	games   map[string]*Game
	tracker *plugins.ChannelTracker

	BlacklistedChannels []string
	BlacklistedMessage  string
}

func newUnoPlugin(b *seabird.Bot, cm *seabird.CommandMux, tracker *plugins.ChannelTracker) error {
	p := &unoPlugin{
		games:   make(map[string]*Game),
		tracker: tracker,

		BlacklistedMessage: "Uno is blacklisted in this channel.",
	}

	err := b.Config("uno", p)
	if err != nil {
		return err
	}

	// TODO: Track channel parts

	cm.Channel("uno", p.unoCallback, &seabird.HelpInfo{
		Usage:       "[create|join|start|stop]",
		Description: "Flow control and stuff",
	})

	cm.Channel("hand", p.handCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Messages you your hand in an UNO game",
	})

	cm.Channel("play", p.playCallback, &seabird.HelpInfo{
		Usage:       "<card_name>",
		Description: "Plays card from your hand matching the given card_name",
	})

	cm.Channel("draw", p.drawCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Draws a card and possibly ends your turn",
	})

	cm.Channel("draw_play", p.drawPlayCallback, &seabird.HelpInfo{
		Usage:       "[yes|no]",
		Description: "Used after a call to <prefix>draw to possibly play a card",
	})

	cm.Channel("color", p.colorCallback, &seabird.HelpInfo{
		Usage:       "red|yellow|green|blue",
		Description: "Selects next color to play",
	})

	cm.Channel("uno_state", p.stateCallback, &seabird.HelpInfo{
		Usage:       "",
		Description: "Return the top card and current player.",
	})

	return nil
}

func (p *unoPlugin) lookupDataRaw(b *seabird.Bot, m *irc.Message) (*plugins.User, *Game) {
	user := p.tracker.LookupUser(m.Prefix.Name)
	game := p.games[m.Params[0]]

	return user, game
}

func (p *unoPlugin) lookupData(b *seabird.Bot, m *irc.Message) (*plugins.User, *Game, error) {
	user, game := p.lookupDataRaw(b, m)

	if user == nil {
		return user, game, errors.New("Couldn't find user")
	}

	if game == nil {
		return user, game, errors.New("No game in this channel")
	}

	return user, game, nil
}

// sendMessages is an abstraction around sending the uno Message
// type. This simplifies the translation between that and IRC.
func (p *unoPlugin) sendMessages(b *seabird.Bot, m *irc.Message, uMsgs []*Message) {
	for _, uMsg := range uMsgs {
		if uMsg.Target == nil {
			b.Reply(m, "%s", uMsg.Message)
		} else if uMsg.Private {
			b.Send(&irc.Message{
				Command: "NOTICE",
				Params: []string{
					uMsg.Target.Nick,
					uMsg.Message,
				},
			})
		} else {
			b.Reply(m, "%s: %s", uMsg.Target.Nick, uMsg.Message)
		}
	}
}

func (p *unoPlugin) stateCallback(b *seabird.Bot, m *irc.Message) {
	user, game := p.lookupDataRaw(b, m)
	if user == nil {
		b.MentionReply(m, "Couldn't find user")
		return
	}

	if game == nil {
		b.MentionReply(m, "There's no game in this channel")
		return
	}

	// TODO: This should pull from some State struct or similar from
	// the Game
	if game.state == stateNew {
		b.MentionReply(m, "Game hasn't been started yet")
		return
	}
	b.MentionReply(m, "Current Player: %s", game.currentPlayer().User.Nick)
	b.MentionReply(m, "Top Card: %s", game.lastPlayed())
}

func (p *unoPlugin) unoCallback(b *seabird.Bot, m *irc.Message) {
	trailing := strings.TrimSpace(m.Trailing())

	if len(trailing) == 0 {
		p.rawUnoCallback(b, m)
		return
	}

	switch trailing {
	case "create":
		p.createCallback(b, m)
	case "join":
		p.joinCallback(b, m)
	case "start":
		p.startCallback(b, m)
	case "stop":
		p.stopCallback(b, m)
	default:
		b.MentionReply(m, "Usage: <prefix>uno [create|join|start|stop]")
	}
}

func (p *unoPlugin) rawUnoCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.SayUno(user))
}

func (p *unoPlugin) createCallback(b *seabird.Bot, m *irc.Message) {
	// If the current channel is in the blacklist.
	if com.IsSliceContainsStr(p.BlacklistedChannels, m.Params[0]) {
		b.MentionReply(m, "%s", p.BlacklistedMessage)
		return
	}

	user, game := p.lookupDataRaw(b, m)
	if user == nil {
		b.MentionReply(m, "Couldn't find user")
		return
	}

	if game != nil {
		b.MentionReply(m, "There's already a game in this channel")
		return
	}

	// Create a new game, add the current user and store it.
	game, messages := NewGame(user)
	p.sendMessages(b, m, messages)
	p.games[m.Params[0]] = game
}

func (p *unoPlugin) joinCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.AddPlayer(user))
}

func (p *unoPlugin) startCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.Start(user))
}

func (p *unoPlugin) stopCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	messages, ok := game.Stop(user)

	p.sendMessages(b, m, messages)

	if ok {
		delete(p.games, m.Params[0])
	}
}

func (p *unoPlugin) handCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.GetHand(user))
}

func (p *unoPlugin) playCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	messages, done := game.Play(user, m.Trailing())
	if done {
		delete(p.games, m.Params[0])
	}

	p.sendMessages(b, m, messages)
}

func (p *unoPlugin) drawCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.Draw(user))
}

func (p *unoPlugin) drawPlayCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.DrawPlay(user, m.Trailing()))
}

func (p *unoPlugin) colorCallback(b *seabird.Bot, m *irc.Message) {
	user, game, err := p.lookupData(b, m)
	if err != nil {
		b.MentionReply(m, "%s", err.Error())
		return
	}

	p.sendMessages(b, m, game.SetColor(user, m.Trailing()))
}
<|endoftext|>


<commit_before>package command_test

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

	"github.com/TailorDev/msw/command"
	"github.com/mitchellh/cli"
)

func TestNewNoArgs(t *testing.T) {
	ui := new(cli.MockUi)
	cmd := &command.NewCommand{UI: ui}
	cases := []struct {
		args     []string
		expected string
	}{
		{nil, ""},
		{[]string{"abc"}, "Invalid issue number"},
		{[]string{"-date=1234-56-78", "123"}, "Error, parsing time"},
		{[]string{"-date=1234", "123"}, "Error, parsing time"},
		{[]string{"-directory=invalid", "123"}, "no such file or directory"},
	}

	for _, c := range cases {
		code := cmd.Run(c.args)
		if code != 1 {
			t.Fatalf("Expected code = 1, got: %d (args = %v)", code, c.args)
		}
		if !strings.Contains(ui.ErrorWriter.String(), c.expected) {
			t.Fatalf(
				"Expected UI to contain '%s', got: %s (args = %v)",
				c.expected,
				ui.ErrorWriter.String(),
				c.args,
			)
		}

		ui.ErrorWriter.Reset()
	}
}

func TestNew(t *testing.T) {
	ui := new(cli.MockUi)
	c := &command.NewCommand{UI: ui}
	dir := os.TempDir()

	code := c.Run([]string{
		fmt.Sprintf("-directory=%s", dir),
		"-date=2016-10-16",
		"123",
	})
	if code != 0 {
		t.Fatalf("Command should return 0, got: %d", code)
	}

	data, err := ioutil.ReadFile(fmt.Sprintf("%s/2016-10-16.yml", dir))
	if err != nil {
		t.Fatalf("A file should be generated: %s", err)
	}
	if !strings.Contains(string(data), "number: 123") {
		t.Fatalf("The generated file should contain '123', got: %s", data)
	}
}
<commit_msg>Fix a test case name<commit_after>package command_test

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

	"github.com/TailorDev/msw/command"
	"github.com/mitchellh/cli"
)

func TestNewInvalidArgs(t *testing.T) {
	ui := new(cli.MockUi)
	cmd := &command.NewCommand{UI: ui}
	cases := []struct {
		args     []string
		expected string
	}{
		{nil, ""},
		{[]string{"abc"}, "Invalid issue number"},
		{[]string{"-date=1234-56-78", "123"}, "Error, parsing time"},
		{[]string{"-date=1234", "123"}, "Error, parsing time"},
		{[]string{"-directory=invalid", "123"}, "no such file or directory"},
	}

	for _, c := range cases {
		code := cmd.Run(c.args)
		if code != 1 {
			t.Fatalf("Expected code = 1, got: %d (args = %v)", code, c.args)
		}
		if !strings.Contains(ui.ErrorWriter.String(), c.expected) {
			t.Fatalf(
				"Expected UI to contain '%s', got: %s (args = %v)",
				c.expected,
				ui.ErrorWriter.String(),
				c.args,
			)
		}

		ui.ErrorWriter.Reset()
	}
}

func TestNew(t *testing.T) {
	ui := new(cli.MockUi)
	c := &command.NewCommand{UI: ui}
	dir := os.TempDir()

	code := c.Run([]string{
		fmt.Sprintf("-directory=%s", dir),
		"-date=2016-10-16",
		"123",
	})
	if code != 0 {
		t.Fatalf("Command should return 0, got: %d", code)
	}

	data, err := ioutil.ReadFile(fmt.Sprintf("%s/2016-10-16.yml", dir))
	if err != nil {
		t.Fatalf("A file should be generated: %s", err)
	}
	if !strings.Contains(string(data), "number: 123") {
		t.Fatalf("The generated file should contain '123', got: %s", data)
	}
}
<|endoftext|>


<commit_before>package mcl

import "testing"

func testFr(t *testing.T) {
	err := Init(CurveFp254BNb)
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>sample of pairing<commit_after>package mcl

import "testing"

func testPairing(t *testing.T) {
	err := Init(CurveFp254BNb)
	if err != nil {
		t.Error(err)
	}
	var a, b, ab Fr
	a.SetString("12345678901", 10)
	b.SetString("abcdef0abcd", 16)
	FrMul(&ab, &a, &b)
	var P, aP G1
	var Q, bQ G2
	P.HashAndMapTo([]byte("this"))
	G1Mul(&aP, &P, &a)
	Q.HashAndMapTo([]byte("that"))
	G2Mul(&bQ, &Q, &b)
	var e1, e2 GT
	Pairing(&e1, &P, &Q)
	Pairing(&e2, &aP, &bQ)
	GTPow(&e2, &e2, &ab)
	if !e1.IsEqual(&e2) {
		t.Error("not equal pairing")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/nsqio/go-nsq"
	"io"
	"log"
	"os"
	"strings"
	"time"
)

type message struct {
	topic string
	body  [][]byte
}

type LogTask struct {
	Writer        *nsq.Producer
	LogStat       map[string]chan int
	CurrentConfig map[string]string
	Setting       map[string]string
	msgChan       chan *message
	client        *api.Client
	exitChan      chan int
}

func (m *LogTask) Run() {
	m.exitChan = make(chan int)
	m.msgChan = make(chan *message)
	ticker := time.Tick(time.Second * 600)
	config := api.DefaultConfig()
	config.Address = m.Setting["consul_address"]
	config.Datacenter = m.Setting["datacenter"]
	config.Token = m.Setting["consul_token"]
	var err error
	m.client, err = api.NewClient(config)
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	err = m.CheckReload()
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	for {
		select {
		case <-ticker:
			err = m.CheckReload()
			if err != nil {
				fmt.Println("reload consul setting failed", err)
			}
		case <-m.exitChan:
			return
		}
	}
}
func (m *LogTask) Stop() {
	close(m.exitChan)
	for _, v := range m.LogStat {
		close(v)
	}
	m.Writer.Stop()
}
func (m *LogTask) ReadConfigFromConsul() (map[string]string, error) {
	consulSetting := make(map[string]string)
	kv := m.client.KV()
	pairs, _, err := kv.List(m.Setting["cluster"], nil)
	if err != nil {
		return consulSetting, err
	}
	size := len(m.Setting["cluster"]) + 1
	for _, value := range pairs {
		if len(value.Key) > size {
			consulSetting[value.Key[size:]] = string(value.Value)
		}
	}
	return consulSetting, err

}
func (m *LogTask) CheckReload() error {
	newConf, err := m.ReadConfigFromConsul()
	if err != nil {
		return err
	}
	for k, _ := range newConf {
		if m.CurrentConfig[k] != newConf[k] {
			if len(m.CurrentConfig[k]) > 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
				delete(m.CurrentConfig, k)
			}
			if len(newConf[k]) > 0 {
				fileNames := strings.Split(newConf[k], ",")
				m.LogStat[k] = make(chan int)
				for _, fileName := range fileNames {
					go m.WriteLoop(m.LogStat[k])
					go m.ReadLog(fileName, k, m.LogStat[k])
				}
			}
		}
	}
	for k, _ := range m.CurrentConfig {
		if m.CurrentConfig[k] != newConf[k] {
			if len(newConf[k]) == 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
			}
		}
	}
	m.CurrentConfig = newConf
	return nil
}

func (m *LogTask) ReadLog(file string, topic string, exitchan chan int) {
	fd, err := os.Open(file)
	if err != nil {
		log.Println(err)
		return
	}
	defer fd.Close()
	if len(m.Setting["read_all"]) == 0 {
		_, err = fd.Seek(0, os.SEEK_END)
		if err != nil {
			return
		}
		log.Println("reading from 0")
	}
	log.Println("reading ", file)
	reader := bufio.NewReader(fd)
	var body [][]byte
	for {
		select {
		case <-exitchan:
			return
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				time.Sleep(time.Second)
				line, err = reader.ReadString('\n')
			}
			if err == io.EOF {
				log.Println(file, "READ EOF")
				size0, err := fd.Seek(0, os.SEEK_CUR)
				if err != nil {
					return
				}
				fd, err = os.Open(file)
				if err != nil {
					log.Println("open failed", err)
					return
				}
				size1, err := fd.Seek(0, os.SEEK_END)
				if err != nil {
					log.Println(err)
				}
				if size1 < size0 {
					fd.Seek(0, os.SEEK_SET)
				} else {
					fd.Seek(size0, os.SEEK_SET)
				}
				reader = bufio.NewReader(fd)
				continue
			}
			if err != nil {
				log.Println(err)
				return
			}
			body = append(body, []byte(line))
			if len(body) > 100 {
				msg := &message{
					topic: topic,
					body:  body,
				}
				m.msgChan <- msg
				body = body[:0]
			}
		}
	}
}

func (m *LogTask) WriteLoop(exitchan chan int) {
	for {
		select {
		case <-m.exitChan:
			return
		case <-exitchan:
			return
		case msg := <-m.msgChan:
			m.Writer.MultiPublish(msg.topic, msg.body)
		}
	}
}
<commit_msg>use io.Seek* instead<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/nsqio/go-nsq"
	"io"
	"log"
	"os"
	"strings"
	"time"
)

type message struct {
	topic string
	body  [][]byte
}

type LogTask struct {
	Writer        *nsq.Producer
	LogStat       map[string]chan int
	CurrentConfig map[string]string
	Setting       map[string]string
	msgChan       chan *message
	client        *api.Client
	exitChan      chan int
}

func (m *LogTask) Run() {
	m.exitChan = make(chan int)
	m.msgChan = make(chan *message)
	ticker := time.Tick(time.Second * 600)
	config := api.DefaultConfig()
	config.Address = m.Setting["consul_address"]
	config.Datacenter = m.Setting["datacenter"]
	config.Token = m.Setting["consul_token"]
	var err error
	m.client, err = api.NewClient(config)
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	err = m.CheckReload()
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	for {
		select {
		case <-ticker:
			err = m.CheckReload()
			if err != nil {
				fmt.Println("reload consul setting failed", err)
			}
		case <-m.exitChan:
			return
		}
	}
}
func (m *LogTask) Stop() {
	close(m.exitChan)
	for _, v := range m.LogStat {
		close(v)
	}
	m.Writer.Stop()
}
func (m *LogTask) ReadConfigFromConsul() (map[string]string, error) {
	consulSetting := make(map[string]string)
	kv := m.client.KV()
	pairs, _, err := kv.List(m.Setting["cluster"], nil)
	if err != nil {
		return consulSetting, err
	}
	size := len(m.Setting["cluster"]) + 1
	for _, value := range pairs {
		if len(value.Key) > size {
			consulSetting[value.Key[size:]] = string(value.Value)
		}
	}
	return consulSetting, err

}
func (m *LogTask) CheckReload() error {
	newConf, err := m.ReadConfigFromConsul()
	if err != nil {
		return err
	}
	for k, _ := range newConf {
		if m.CurrentConfig[k] != newConf[k] {
			if len(m.CurrentConfig[k]) > 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
				delete(m.CurrentConfig, k)
			}
			if len(newConf[k]) > 0 {
				fileNames := strings.Split(newConf[k], ",")
				m.LogStat[k] = make(chan int)
				for _, fileName := range fileNames {
					go m.WriteLoop(m.LogStat[k])
					go m.ReadLog(fileName, k, m.LogStat[k])
				}
			}
		}
	}
	for k, _ := range m.CurrentConfig {
		if m.CurrentConfig[k] != newConf[k] {
			if len(newConf[k]) == 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
			}
		}
	}
	m.CurrentConfig = newConf
	return nil
}

func (m *LogTask) ReadLog(file string, topic string, exitchan chan int) {
	fd, err := os.Open(file)
	if err != nil {
		log.Println(err)
		return
	}
	defer fd.Close()
	_, err = fd.Seek(0, io.SeekStart)
	if err != nil {
		return
	}
	if len(m.Setting["read_all"]) == 0 {
		_, err = fd.Seek(0, io.SeekEnd)
		if err != nil {
			return
		}
		log.Println("reading from EOF")
	}
	log.Println("reading ", file)
	reader := bufio.NewReader(fd)
	var body [][]byte
	for {
		select {
		case <-exitchan:
			return
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				time.Sleep(time.Second)
				line, err = reader.ReadString('\n')
			}
			if err == io.EOF {
				log.Println(file, "READ EOF")
				size0, err := fd.Seek(0, io.SeekCurrent)
				if err != nil {
					return
				}
				fd, err = os.Open(file)
				if err != nil {
					log.Println("open failed", err)
					return
				}
				size1, err := fd.Seek(0, io.SeekEnd)
				if err != nil {
					log.Println(err)
				}
				if size1 < size0 {
					fd.Seek(0, io.SeekCurrent)
				} else {
					fd.Seek(size0, io.SeekStart)
				}
				reader = bufio.NewReader(fd)
				continue
			}
			if err != nil {
				log.Println(err)
				return
			}
			body = append(body, []byte(line))
			if len(body) > 100 {
				msg := &message{
					topic: topic,
					body:  body,
				}
				m.msgChan <- msg
				body = body[:0]
			}
		}
	}
}

func (m *LogTask) WriteLoop(exitchan chan int) {
	for {
		select {
		case <-m.exitChan:
			return
		case <-exitchan:
			return
		case msg := <-m.msgChan:
			m.Writer.MultiPublish(msg.topic, msg.body)
		}
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"regexp"
	"strings"
)

// global variables
var (
	region  string
	project string
	stacks  map[string]*stack
)

// fetchContent - checks the source type, url/s3/file and calls the corresponding function
func fetchContent(source string) (string, error) {
	switch strings.Split(strings.ToLower(source), ":")[0] {
	case "http", "https":
		Log(fmt.Sprintln("Source Type: [http] Detected, Fetching Source: ", source), level.debug)
		resp, err := Get(source)
		if err != nil {
			return "", err
		}
		return resp, nil
	case "s3":
		Log(fmt.Sprintln("Source Type: [s3] Detected, Fetching Source: ", source), level.debug)
		resp, err := S3Read(source)
		if err != nil {
			return "", err
		}
		return resp, nil
	case "lambda":
		Log(fmt.Sprintln("Source Type: [lambda] Detected, Fetching Source: ", source), level.debug)
		lambdaSrc := strings.Split(strings.Replace(source, "lambda:", "", -1), "@")

		var raw interface{}
		if err := json.Unmarshal([]byte(lambdaSrc[0]), &raw); err != nil {
			return "", err
		}

		event, err := json.Marshal(raw)
		if err != nil {
			return "", err
		}

		reg, err := regexp.Compile("[^A-Za-z0-9_-]+")
		if err != nil {
			return "", err
		}

		lambdaName := reg.ReplaceAllString(lambdaSrc[1], "")

		f := awsLambda{
			name:    lambdaName,
			payload: event,
		}

		// using default profile
		sess := manager.sessions[run.profile]
		if err := f.Invoke(sess); err != nil {
			return "", err
		}

		return f.response, nil

	default:
		if gitrepo.config != "" {
			Log(fmt.Sprintln("Source Type: [git-repo file] Detected, Fetching Source: ", source), level.debug)
			return gitrepo.config, nil
		}

		Log(fmt.Sprintln("Source Type: [file] Detected, Fetching Source: ", source), level.debug)
		b, err := ioutil.ReadFile(source)
		if err != nil {
			return "", err
		}
		return string(b), nil
	}
}

// getName  - Checks if arg is url or file and returns stack name and filepath/url
func getSource(src string) (string, string, error) {

	vals := strings.Split(src, "::")
	if len(vals) < 2 {
		return "", "", errors.New(`Error, invalid format - Usage: stackname::http://someurl OR stackname::path/to/template`)
	}

	return vals[0], vals[1], nil
}
<commit_msg>added condiition for repo virtual filesystem check in source<commit_after>package commands

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"regexp"
	"strings"
)

// global variables
var (
	region  string
	project string
	stacks  map[string]*stack
)

// fetchContent - checks the source type, url/s3/file and calls the corresponding function
func fetchContent(source string) (string, error) {
	switch strings.Split(strings.ToLower(source), ":")[0] {
	case "http", "https":
		Log(fmt.Sprintln("Source Type: [http] Detected, Fetching Source: ", source), level.debug)
		resp, err := Get(source)
		if err != nil {
			return "", err
		}
		return resp, nil
	case "s3":
		Log(fmt.Sprintln("Source Type: [s3] Detected, Fetching Source: ", source), level.debug)
		resp, err := S3Read(source)
		if err != nil {
			return "", err
		}
		return resp, nil
	case "lambda":
		Log(fmt.Sprintln("Source Type: [lambda] Detected, Fetching Source: ", source), level.debug)
		lambdaSrc := strings.Split(strings.Replace(source, "lambda:", "", -1), "@")

		var raw interface{}
		if err := json.Unmarshal([]byte(lambdaSrc[0]), &raw); err != nil {
			return "", err
		}

		event, err := json.Marshal(raw)
		if err != nil {
			return "", err
		}

		reg, err := regexp.Compile("[^A-Za-z0-9_-]+")
		if err != nil {
			return "", err
		}

		lambdaName := reg.ReplaceAllString(lambdaSrc[1], "")

		f := awsLambda{
			name:    lambdaName,
			payload: event,
		}

		// using default profile
		sess := manager.sessions[run.profile]
		if err := f.Invoke(sess); err != nil {
			return "", err
		}

		return f.response, nil

	default:
		if gitrepo.URL != "" {
			Log(fmt.Sprintln("Source Type: [git-repo file] Detected, Fetching Source: ", source), level.debug)
			out, ok := gitrepo.files[source]
			if ok {
				return out, nil
			} else if !ok {
				Log(fmt.Sprintf("config [%s] not found in git repo - checking local file system", source), level.warn)
			}

		}

		Log(fmt.Sprintln("Source Type: [file] Detected, Fetching Source: ", source), level.debug)
		b, err := ioutil.ReadFile(source)
		if err != nil {
			return "", err
		}
		return string(b), nil
	}
}

// getName  - Checks if arg is url or file and returns stack name and filepath/url
func getSource(src string) (string, string, error) {

	vals := strings.Split(src, "::")
	if len(vals) < 2 {
		return "", "", errors.New(`Error, invalid format - Usage: stackname::http://someurl OR stackname::path/to/template`)
	}

	return vals[0], vals[1], nil
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"github.com/PagerDuty/godspeed"
	"github.com/zorkian/go-datadog-api"
	"os"
)

func StatsdIn(key string, data_length int, data string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='in'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.in", tags)
	statsd.Gauge("kvexpress.bytes", float64(data_length), tags)
	statsd.Gauge("kvexpress.lines", float64(LineCount(data)), tags)
}

func StatsdOut(key string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='out'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.out", tags)
}

func StatsdRaw(key string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='raw'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.raw", tags)
}

func StatsdRunTime(key string, location string, msec int64) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' location='%s' msec='%d'", key, location, msec), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, location)
	locationTag := fmt.Sprintf("location:%s", location)
	tags = append(tags, locationTag)
	statsd.Gauge("kvexpress.time", float64(msec), tags)
}

func StatsdPanic(key, location string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' location='%s' stats='panic'", key, location), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, location)
	statsd.Incr("kvexpress.panic", tags)
	// If we're going to panic, we might as well stop right here.
	// Means we can't connect to Consul, download a URL or
	// write and/or chown files.
	os.Exit(0)
}

func DDAPIConnect(api, app string) *datadog.Client {
	client := datadog.NewClient(api, app)
	return client
}

func makeTags(key, location string) []string {
	tags := make([]string, 4)
	keyTag := fmt.Sprintf("key:%s", key)
	hostname, _ := os.Hostname()
	hostTag := fmt.Sprintf("host:%s", hostname)
	directionTag := fmt.Sprintf("direction:%s", Direction)
	locationTag := fmt.Sprintf("location:%s", location)
	tags = append(tags, keyTag)
	tags = append(tags, hostTag)
	tags = append(tags, directionTag)
	tags = append(tags, locationTag)
	return tags
}

// TODO: These three functions are ripe for refactoring to be more Golang like.
func DDStopEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDStopEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "stop_key_present")
	tags = append(tags, "kvexpress:stop")
	title := fmt.Sprintf("Stop key is present: %s. Stopping.", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "error", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDSaveDataEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDSaveDataEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "complete")
	tags = append(tags, "kvexpress:success")
	title := fmt.Sprintf("Updated: %s", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "info", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDCopyDataEvent(dd *datadog.Client, keyFrom, keyTo string) {
	Log(fmt.Sprintf("datadog='true' DDCopyDataEvent='true' keyFrom='%s' keyTo='%s'", keyFrom, keyTo), "debug")
	tags := makeTags(keyTo, "complete")
	tags = append(tags, "kvexpress:success")
	tags = append(tags, fmt.Sprintf("keyFrom:%s", keyFrom))
	title := fmt.Sprintf("Copy: %s to %s", keyFrom, keyTo)
	event := datadog.Event{Title: title, Text: title, AlertType: "info", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDSaveStopEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDSaveStopEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "stop_key_save")
	tags = append(tags, "kvexpress:stop_set")
	title := fmt.Sprintf("Set Stop Key: %s", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "warning", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}
<commit_msg>Change name to be more Go like.<commit_after>package commands

import (
	"fmt"
	"github.com/PagerDuty/godspeed"
	"github.com/zorkian/go-datadog-api"
	"os"
)

func StatsdIn(key string, dataLength int, data string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='in'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.in", tags)
	statsd.Gauge("kvexpress.bytes", float64(dataLength), tags)
	statsd.Gauge("kvexpress.lines", float64(LineCount(data)), tags)
}

func StatsdOut(key string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='out'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.out", tags)
}

func StatsdRaw(key string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' stats='raw'", key), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, "complete")
	statsd.Incr("kvexpress.raw", tags)
}

func StatsdRunTime(key string, location string, msec int64) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' location='%s' msec='%d'", key, location, msec), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, location)
	locationTag := fmt.Sprintf("location:%s", location)
	tags = append(tags, locationTag)
	statsd.Gauge("kvexpress.time", float64(msec), tags)
}

func StatsdPanic(key, location string) {
	Log(fmt.Sprintf("dogstatsd='true' key='%s' location='%s' stats='panic'", key, location), "debug")
	statsd, _ := godspeed.NewDefault()
	defer statsd.Conn.Close()
	tags := makeTags(key, location)
	statsd.Incr("kvexpress.panic", tags)
	// If we're going to panic, we might as well stop right here.
	// Means we can't connect to Consul, download a URL or
	// write and/or chown files.
	os.Exit(0)
}

func DDAPIConnect(api, app string) *datadog.Client {
	client := datadog.NewClient(api, app)
	return client
}

func makeTags(key, location string) []string {
	tags := make([]string, 4)
	keyTag := fmt.Sprintf("key:%s", key)
	hostname, _ := os.Hostname()
	hostTag := fmt.Sprintf("host:%s", hostname)
	directionTag := fmt.Sprintf("direction:%s", Direction)
	locationTag := fmt.Sprintf("location:%s", location)
	tags = append(tags, keyTag)
	tags = append(tags, hostTag)
	tags = append(tags, directionTag)
	tags = append(tags, locationTag)
	return tags
}

// TODO: These three functions are ripe for refactoring to be more Golang like.
func DDStopEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDStopEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "stop_key_present")
	tags = append(tags, "kvexpress:stop")
	title := fmt.Sprintf("Stop key is present: %s. Stopping.", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "error", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDSaveDataEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDSaveDataEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "complete")
	tags = append(tags, "kvexpress:success")
	title := fmt.Sprintf("Updated: %s", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "info", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDCopyDataEvent(dd *datadog.Client, keyFrom, keyTo string) {
	Log(fmt.Sprintf("datadog='true' DDCopyDataEvent='true' keyFrom='%s' keyTo='%s'", keyFrom, keyTo), "debug")
	tags := makeTags(keyTo, "complete")
	tags = append(tags, "kvexpress:success")
	tags = append(tags, fmt.Sprintf("keyFrom:%s", keyFrom))
	title := fmt.Sprintf("Copy: %s to %s", keyFrom, keyTo)
	event := datadog.Event{Title: title, Text: title, AlertType: "info", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}

func DDSaveStopEvent(dd *datadog.Client, key, value string) {
	Log(fmt.Sprintf("datadog='true' DDSaveStopEvent='true' key='%s'", key), "debug")
	tags := makeTags(key, "stop_key_save")
	tags = append(tags, "kvexpress:stop_set")
	title := fmt.Sprintf("Set Stop Key: %s", key)
	event := datadog.Event{Title: title, Text: value, AlertType: "warning", Tags: tags}
	post, _ := dd.PostEvent(&event)
	if post != nil {

	}
}
<|endoftext|>