<commit_before>package tnetstring

import (
	"bytes"
	"os"
	"reflect"
	"strconv"
)

func Unmarshal(data []byte, v interface{}) os.Error {
	val := reflect.ValueOf(v)
	val = reflect.Indirect(val)
	if !val.CanSet() {
		return os.NewError("tnetstring: Unmarshal requires a settable value")
	}
	_, err := unmarshal(data, val)
	return err
}

func indirect(v reflect.Value, create bool) reflect.Value {
	for {
		switch v.Kind() {
		case reflect.Ptr:
			if create && v.IsNil() {
				v.Set(reflect.New(v.Type().Elem()))
			}
			v = v.Elem()
		case reflect.Interface:
			if create && v.IsNil() {
				return v
			}
			v = v.Elem()
		default:
			return v
		}
	}
	panic("unreachable")
}

func unmarshal(data []byte, v reflect.Value) (int, os.Error) {
	typ, content, n := readElement(data)
	if n == 0 {
		return 0, os.NewError("tnetstring: invalid data")
	}
	v = indirect(v, true)
	kind := v.Kind()
	// ~ and interface types are special cases
	if typ != '~' && kind != reflect.Interface && typeLookup[kind] != typ {
		return 0, os.NewError("tnetstring: invalid value to unmarshal into")
	}
	switch typ {
	case '!':
		v.Set(reflect.ValueOf(string(content) == "true"))
	case '#':
		switch kind {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			i, err := strconv.Atoi64(string(content))
			if err != nil {
				return 0, err
			}
			v.SetInt(i)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
			reflect.Uint64, reflect.Uintptr:
			ui, err := strconv.Atoui64(string(content))
			if err != nil {
				return 0, err
			}
			v.SetUint(ui)
		case reflect.Interface:
			i, err := strconv.Atoi64(string(content))
			if err != nil {
				return 0, err
			}
			v.Set(reflect.ValueOf(i))
		}
	case ',':
		v.Set(reflect.ValueOf(string(content)))
	case ']':
		unmarshalArray(content, v)
	case '}':
		var err os.Error
		if kind == reflect.Map {
			err = unmarshalMap(content, v)
		} else {
			err = unmarshalStruct(content, v)
		}
		if err != nil {
			return 0, err
		}
	case '~':
		switch kind {
		case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
			v.Set(reflect.Zero(v.Type()))
		default:
			return 0, os.NewError("tnetstring: invalid value to unmarshal into")
		}
	default:
		return 0, os.NewError("tnetstring: unknown type")
	}
	return n, nil
}

func unmarshalArray(data []byte, v reflect.Value) os.Error {
	kind := v.Kind()
	n := 0
	i := 0
	elType := v.Type().Elem()
	for len(data)-n > 0 {
		if i >= v.Len() {
			if kind == reflect.Array {
				break
			} else {
				// TODO: could cut down on allocations by calling MakeSlice instead
				v.Set(reflect.Append(v, reflect.New(elType).Elem()))
			}
		}
		el := v.Index(i)
		i++
		nn, err := unmarshal(data[n:], el)
		if err != nil {
			return err
		}
		n += nn
	}
	return nil
}

func unmarshalMap(data []byte, v reflect.Value) os.Error {
	ktype := v.Type().Key()
	if ktype.Kind() != reflect.String {
		return os.NewError("tnetstring: only maps with string keys can be unmarshaled")
	}
	if v.IsNil() {
		v.Set(reflect.MakeMap(v.Type()))
	}
	n := 0
	vtype := v.Type().Elem()
	key := reflect.New(ktype).Elem()
	val := reflect.New(vtype).Elem()
	for len(data)-n > 0 {
		nn, err := unmarshal(data[n:], key)
		if err != nil {
			return err
		}
		n += nn
		nn, err = unmarshal(data[n:], val)
		if err != nil {
			return err
		}
		n += nn
		v.SetMapIndex(key, val)
	}
	return nil
}

func unmarshalStruct(data []byte, v reflect.Value) os.Error {
	n := 0
	structType := v.Type()
	var s string
	name := reflect.ValueOf(&s).Elem()
	for len(data)-n > 0 {
		nn, err := unmarshal(data[n:], name)
		if err != nil {
			return err
		}
		n += nn
		field := v.FieldByName(s)
		if field.Internal == nil {
			for i := 0; i < structType.NumField(); i++ {
				f := structType.Field(i)
				if f.Tag == s {
					field = v.Field(i)
					break
				}
			}
			if field.Internal == nil {
				var i interface{}
				field = reflect.ValueOf(&i).Elem()
			}
		}
		nn, err = unmarshal(data[n:], field)
		if err != nil {
			return err
		}
		n += nn
	}
	return nil
}

func readElement(data []byte) (typ byte, content []byte, n int) {
	col := bytes.IndexByte(data, ':')
	if col < 1 {
		return
	}
	n, err := strconv.Atoi(string(data[:col]))
	if err != nil || n > len(data[col+1:]) {
		return
	}
	// +1 for colon
	n += col + 1
	content = data[col+1 : n]
	typ = data[n]
	n++
	return
}
<commit_msg>Improve dictionary unmarshal speed<commit_after>package tnetstring

import (
	"bytes"
	"os"
	"reflect"
	"strconv"
)

func Unmarshal(data []byte, v interface{}) os.Error {
	val := reflect.ValueOf(v)
	val = reflect.Indirect(val)
	if !val.CanSet() {
		return os.NewError("tnetstring: Unmarshal requires a settable value")
	}
	_, err := unmarshal(data, val)
	return err
}

func indirect(v reflect.Value, create bool) reflect.Value {
	for {
		switch v.Kind() {
		case reflect.Ptr:
			if create && v.IsNil() {
				v.Set(reflect.New(v.Type().Elem()))
			}
			v = v.Elem()
		case reflect.Interface:
			if create && v.IsNil() {
				return v
			}
			v = v.Elem()
		default:
			return v
		}
	}
	panic("unreachable")
}

func unmarshal(data []byte, v reflect.Value) (int, os.Error) {
	typ, content, n := readElement(data)
	if n == 0 {
		return 0, os.NewError("tnetstring: invalid data")
	}
	v = indirect(v, true)
	kind := v.Kind()
	// ~ and interface types are special cases
	if typ != '~' && kind != reflect.Interface && typeLookup[kind] != typ {
		return 0, os.NewError("tnetstring: invalid value to unmarshal into")
	}
	switch typ {
	case '!':
		v.Set(reflect.ValueOf(string(content) == "true"))
	case '#':
		switch kind {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			i, err := strconv.Atoi64(string(content))
			if err != nil {
				return 0, err
			}
			v.SetInt(i)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
			reflect.Uint64, reflect.Uintptr:
			ui, err := strconv.Atoui64(string(content))
			if err != nil {
				return 0, err
			}
			v.SetUint(ui)
		case reflect.Interface:
			i, err := strconv.Atoi64(string(content))
			if err != nil {
				return 0, err
			}
			v.Set(reflect.ValueOf(i))
		}
	case ',':
		v.Set(reflect.ValueOf(string(content)))
	case ']':
		unmarshalArray(content, v)
	case '}':
		var err os.Error
		if kind == reflect.Map {
			err = unmarshalMap(content, v)
		} else {
			err = unmarshalStruct(content, v)
		}
		if err != nil {
			return 0, err
		}
	case '~':
		switch kind {
		case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
			v.Set(reflect.Zero(v.Type()))
		default:
			return 0, os.NewError("tnetstring: invalid value to unmarshal into")
		}
	default:
		return 0, os.NewError("tnetstring: unknown type")
	}
	return n, nil
}

func unmarshalArray(data []byte, v reflect.Value) os.Error {
	kind := v.Kind()
	n := 0
	i := 0
	elType := v.Type().Elem()
	for len(data)-n > 0 {
		if i >= v.Len() {
			if kind == reflect.Array {
				break
			} else {
				// TODO: could cut down on allocations by calling MakeSlice instead
				v.Set(reflect.Append(v, reflect.New(elType).Elem()))
			}
		}
		el := v.Index(i)
		i++
		nn, err := unmarshal(data[n:], el)
		if err != nil {
			return err
		}
		n += nn
	}
	return nil
}

func unmarshalMap(data []byte, v reflect.Value) os.Error {
	if v.Type().Key().Kind() != reflect.String {
		return os.NewError("tnetstring: only maps with string keys can be unmarshaled")
	}
	if v.IsNil() {
		v.Set(reflect.MakeMap(v.Type()))
	}
	n := 0
	vtype := v.Type().Elem()
	var s string
	key := reflect.ValueOf(&s).Elem()
	val := reflect.New(vtype).Elem()
	for len(data)-n > 0 {
		typ, content, nn := readElement(data[n:])
		if typ != ',' {
			return os.NewError("tnetstring: non-string key in dictionary")
		}
		s = string(content)
		n += nn
		nn, err := unmarshal(data[n:], val)
		if err != nil {
			return err
		}
		n += nn
		v.SetMapIndex(key, val)
	}
	return nil
}

func unmarshalStruct(data []byte, v reflect.Value) os.Error {
	n := 0
	structType := v.Type()
	var s string
	name := reflect.ValueOf(&s).Elem()
	for len(data)-n > 0 {
		nn, err := unmarshal(data[n:], name)
		if err != nil {
			return err
		}
		n += nn
		field := v.FieldByName(s)
		if field.Internal == nil {
			for i := 0; i < structType.NumField(); i++ {
				f := structType.Field(i)
				if f.Tag == s {
					field = v.Field(i)
					break
				}
			}
			if field.Internal == nil {
				var i interface{}
				field = reflect.ValueOf(&i).Elem()
			}
		}
		nn, err = unmarshal(data[n:], field)
		if err != nil {
			return err
		}
		n += nn
	}
	return nil
}

func readElement(data []byte) (typ byte, content []byte, n int) {
	col := bytes.IndexByte(data, ':')
	if col < 1 {
		return
	}
	n, err := strconv.Atoi(string(data[:col]))
	if err != nil || n > len(data[col+1:]) {
		return
	}
	// +1 for colon
	n += col + 1
	content = data[col+1 : n]
	typ = data[n]
	n++
	return
}
<|endoftext|>


<commit_before>/*
Package gonexmo implements a simple client library for accessing the Nexmo API.

Usage is simple. Create a Nexmo instance with NexmoWithKeyAndSecret(), providing
your API key and API secret. Then send messages with SendTextMessage() or
SendFlashMessage(). The API will return a MessageResponse which you can
use to see if your message went through, how much it cost, etc.
*/
package gonexmo

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

// MessageReport is the "status report" for a single SMS sent via the Nexmo API
type MessageReport struct {
	Status           string `json:"status"`
	MessageID        string `json:"message-id"`
	To               string `json:"to"`
	ClientReference  string `json:"client-ref"`
	RemainingBalance string `json:"remaining-balance"`
	MessagePrice     string `json:"message-price"`
	Network          string `json:"network"`
	ErrorText        string `json:"error-text"`
}

// MessageResponse contains the response from Nexmo's API after we attempt to send any kind of message.
// It will contain one MessageReport for every 160 chars sent.
type MessageResponse struct {
	MessageCount string          `json:"message-count"`
	Messages     []MessageReport `json:"messages"`
}

// AccountBalance represents the "balance" object we get back when calling GET /account/get-balance
type AccountBalance struct {
	Value float64 `json:"value"`
}

// Nexmo encapsulates the Nexmo functions - must be created with NexmoWithKeyAndSecret()
type Nexmo struct {
	apiKey    string
	apiSecret string
}

// NexmoWithKeyAndSecret creates a Nexmo object with the provided API key / API secret.
func NexmoWithKeyAndSecret(apiKey, apiSecret string) (*Nexmo, error) {
	if apiKey == "" {
		return nil, errors.New("apiKey can not be empty!")
	} else if apiSecret == "" {
		return nil, errors.New("apiSecret can not be empty!")
	}

	nexmo := &Nexmo{apiKey, apiSecret}
	return nexmo, nil
}

func (nexmo *Nexmo) sendMessage(from string, to string, text string, clientReference string, statusReportRequired bool, is_flash_message bool) (*MessageResponse, error) {
	var messageResponse *MessageResponse

	values := make(url.Values)
	values.Set("api_key", nexmo.apiKey)
	values.Set("api_secret", nexmo.apiSecret)
	values.Set("type", "text")

	values.Set("to", to)
	values.Set("from", from)
	values.Set("text", text)
	values.Set("client_ref", clientReference)

	if statusReportRequired {
		values.Set("status_report_req", string(1))

	}
	if is_flash_message {
		values.Set("message_class", "0")
	}

	client := &http.Client{}
	r, _ := http.NewRequest("POST", "https://rest.nexmo.com/sms/json", bytes.NewBufferString(values.Encode())) // <-- URL-encoded payload
	r.Header.Add("Accept", "application/json")
	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	// r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

	resp, err := client.Do(r)
	defer resp.Body.Close()

	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(resp.Body)

	err = json.Unmarshal(body, &messageResponse)
	if err != nil {
		return nil, err
	} else {
		return messageResponse, nil
	}
}

// SendTextMessage() sends a normal SMS
func (nexmo *Nexmo) SendTextMessage(from, to, text, clientReference string, statusReportRequired bool) (*MessageResponse, error) {
	return nexmo.sendMessage(from, to, text, clientReference, statusReportRequired, false)
}

// SendFlashMessage() sends a class 0 SMS (Flash message).
func (nexmo *Nexmo) SendFlashMessage(from, to, text, clientReference string, statusReportRequired bool) (*MessageResponse, error) {
	return nexmo.sendMessage(from, to, text, clientReference, statusReportRequired, true)
}

// GetBalance() retrieves the current balance of your Nexmo account in Euros (€)
func (nexmo *Nexmo) GetBalance() (float64, error) {
	var accBalance *AccountBalance

	client := &http.Client{}
	r, _ := http.NewRequest("GET", "https://rest.nexmo.com/account/get-balance/"+nexmo.apiKey+"/"+nexmo.apiSecret, nil)
	r.Header.Add("Accept", "application/json")

	resp, err := client.Do(r)
	defer resp.Body.Close()

	if err != nil {
		return 0.0, err
	}

	body, _ := ioutil.ReadAll(resp.Body)

	err = json.Unmarshal(body, &accBalance)
	if err != nil {
		return 0.0, err
	} else {
		return accBalance.Value, nil
	}
}
<commit_msg>Remove unused fmt pkg import<commit_after>/*
Package gonexmo implements a simple client library for accessing the Nexmo API.

Usage is simple. Create a Nexmo instance with NexmoWithKeyAndSecret(), providing
your API key and API secret. Then send messages with SendTextMessage() or
SendFlashMessage(). The API will return a MessageResponse which you can
use to see if your message went through, how much it cost, etc.
*/
package gonexmo

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
)

// MessageReport is the "status report" for a single SMS sent via the Nexmo API
type MessageReport struct {
	Status           string `json:"status"`
	MessageID        string `json:"message-id"`
	To               string `json:"to"`
	ClientReference  string `json:"client-ref"`
	RemainingBalance string `json:"remaining-balance"`
	MessagePrice     string `json:"message-price"`
	Network          string `json:"network"`
	ErrorText        string `json:"error-text"`
}

// MessageResponse contains the response from Nexmo's API after we attempt to send any kind of message.
// It will contain one MessageReport for every 160 chars sent.
type MessageResponse struct {
	MessageCount string          `json:"message-count"`
	Messages     []MessageReport `json:"messages"`
}

// AccountBalance represents the "balance" object we get back when calling GET /account/get-balance
type AccountBalance struct {
	Value float64 `json:"value"`
}

// Nexmo encapsulates the Nexmo functions - must be created with NexmoWithKeyAndSecret()
type Nexmo struct {
	apiKey    string
	apiSecret string
}

// NexmoWithKeyAndSecret creates a Nexmo object with the provided API key / API secret.
func NexmoWithKeyAndSecret(apiKey, apiSecret string) (*Nexmo, error) {
	if apiKey == "" {
		return nil, errors.New("apiKey can not be empty!")
	} else if apiSecret == "" {
		return nil, errors.New("apiSecret can not be empty!")
	}

	nexmo := &Nexmo{apiKey, apiSecret}
	return nexmo, nil
}

func (nexmo *Nexmo) sendMessage(from string, to string, text string, clientReference string, statusReportRequired bool, is_flash_message bool) (*MessageResponse, error) {
	var messageResponse *MessageResponse

	values := make(url.Values)
	values.Set("api_key", nexmo.apiKey)
	values.Set("api_secret", nexmo.apiSecret)
	values.Set("type", "text")

	values.Set("to", to)
	values.Set("from", from)
	values.Set("text", text)
	values.Set("client_ref", clientReference)

	if statusReportRequired {
		values.Set("status_report_req", string(1))

	}
	if is_flash_message {
		values.Set("message_class", "0")
	}

	client := &http.Client{}
	r, _ := http.NewRequest("POST", "https://rest.nexmo.com/sms/json", bytes.NewBufferString(values.Encode())) // <-- URL-encoded payload
	r.Header.Add("Accept", "application/json")
	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	// r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

	resp, err := client.Do(r)
	defer resp.Body.Close()

	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(resp.Body)

	err = json.Unmarshal(body, &messageResponse)
	if err != nil {
		return nil, err
	} else {
		return messageResponse, nil
	}
}

// SendTextMessage() sends a normal SMS
func (nexmo *Nexmo) SendTextMessage(from, to, text, clientReference string, statusReportRequired bool) (*MessageResponse, error) {
	return nexmo.sendMessage(from, to, text, clientReference, statusReportRequired, false)
}

// SendFlashMessage() sends a class 0 SMS (Flash message).
func (nexmo *Nexmo) SendFlashMessage(from, to, text, clientReference string, statusReportRequired bool) (*MessageResponse, error) {
	return nexmo.sendMessage(from, to, text, clientReference, statusReportRequired, true)
}

// GetBalance() retrieves the current balance of your Nexmo account in Euros (€)
func (nexmo *Nexmo) GetBalance() (float64, error) {
	var accBalance *AccountBalance

	client := &http.Client{}
	r, _ := http.NewRequest("GET", "https://rest.nexmo.com/account/get-balance/"+nexmo.apiKey+"/"+nexmo.apiSecret, nil)
	r.Header.Add("Accept", "application/json")

	resp, err := client.Do(r)
	defer resp.Body.Close()

	if err != nil {
		return 0.0, err
	}

	body, _ := ioutil.ReadAll(resp.Body)

	err = json.Unmarshal(body, &accBalance)
	if err != nil {
		return 0.0, err
	} else {
		return accBalance.Value, nil
	}
}
<|endoftext|>


<commit_before>package gpsutil

import (
	"math"
)

type LatLng struct {
	lat float64
	lng float64
}

func (latlng *LatLng) Lat() float64 {
	return latlng.lat
}

func (latlng *LatLng) Lng() float64 {
	return latlng.lng
}

type GeohashDecoded struct {
	lat float64
	lng float64
	err struct {
		lat float64
		lgn float64
	}
}

type BBox struct {
	Southwest *LatLng
	Northeast *LatLng
	Center    *LatLng
}

func toRad(decDegrees float64) float64 {
	return decDegrees * math.Pi / 180.0
}

func toDegrees(radians float64) float64 {
	return 180.0 * radians / math.Pi
}
<commit_msg>Redefine BBox and GeohashDecoded  type<commit_after>package gpsutil

import (
	"math"
)

type LatLng struct {
	lat float64
	lng float64
}

func (latlng *LatLng) Lat() float64 {
	return latlng.lat
}

func (latlng *LatLng) Lng() float64 {
	return latlng.lng
}

type GeohashDecoded struct {
	lat    float64
	lng    float64
	latErr float64
	lgnErr float64
}

func (ghd *GeohashDecoded) Lat() float64 {
	return ghd.lat
}

func (ghd *GeohashDecoded) Lng() float64 {
	return ghd.lng
}

func (ghd *GeohashDecoded) LatErr() float64 {
	return ghd.latErr
}

func (ghd *GeohashDecoded) LngErr() float64 {
	return ghd.lgnErr
}

type BBox struct {
	southwest *LatLng
	northeast *LatLng
	center    *LatLng
}

func (bbox *BBox) Southwest() *LatLng {
	return bbox.southwest
}

func (bbox *BBox) Northeast() *LatLng {
	return bbox.northeast
}

func (bbox *BBox) Center() *LatLng {
	return bbox.center
}

func toRad(decDegrees float64) float64 {
	return decDegrees * math.Pi / 180.0
}

func toDegrees(radians float64) float64 {
	return 180.0 * radians / math.Pi
}
<|endoftext|>


<commit_before>package term

import (
	"io"

	"golang.org/x/mobile/event/key"
	"golang.org/x/mobile/event/mouse"

	"github.com/gdamore/tcell"
	"github.com/mibk/syd/ui"
)

type UI struct {
	screen        tcell.Screen
	wasBtnPressed bool

	y      int
	width  int
	height int

	firstWin   *Window
	activeText *Text   // will receive key events
	grabbedWin *Window // index of the grabbed win or nil
}

func (t *UI) Init() error {
	sc, err := tcell.NewScreen()
	if err != nil {
		return err
	}
	if err := sc.Init(); err != nil {
		return err
	}
	sc.EnableMouse()
	t.screen = sc

	// TODO: Just for testing purposes.
	t.y = 1
	w, h := t.Size()
	t.width = w / 2
	t.height = h - 2

	go t.translateEvents()
	return nil
}

func (t *UI) Close() error {
	t.screen.Fini()
	return nil
}

func (t *UI) Size() (w, h int) { return t.screen.Size() }

func (t *UI) NewWindow() *Window {
	head := &Text{
		frame: new(Frame),
		bgstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#eaffff")),
		hlstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#90e0e0")),
	}
	body := &Text{
		frame: new(Frame),
		bgstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#ffffea")),
		hlstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#e0e090")),
	}
	win := &Window{
		y:     t.y,
		width: t.width,
		ui:    t,
		head:  head,
		body:  body,
	}
	head.win = win
	body.win = win

	if t.firstWin == nil {
		t.activeText = body
		t.firstWin = win
	} else {
		prev := t.lastWin()
		win.y = prev.y + prev.height()/2
		prev.nextWin = win
	}
	return win
}

func (t *UI) Flush() {
	win := t.firstWin
	for win != nil {
		win.flush()
		win = win.nextWin
	}
}

// TODO: This is for temporary reasons. Remove it.
func (t *UI) Push_Mouse_Event(ev mouse.Event) {
	y := int(ev.Y)
	if t.grabbedWin != nil {
		if ev.Direction == mouse.DirRelease {
			t.moveGrabbedWin(y)
		}
		return
	}
	win := t.firstWin
	for win != nil {
		if y < win.y || y >= win.y+win.height() {
			win = win.nextWin
			continue
		}
		if y >= win.body.y {
			win.body.click(ev)
			t.activeText = win.body
		} else {
			if int(ev.X) == win.x && ev.Direction == mouse.DirPress {
				t.grabbedWin = win
				break
			}
			win.head.click(ev)
			t.activeText = win.head
		}
		break
	}
}

func (t *UI) Push_Key_Event(ev key.Event) {
	t.activeText.keyEventHandler(ev)
}

func (t *UI) lastWin() *Window {
	win := t.firstWin
	if win == nil {
		return nil
	}
	for win.nextWin != nil {
		win = win.nextWin
	}
	return win
}

func (t *UI) moveGrabbedWin(y int) {
	target := t.firstWin
	if target.nextWin == nil {
		// Cannot move anything if there's just one
		// window.
		return
	}
	for target != nil {
		if y >= target.y && y < target.y+target.height() {
			break
		}
		target = target.nextWin
	}

	if t.grabbedWin == target || (target.nextWin != nil && t.grabbedWin == target.nextWin) {
		if t.grabbedWin != t.firstWin {
			t.grabbedWin.y = y
		}
	}
	t.grabbedWin = nil
}

type Window struct {
	ui *UI

	width int
	x, y  int

	head *Text
	body *Text

	nextWin *Window
}

func (win *Window) Size() (w, h int) {
	return win.width, win.height()
}

func (win *Window) Head() *Text { return win.head }
func (win *Window) Body() *Text { return win.body }

func (win *Window) Clear() {
	h := win.height()
	win.head.width = win.width - 1
	win.head.height = h - 1
	win.head.clear()

	win.body.width = win.width
	win.body.height = h
	win.body.clear()
}

func (win *Window) flush() {
	win.head.x = win.x + 1
	win.head.y = win.y
	win.head.flush()

	h := len(win.head.frame.lines)
	win.head.height = h

	y := 0
	for ; y < h; y++ {
		win.ui.screen.SetContent(win.x, win.y+y, ' ', nil, win.head.bgstyle)
	}
	winh := win.height()
	for ; y < winh; y++ {
		win.ui.screen.SetContent(win.x, win.y+y, ' ', nil, win.body.bgstyle)
	}

	win.body.height = winh - h
	if len(win.body.frame.lines) > win.body.height {
		// TODO: We didn't know how many lines will the head of the window
		// span. Can we do better?
		win.body.frame.lines = win.body.frame.lines[:win.body.height]
	}
	win.body.x = win.x + 1
	win.body.y = win.y + h
	win.body.flush()
	win.body.fill()

	win.ui.screen.Show()
}

func (win *Window) height() int {
	if win.nextWin == nil {
		return win.ui.y + win.ui.height - win.y
	}
	return win.nextWin.y - win.y
}

type Text struct {
	win   *Window
	frame *Frame

	width, height int
	x, y          int
	cur           struct {
		p0, p1 int // char position
		x, y   int // current position
	}

	// styles
	bgstyle tcell.Style
	hlstyle tcell.Style

	mouseEventHandler ui.MouseEventHandler
	keyEventHandler   ui.KeyEventHandler
}

func (t *Text) click(ev mouse.Event) {
	if t.mouseEventHandler == nil {
		return
	}
	p := t.frame.CharsUntilXY(int(ev.X)-t.x, int(ev.Y)-t.y)
	t.mouseEventHandler(p, ev)
}

func (t *Text) OnMouseEvent(h ui.MouseEventHandler) {
	t.mouseEventHandler = h
}

func (t *Text) OnKeyEvent(h ui.KeyEventHandler) {
	t.keyEventHandler = h
}

func (t *Text) clear() {
	*t.frame = Frame{
		lines:   make([][]rune, 1),
		wantCol: t.frame.wantCol,
	}
	t.cur.x, t.cur.y = 0, 0
	t.checkSelection()
}

func (t *Text) Select(p0, p1 int) { t.cur.p0, t.cur.p1 = p0, p1 }

func (t *Text) WriteRune(r rune) error {
	t.frame.lines[t.cur.y] = append(t.frame.lines[t.cur.y], r)
	if r == '\t' {
		t.cur.x += tabWidthForCol(t.cur.x)
	} else {
		t.cur.x++
	}

	if t.cur.x >= t.width || r == '\n' {
		t.cur.y++
		t.cur.x = 0
		t.frame.lines = append(t.frame.lines, nil)
		if t.cur.y == t.height {
			return io.EOF
		}
	}

	t.frame.nchars++
	t.checkSelection()
	return nil
}

// checkSelection tries to line0, line1, and wantCol.
func (t *Text) checkSelection() {
	if t.cur.p0 == t.frame.nchars {
		t.frame.line0 = t.cur.y
		if t.frame.wantCol == ui.ColQ0 {
			t.frame.wantCol = t.cur.x
		}
	}
	if t.cur.p1 == t.frame.nchars {
		t.frame.line1 = t.cur.y
		if t.frame.wantCol == ui.ColQ1 {
			t.frame.wantCol = t.cur.x
		}
	}
}

var reverse = tcell.StyleDefault.Reverse(true)

func (t *Text) flush() {
	style := t.bgstyle
	selStyle := func(p int) {
		if p == t.cur.p0 && t.cur.p0 == t.cur.p1 {
			style = reverse
		} else if p >= t.cur.p0 && p < t.cur.p1 {
			style = t.hlstyle
		} else {
			style = t.bgstyle
		}
	}
	p := 0
	for y, l := range t.frame.lines {
		x := 0
		for _, r := range l {
			selStyle(p)
			p++
			if r == '\n' {
				goto fill
			}
			w := 1
			if r == '\t' {
				r = ' '
				w = tabWidthForCol(x)
			}
			for i := 0; i < w && x < t.width; i++ {
				// TODO: Should the rest of the tab at the end of a
				// line span the begining of the next line?
				t.win.ui.screen.SetContent(t.x+x, t.y+y, r, nil, style)
				x++
				if style == reverse {
					style = t.bgstyle
				}
			}
		}
		selStyle(p)
	fill:
		for ; x < t.width; x++ {
			t.win.ui.screen.SetContent(t.x+x, t.y+y, ' ', nil, style)
			if style == reverse {
				style = t.bgstyle
			}
		}
	}
}

func (t *Text) fill() {
	// TODO: Using this bg color just for testing purposes.
	bg := tcell.StyleDefault.Background(tcell.GetColor("#ffe0ff"))
	for y := len(t.frame.lines); y < t.height; y++ {
		for x := 0; x < t.width; x++ {
			t.win.ui.screen.SetContent(t.x+x, t.y+y, ' ', nil, bg)
		}
	}
}

func (t *Text) Frame() *Frame { return t.frame }

type Frame struct {
	lines   [][]rune
	line0   int
	line1   int
	wantCol int
	nchars  int
}

func (f *Frame) Nchars() int                { return f.nchars }
func (f *Frame) SelectionLines() (int, int) { return f.line0, f.line1 }

func (f *Frame) CharsUntilXY(x, y int) int {
	if y >= len(f.lines) {
		return f.nchars
	}
	var p int
	for n, l := range f.lines {
		if n == y {
			return p + charsUntilX(l, x)
		}
		p += len(l)
	}
	return 0
}

func charsUntilX(s []rune, x int) int {
	if len(s) == 0 {
		return 0
	}
	var w int
	for i, r := range s {
		if r == '\t' {
			w += tabWidthForCol(w)
		} else {
			w += 1
		}
		if w > x {
			return i
		}
	}
	if s[len(s)-1] == '\n' {
		return len(s) - 1
	}
	return len(s)
}

const tabStop = 8

func tabWidthForCol(col int) int {
	w := tabStop - col%tabStop
	if w == 0 {
		return tabStop
	}
	return w
}

func (f *Frame) Lines() int         { return len(f.lines) }
func (f *Frame) WantCol() int       { return f.wantCol }
func (f *Frame) SetWantCol(col int) { f.wantCol = col }
<commit_msg>ui/term: Implement changing window order by grabbing them<commit_after>package term

import (
	"io"

	"golang.org/x/mobile/event/key"
	"golang.org/x/mobile/event/mouse"

	"github.com/gdamore/tcell"
	"github.com/mibk/syd/ui"
)

type UI struct {
	screen        tcell.Screen
	wasBtnPressed bool

	y      int
	width  int
	height int

	firstWin   *Window
	activeText *Text   // will receive key events
	grabbedWin *Window // index of the grabbed win or nil
}

func (t *UI) Init() error {
	sc, err := tcell.NewScreen()
	if err != nil {
		return err
	}
	if err := sc.Init(); err != nil {
		return err
	}
	sc.EnableMouse()
	t.screen = sc

	// TODO: Just for testing purposes.
	t.y = 1
	w, h := t.Size()
	t.width = w / 2
	t.height = h - 2

	go t.translateEvents()
	return nil
}

func (t *UI) Close() error {
	t.screen.Fini()
	return nil
}

func (t *UI) Size() (w, h int) { return t.screen.Size() }

func (t *UI) NewWindow() *Window {
	head := &Text{
		frame: new(Frame),
		bgstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#eaffff")),
		hlstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#90e0e0")),
	}
	body := &Text{
		frame: new(Frame),
		bgstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#ffffea")),
		hlstyle: tcell.StyleDefault.
			Background(tcell.GetColor("#e0e090")),
	}
	win := &Window{
		y:     t.y,
		width: t.width,
		ui:    t,
		head:  head,
		body:  body,
	}
	head.win = win
	body.win = win

	if t.firstWin == nil {
		t.activeText = body
		t.firstWin = win
	} else {
		prev := t.lastWin()
		win.y = prev.y + prev.height()/2
		prev.nextWin = win
	}
	return win
}

func (t *UI) Flush() {
	win := t.firstWin
	for win != nil {
		win.flush()
		win = win.nextWin
	}
}

// TODO: This is for temporary reasons. Remove it.
func (t *UI) Push_Mouse_Event(ev mouse.Event) {
	y := int(ev.Y)
	if t.grabbedWin != nil {
		if ev.Direction == mouse.DirRelease {
			t.moveGrabbedWin(y)
		}
		return
	}
	win := t.firstWin
	for win != nil {
		if y < win.y || y >= win.y+win.height() {
			win = win.nextWin
			continue
		}
		if y >= win.body.y {
			win.body.click(ev)
			t.activeText = win.body
		} else {
			if int(ev.X) == win.x && ev.Direction == mouse.DirPress {
				t.grabbedWin = win
				break
			}
			win.head.click(ev)
			t.activeText = win.head
		}
		break
	}
}

func (t *UI) Push_Key_Event(ev key.Event) {
	t.activeText.keyEventHandler(ev)
}

func (t *UI) lastWin() *Window {
	win := t.firstWin
	if win == nil {
		return nil
	}
	for win.nextWin != nil {
		win = win.nextWin
	}
	return win
}

func (t *UI) moveGrabbedWin(y int) {
	gw := t.grabbedWin
	t.grabbedWin = nil
	target := t.firstWin

	if target.nextWin == nil {
		// Cannot move anything if there's just one
		// window.
		return
	}

	for target != nil {
		if y >= target.y && y < target.y+target.height() {
			break
		}
		target = target.nextWin
	}

	if y == target.y {
		// TODO: If this happens, adjust position of the windows
		// to ensure at least one line of each window is shown.
		// Forbid it for now as it would cause panic otherwise.
		return
	}

	if gw == target || (target.nextWin != nil && gw == target.nextWin) {
		if gw == t.firstWin {
			return
		}
	} else {
		t.moveWin(gw, target)
	}
	gw.y = y
}

func (t *UI) moveWin(win, after *Window) {
	sentinel := &Window{nextWin: t.firstWin}
	prev := sentinel
	for prev.nextWin != nil {
		if prev.nextWin == win {
			prev.nextWin = win.nextWin
			win.nextWin = after.nextWin
			after.nextWin = win

			t.firstWin = sentinel.nextWin
			t.firstWin.y = t.y
			return
		}
		prev = prev.nextWin
	}
	panic("window not found")
}

type Window struct {
	ui *UI

	width int
	x, y  int

	head *Text
	body *Text

	nextWin *Window
}

func (win *Window) Size() (w, h int) {
	return win.width, win.height()
}

func (win *Window) Head() *Text { return win.head }
func (win *Window) Body() *Text { return win.body }

func (win *Window) Clear() {
	h := win.height()
	win.head.width = win.width - 1
	win.head.height = h - 1
	win.head.clear()

	win.body.width = win.width
	win.body.height = h
	win.body.clear()
}

func (win *Window) flush() {
	win.head.x = win.x + 1
	win.head.y = win.y
	win.head.flush()

	h := len(win.head.frame.lines)
	win.head.height = h

	y := 0
	for ; y < h; y++ {
		win.ui.screen.SetContent(win.x, win.y+y, ' ', nil, win.head.bgstyle)
	}
	winh := win.height()
	for ; y < winh; y++ {
		win.ui.screen.SetContent(win.x, win.y+y, ' ', nil, win.body.bgstyle)
	}

	win.body.height = winh - h
	if len(win.body.frame.lines) > win.body.height {
		// TODO: We didn't know how many lines will the head of the window
		// span. Can we do better?
		win.body.frame.lines = win.body.frame.lines[:win.body.height]
	}
	win.body.x = win.x + 1
	win.body.y = win.y + h
	win.body.flush()
	win.body.fill()

	win.ui.screen.Show()
}

func (win *Window) height() int {
	if win.nextWin == nil {
		return win.ui.y + win.ui.height - win.y
	}
	return win.nextWin.y - win.y
}

type Text struct {
	win   *Window
	frame *Frame

	width, height int
	x, y          int
	cur           struct {
		p0, p1 int // char position
		x, y   int // current position
	}

	// styles
	bgstyle tcell.Style
	hlstyle tcell.Style

	mouseEventHandler ui.MouseEventHandler
	keyEventHandler   ui.KeyEventHandler
}

func (t *Text) click(ev mouse.Event) {
	if t.mouseEventHandler == nil {
		return
	}
	p := t.frame.CharsUntilXY(int(ev.X)-t.x, int(ev.Y)-t.y)
	t.mouseEventHandler(p, ev)
}

func (t *Text) OnMouseEvent(h ui.MouseEventHandler) {
	t.mouseEventHandler = h
}

func (t *Text) OnKeyEvent(h ui.KeyEventHandler) {
	t.keyEventHandler = h
}

func (t *Text) clear() {
	*t.frame = Frame{
		lines:   make([][]rune, 1),
		wantCol: t.frame.wantCol,
	}
	t.cur.x, t.cur.y = 0, 0
	t.checkSelection()
}

func (t *Text) Select(p0, p1 int) { t.cur.p0, t.cur.p1 = p0, p1 }

func (t *Text) WriteRune(r rune) error {
	t.frame.lines[t.cur.y] = append(t.frame.lines[t.cur.y], r)
	if r == '\t' {
		t.cur.x += tabWidthForCol(t.cur.x)
	} else {
		t.cur.x++
	}

	if t.cur.x >= t.width || r == '\n' {
		t.cur.y++
		t.cur.x = 0
		t.frame.lines = append(t.frame.lines, nil)
		if t.cur.y == t.height {
			return io.EOF
		}
	}

	t.frame.nchars++
	t.checkSelection()
	return nil
}

// checkSelection tries to line0, line1, and wantCol.
func (t *Text) checkSelection() {
	if t.cur.p0 == t.frame.nchars {
		t.frame.line0 = t.cur.y
		if t.frame.wantCol == ui.ColQ0 {
			t.frame.wantCol = t.cur.x
		}
	}
	if t.cur.p1 == t.frame.nchars {
		t.frame.line1 = t.cur.y
		if t.frame.wantCol == ui.ColQ1 {
			t.frame.wantCol = t.cur.x
		}
	}
}

var reverse = tcell.StyleDefault.Reverse(true)

func (t *Text) flush() {
	style := t.bgstyle
	selStyle := func(p int) {
		if p == t.cur.p0 && t.cur.p0 == t.cur.p1 {
			style = reverse
		} else if p >= t.cur.p0 && p < t.cur.p1 {
			style = t.hlstyle
		} else {
			style = t.bgstyle
		}
	}
	p := 0
	for y, l := range t.frame.lines {
		x := 0
		for _, r := range l {
			selStyle(p)
			p++
			if r == '\n' {
				goto fill
			}
			w := 1
			if r == '\t' {
				r = ' '
				w = tabWidthForCol(x)
			}
			for i := 0; i < w && x < t.width; i++ {
				// TODO: Should the rest of the tab at the end of a
				// line span the begining of the next line?
				t.win.ui.screen.SetContent(t.x+x, t.y+y, r, nil, style)
				x++
				if style == reverse {
					style = t.bgstyle
				}
			}
		}
		selStyle(p)
	fill:
		for ; x < t.width; x++ {
			t.win.ui.screen.SetContent(t.x+x, t.y+y, ' ', nil, style)
			if style == reverse {
				style = t.bgstyle
			}
		}
	}
}

func (t *Text) fill() {
	// TODO: Using this bg color just for testing purposes.
	bg := tcell.StyleDefault.Background(tcell.GetColor("#ffe0ff"))
	for y := len(t.frame.lines); y < t.height; y++ {
		for x := 0; x < t.width; x++ {
			t.win.ui.screen.SetContent(t.x+x, t.y+y, ' ', nil, bg)
		}
	}
}

func (t *Text) Frame() *Frame { return t.frame }

type Frame struct {
	lines   [][]rune
	line0   int
	line1   int
	wantCol int
	nchars  int
}

func (f *Frame) Nchars() int                { return f.nchars }
func (f *Frame) SelectionLines() (int, int) { return f.line0, f.line1 }

func (f *Frame) CharsUntilXY(x, y int) int {
	if y >= len(f.lines) {
		return f.nchars
	}
	var p int
	for n, l := range f.lines {
		if n == y {
			return p + charsUntilX(l, x)
		}
		p += len(l)
	}
	return 0
}

func charsUntilX(s []rune, x int) int {
	if len(s) == 0 {
		return 0
	}
	var w int
	for i, r := range s {
		if r == '\t' {
			w += tabWidthForCol(w)
		} else {
			w += 1
		}
		if w > x {
			return i
		}
	}
	if s[len(s)-1] == '\n' {
		return len(s) - 1
	}
	return len(s)
}

const tabStop = 8

func tabWidthForCol(col int) int {
	w := tabStop - col%tabStop
	if w == 0 {
		return tabStop
	}
	return w
}

func (f *Frame) Lines() int         { return len(f.lines) }
func (f *Frame) WantCol() int       { return f.wantCol }
func (f *Frame) SetWantCol(col int) { f.wantCol = col }
<|endoftext|>


<commit_before>package universe

import (
	"fmt"
	"log"
	"net"
	"sync"
	"time"
)

func tcpSender(options TallyOptions, url TallyURL) (*TCPSender, error) {
	var addr = url.Addr()
	var tcpSender = TCPSender{
		options:  options,
		sendChan: make(chan []byte, options.SendBuffer),
	}

	if tcpAddr, err := net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, fmt.Errorf("ResolveTCPAddr %v: %v", addr, err)
	} else {
		tcpSender.tcpAddr = tcpAddr
	}

	log.Printf("universe:TCPSender: %v", &tcpSender)

	tcpSender.runWG.Add(1)
	go tcpSender.run()

	return &tcpSender, nil
}

type TCPSender struct {
	options TallyOptions

	tcpAddr *net.TCPAddr
	tcpConn *net.TCPConn
	err     error

	sendChan chan []byte
	runWG    sync.WaitGroup
}

func (tcpSender *TCPSender) String() string {
	return "tcp://" + tcpSender.tcpAddr.String()
}

func (tcpSender *TCPSender) connect() error {
	if tcpConn, err := net.DialTCP("tcp", nil, tcpSender.tcpAddr); err != nil {
		return fmt.Errorf("DialTCP %v: %v", tcpSender.tcpAddr, err)
	} else {
		tcpSender.tcpConn = tcpConn
	}

	return nil
}

func (tcpSender *TCPSender) send(msg []byte) error {
	log.Printf("universe:TCPSender %v: send msg=%#v", udpSender, string(msg))

	if err := tcpSender.tcpConn.SetWriteDeadline(time.Now().Add(tcpSender.options.Timeout)); err != nil {
		return err
	}

	if _, err := tcpSender.tcpConn.Write(msg); err != nil {
		return err
	}

	return nil
}

func (tcpSender *TCPSender) close() error {
	tcpSender.err = tcpSender.tcpConn.Close()

	tcpSender.tcpConn = nil

	return tcpSender.err
}

func (tcpSender *TCPSender) run() {
	defer tcpSender.runWG.Done()
	defer tcpSender.close()

	// TODO: flush messages on reconnect...?
	for msg := range tcpSender.sendChan {
		if tcpSender.tcpConn != nil {

		} else if err := tcpSender.connect(); err != nil {
			tcpSender.err = err
			log.Printf("universe:TCPSender %v: drop connect: %v", tcpSender, err)
			continue
		}

		if err := tcpSender.send(msg); err != nil {
			log.Printf("universe:TCPSender %v: drop send: %v", tcpSender, err)

			tcpSender.close()
			tcpSender.err = err
		}
	}
}

func (tcpSender *TCPSender) Send(msg []byte) error {
	select {
	case tcpSender.sendChan <- msg:
		return nil
	default:
		log.Printf("universe:TCPSender %v: send dropped", tcpSender)
	}

	return nil
}

func (tcpSender *TCPSender) Close() error {
	close(tcpSender.sendChan)

	tcpSender.runWG.Wait()

	return tcpSender.err
}
<commit_msg>universe: docdoc TCPSender write-only<commit_after>package universe

import (
	"fmt"
	"log"
	"net"
	"sync"
	"time"
)

func tcpSender(options TallyOptions, url TallyURL) (*TCPSender, error) {
	var addr = url.Addr()
	var tcpSender = TCPSender{
		options:  options,
		sendChan: make(chan []byte, options.SendBuffer),
	}

	if tcpAddr, err := net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, fmt.Errorf("ResolveTCPAddr %v: %v", addr, err)
	} else {
		tcpSender.tcpAddr = tcpAddr
	}

	log.Printf("universe:TCPSender: %v", &tcpSender)

	tcpSender.runWG.Add(1)
	go tcpSender.run()

	return &tcpSender, nil
}

// The TCP connection is uni-directional. It is only used to send commands,
// and we do not expect to ever receive any commands.
// TODO: consider net:TCPConn.CloseRead?
type TCPSender struct {
	options TallyOptions

	tcpAddr *net.TCPAddr
	tcpConn *net.TCPConn
	err     error

	sendChan chan []byte
	runWG    sync.WaitGroup
}

func (tcpSender *TCPSender) String() string {
	return "tcp://" + tcpSender.tcpAddr.String()
}

func (tcpSender *TCPSender) connect() error {
	if tcpConn, err := net.DialTCP("tcp", nil, tcpSender.tcpAddr); err != nil {
		return fmt.Errorf("DialTCP %v: %v", tcpSender.tcpAddr, err)
	} else {
		tcpSender.tcpConn = tcpConn
	}

	return nil
}

func (tcpSender *TCPSender) send(msg []byte) error {
	log.Printf("universe:TCPSender %v: send msg=%#v", udpSender, string(msg))

	if err := tcpSender.tcpConn.SetWriteDeadline(time.Now().Add(tcpSender.options.Timeout)); err != nil {
		return err
	}

	if _, err := tcpSender.tcpConn.Write(msg); err != nil {
		return err
	}

	return nil
}

func (tcpSender *TCPSender) close() error {
	tcpSender.err = tcpSender.tcpConn.Close()

	tcpSender.tcpConn = nil

	return tcpSender.err
}

func (tcpSender *TCPSender) run() {
	defer tcpSender.runWG.Done()
	defer tcpSender.close()

	// TODO: flush messages on reconnect...?
	for msg := range tcpSender.sendChan {
		if tcpSender.tcpConn != nil {

		} else if err := tcpSender.connect(); err != nil {
			tcpSender.err = err
			log.Printf("universe:TCPSender %v: drop connect: %v", tcpSender, err)
			continue
		}

		if err := tcpSender.send(msg); err != nil {
			log.Printf("universe:TCPSender %v: drop send: %v", tcpSender, err)

			tcpSender.close()
			tcpSender.err = err
		}
	}
}

func (tcpSender *TCPSender) Send(msg []byte) error {
	select {
	case tcpSender.sendChan <- msg:
		return nil
	default:
		log.Printf("universe:TCPSender %v: send dropped", tcpSender)
	}

	return nil
}

func (tcpSender *TCPSender) Close() error {
	close(tcpSender.sendChan)

	tcpSender.runWG.Wait()

	return tcpSender.err
}
<|endoftext|>


<commit_before>package openvswitch

import (
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"github.com/lxc/lxd/shared"
)

// ovnBridgeMappingMutex locks access to read/write external-ids:ovn-bridge-mappings.
var ovnBridgeMappingMutex sync.Mutex

// NewOVS initialises new OVS wrapper.
func NewOVS() *OVS {
	return &OVS{}
}

// OVS command wrapper.
type OVS struct{}

// Installed returns true if OVS tools are installed.
func (o *OVS) Installed() bool {
	_, err := exec.LookPath("ovs-vsctl")
	if err != nil {
		return false
	}

	return true
}

// BridgeExists returns true if OVS bridge exists.
func (o *OVS) BridgeExists(bridgeName string) (bool, error) {
	_, err := shared.RunCommand("ovs-vsctl", "br-exists", bridgeName)
	if err != nil {
		runErr, ok := err.(shared.RunError)
		if ok {
			exitError, ok := runErr.Err.(*exec.ExitError)

			// ovs-vsctl manpage says that br-exists exits with code 2 if bridge doesn't exist.
			if ok && exitError.ExitCode() == 2 {
				return false, nil
			}
		}

		return false, err
	}

	return true, nil
}

// BridgeAdd adds an OVS bridge.
func (o *OVS) BridgeAdd(bridgeName string, mayExist bool) error {
	args := []string{}

	if mayExist {
		args = append(args, "--may-exist")
	}

	args = append(args, "add-br", bridgeName)

	_, err := shared.RunCommand("ovs-vsctl", args...)
	if err != nil {
		return err
	}

	return nil
}

// BridgeDelete deletes an OVS bridge.
func (o *OVS) BridgeDelete(bridgeName string) error {
	_, err := shared.RunCommand("ovs-vsctl", "del-br", bridgeName)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortAdd adds a port to the bridge (if already attached does nothing).
func (o *OVS) BridgePortAdd(bridgeName string, portName string, mayExist bool) error {
	args := []string{}

	if mayExist {
		args = append(args, "--may-exist")
	}

	args = append(args, "add-port", bridgeName, portName)

	_, err := shared.RunCommand("ovs-vsctl", args...)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortDelete deletes a port from the bridge (if already detached does nothing).
func (o *OVS) BridgePortDelete(bridgeName string, portName string) error {
	_, err := shared.RunCommand("ovs-vsctl", "--if-exists", "del-port", bridgeName, portName)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortSet sets port options.
func (o *OVS) BridgePortSet(portName string, options ...string) error {
	_, err := shared.RunCommand("ovs-vsctl", append([]string{"set", "port", portName}, options...)...)
	if err != nil {
		return err
	}

	return nil
}

// InterfaceAssociateOVNSwitchPort removes any existing OVS ports associated to the specified ovnSwitchPortName
// and then associates the specified interfaceName to the OVN switch port.
func (o *OVS) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitchPortName OVNSwitchPort) error {
	// Clear existing ports that were formerly associated to ovnSwitchPortName.
	existingPorts, err := shared.RunCommand("ovs-vsctl", "--format=csv", "--no-headings", "--data=bare", "--colum=name", "find", "interface", fmt.Sprintf("external-ids:iface-id=%s", string(ovnSwitchPortName)))
	if err != nil {
		return err
	}

	existingPorts = strings.TrimSpace(existingPorts)
	if existingPorts != "" {
		for _, port := range strings.Split(existingPorts, "\n") {
			_, err = shared.RunCommand("ovs-vsctl", "del-port", port)
			if err != nil {
				return err
			}

			// Atempt to remove port, but don't fail if doesn't exist or can't be removed, at least
			// the OVS association has been successfully removed, so the new port being added next
			// won't fail to work properly.
			shared.RunCommand("ip", "link", "del", port)
		}
	}

	_, err = shared.RunCommand("ovs-vsctl", "set", "interface", interfaceName, fmt.Sprintf("external_ids:iface-id=%s", string(ovnSwitchPortName)))
	if err != nil {
		return err
	}

	return nil
}

// ChassisID returns the local chassis ID.
func (o *OVS) ChassisID() (string, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	chassisID, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:system-id")
	if err != nil {
		return "", err
	}

	chassisID = strings.TrimSpace(chassisID)
	chassisID, err = strconv.Unquote(chassisID)
	if err != nil {
		return "", err
	}

	return chassisID, nil
}

// OVNEncapIP returns the enscapsulation IP used for OVN underlay tunnels.
func (o *OVS) OVNEncapIP() (net.IP, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	encapIPStr, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:ovn-encap-ip")
	if err != nil {
		return nil, err
	}

	encapIPStr = strings.TrimSpace(encapIPStr)
	encapIPStr, err = strconv.Unquote(encapIPStr)
	if err != nil {
		return nil, err
	}

	encapIP := net.ParseIP(encapIPStr)
	if encapIP == nil {
		return nil, fmt.Errorf("Invalid ovn-encap-ip address")
	}

	return encapIP, nil
}

// OVNBridgeMappings gets the current OVN bridge mappings.
func (o *OVS) OVNBridgeMappings(bridgeName string) ([]string, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	mappings, err := shared.RunCommand("ovs-vsctl", "--if-exists", "get", "open_vswitch", ".", "external-ids:ovn-bridge-mappings")
	if err != nil {
		return nil, err
	}

	mappings = strings.TrimSpace(mappings)
	if mappings == "" {
		return []string{}, nil
	}

	mappings, err = strconv.Unquote(mappings)
	if err != nil {
		return nil, err
	}

	return strings.SplitN(mappings, ",", -1), nil
}

// OVNBridgeMappingAdd appends an OVN bridge mapping between an OVS bridge and the logical provider name.
func (o *OVS) OVNBridgeMappingAdd(bridgeName string, providerName string) error {
	ovnBridgeMappingMutex.Lock()
	defer ovnBridgeMappingMutex.Unlock()

	mappings, err := o.OVNBridgeMappings(bridgeName)
	if err != nil {
		return err
	}

	newMapping := fmt.Sprintf("%s:%s", providerName, bridgeName)
	for _, mapping := range mappings {
		if mapping == newMapping {
			return nil // Mapping is already present, nothing to do.
		}
	}

	mappings = append(mappings, newMapping)

	// Set new mapping string back into OVS database.
	_, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(mappings, ",")))
	if err != nil {
		return err
	}

	return nil
}

// OVNBridgeMappingDelete deletes an OVN bridge mapping between an OVS bridge and the logical provider name.
func (o *OVS) OVNBridgeMappingDelete(bridgeName string, providerName string) error {
	ovnBridgeMappingMutex.Lock()
	defer ovnBridgeMappingMutex.Unlock()

	mappings, err := o.OVNBridgeMappings(bridgeName)
	if err != nil {
		return err
	}

	changed := false
	newMappings := make([]string, 0, len(mappings))
	matchMapping := fmt.Sprintf("%s:%s", providerName, bridgeName)
	for _, mapping := range mappings {
		if mapping != matchMapping {
			newMappings = append(newMappings, mapping)
		} else {
			changed = true
		}
	}

	if changed {
		if len(newMappings) < 1 {
			// Remove mapping key in OVS database.
			_, err = shared.RunCommand("ovs-vsctl", "remove", "open_vswitch", ".", "external-ids", "ovn-bridge-mappings")
			if err != nil {
				return err
			}
		} else {
			// Set updated mapping string back into OVS database.
			_, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(newMappings, ",")))
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// BridgePortList returns a list of ports that are connected to the bridge.
func (o *OVS) BridgePortList(bridgeName string) ([]string, error) {
	// Clear existing ports that were formerly associated to ovnSwitchPortName.
	portString, err := shared.RunCommand("ovs-vsctl", "list-ports", bridgeName)
	if err != nil {
		return nil, err
	}

	ports := []string{}

	portString = strings.TrimSpace(portString)
	if portString != "" {
		for _, port := range strings.Split(portString, "\n") {
			ports = append(ports, strings.TrimSpace(port))
		}
	}

	return ports, nil
}
<commit_msg>lxd/network/openvswitch/ovs: Adds InterfaceAssociatedOVNSwitchPort function<commit_after>package openvswitch

import (
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"github.com/lxc/lxd/shared"
)

// ovnBridgeMappingMutex locks access to read/write external-ids:ovn-bridge-mappings.
var ovnBridgeMappingMutex sync.Mutex

// NewOVS initialises new OVS wrapper.
func NewOVS() *OVS {
	return &OVS{}
}

// OVS command wrapper.
type OVS struct{}

// Installed returns true if OVS tools are installed.
func (o *OVS) Installed() bool {
	_, err := exec.LookPath("ovs-vsctl")
	if err != nil {
		return false
	}

	return true
}

// BridgeExists returns true if OVS bridge exists.
func (o *OVS) BridgeExists(bridgeName string) (bool, error) {
	_, err := shared.RunCommand("ovs-vsctl", "br-exists", bridgeName)
	if err != nil {
		runErr, ok := err.(shared.RunError)
		if ok {
			exitError, ok := runErr.Err.(*exec.ExitError)

			// ovs-vsctl manpage says that br-exists exits with code 2 if bridge doesn't exist.
			if ok && exitError.ExitCode() == 2 {
				return false, nil
			}
		}

		return false, err
	}

	return true, nil
}

// BridgeAdd adds an OVS bridge.
func (o *OVS) BridgeAdd(bridgeName string, mayExist bool) error {
	args := []string{}

	if mayExist {
		args = append(args, "--may-exist")
	}

	args = append(args, "add-br", bridgeName)

	_, err := shared.RunCommand("ovs-vsctl", args...)
	if err != nil {
		return err
	}

	return nil
}

// BridgeDelete deletes an OVS bridge.
func (o *OVS) BridgeDelete(bridgeName string) error {
	_, err := shared.RunCommand("ovs-vsctl", "del-br", bridgeName)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortAdd adds a port to the bridge (if already attached does nothing).
func (o *OVS) BridgePortAdd(bridgeName string, portName string, mayExist bool) error {
	args := []string{}

	if mayExist {
		args = append(args, "--may-exist")
	}

	args = append(args, "add-port", bridgeName, portName)

	_, err := shared.RunCommand("ovs-vsctl", args...)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortDelete deletes a port from the bridge (if already detached does nothing).
func (o *OVS) BridgePortDelete(bridgeName string, portName string) error {
	_, err := shared.RunCommand("ovs-vsctl", "--if-exists", "del-port", bridgeName, portName)
	if err != nil {
		return err
	}

	return nil
}

// BridgePortSet sets port options.
func (o *OVS) BridgePortSet(portName string, options ...string) error {
	_, err := shared.RunCommand("ovs-vsctl", append([]string{"set", "port", portName}, options...)...)
	if err != nil {
		return err
	}

	return nil
}

// InterfaceAssociateOVNSwitchPort removes any existing OVS ports associated to the specified ovnSwitchPortName
// and then associates the specified interfaceName to the OVN switch port.
func (o *OVS) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitchPortName OVNSwitchPort) error {
	// Clear existing ports that were formerly associated to ovnSwitchPortName.
	existingPorts, err := shared.RunCommand("ovs-vsctl", "--format=csv", "--no-headings", "--data=bare", "--colum=name", "find", "interface", fmt.Sprintf("external-ids:iface-id=%s", string(ovnSwitchPortName)))
	if err != nil {
		return err
	}

	existingPorts = strings.TrimSpace(existingPorts)
	if existingPorts != "" {
		for _, port := range strings.Split(existingPorts, "\n") {
			_, err = shared.RunCommand("ovs-vsctl", "del-port", port)
			if err != nil {
				return err
			}

			// Atempt to remove port, but don't fail if doesn't exist or can't be removed, at least
			// the OVS association has been successfully removed, so the new port being added next
			// won't fail to work properly.
			shared.RunCommand("ip", "link", "del", port)
		}
	}

	_, err = shared.RunCommand("ovs-vsctl", "set", "interface", interfaceName, fmt.Sprintf("external_ids:iface-id=%s", string(ovnSwitchPortName)))
	if err != nil {
		return err
	}

	return nil
}

// InterfaceAssociatedOVNSwitchPort returns the OVN switch port associated to the OVS interface.
func (o *OVS) InterfaceAssociatedOVNSwitchPort(interfaceName string) (OVNSwitchPort, error) {
	ovnSwitchPort, err := shared.RunCommand("ovs-vsctl", "get", "interface", interfaceName, "external_ids:iface-id")
	if err != nil {
		return "", err
	}

	return OVNSwitchPort(strings.TrimSpace(ovnSwitchPort)), nil
}

// ChassisID returns the local chassis ID.
func (o *OVS) ChassisID() (string, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	chassisID, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:system-id")
	if err != nil {
		return "", err
	}

	chassisID = strings.TrimSpace(chassisID)
	chassisID, err = strconv.Unquote(chassisID)
	if err != nil {
		return "", err
	}

	return chassisID, nil
}

// OVNEncapIP returns the enscapsulation IP used for OVN underlay tunnels.
func (o *OVS) OVNEncapIP() (net.IP, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	encapIPStr, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:ovn-encap-ip")
	if err != nil {
		return nil, err
	}

	encapIPStr = strings.TrimSpace(encapIPStr)
	encapIPStr, err = strconv.Unquote(encapIPStr)
	if err != nil {
		return nil, err
	}

	encapIP := net.ParseIP(encapIPStr)
	if encapIP == nil {
		return nil, fmt.Errorf("Invalid ovn-encap-ip address")
	}

	return encapIP, nil
}

// OVNBridgeMappings gets the current OVN bridge mappings.
func (o *OVS) OVNBridgeMappings(bridgeName string) ([]string, error) {
	// ovs-vsctl's get command doesn't support its --format flag, so we always get the output quoted.
	// However ovs-vsctl's find and list commands don't support retrieving a single column's map field.
	// And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types
	// in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values.
	mappings, err := shared.RunCommand("ovs-vsctl", "--if-exists", "get", "open_vswitch", ".", "external-ids:ovn-bridge-mappings")
	if err != nil {
		return nil, err
	}

	mappings = strings.TrimSpace(mappings)
	if mappings == "" {
		return []string{}, nil
	}

	mappings, err = strconv.Unquote(mappings)
	if err != nil {
		return nil, err
	}

	return strings.SplitN(mappings, ",", -1), nil
}

// OVNBridgeMappingAdd appends an OVN bridge mapping between an OVS bridge and the logical provider name.
func (o *OVS) OVNBridgeMappingAdd(bridgeName string, providerName string) error {
	ovnBridgeMappingMutex.Lock()
	defer ovnBridgeMappingMutex.Unlock()

	mappings, err := o.OVNBridgeMappings(bridgeName)
	if err != nil {
		return err
	}

	newMapping := fmt.Sprintf("%s:%s", providerName, bridgeName)
	for _, mapping := range mappings {
		if mapping == newMapping {
			return nil // Mapping is already present, nothing to do.
		}
	}

	mappings = append(mappings, newMapping)

	// Set new mapping string back into OVS database.
	_, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(mappings, ",")))
	if err != nil {
		return err
	}

	return nil
}

// OVNBridgeMappingDelete deletes an OVN bridge mapping between an OVS bridge and the logical provider name.
func (o *OVS) OVNBridgeMappingDelete(bridgeName string, providerName string) error {
	ovnBridgeMappingMutex.Lock()
	defer ovnBridgeMappingMutex.Unlock()

	mappings, err := o.OVNBridgeMappings(bridgeName)
	if err != nil {
		return err
	}

	changed := false
	newMappings := make([]string, 0, len(mappings))
	matchMapping := fmt.Sprintf("%s:%s", providerName, bridgeName)
	for _, mapping := range mappings {
		if mapping != matchMapping {
			newMappings = append(newMappings, mapping)
		} else {
			changed = true
		}
	}

	if changed {
		if len(newMappings) < 1 {
			// Remove mapping key in OVS database.
			_, err = shared.RunCommand("ovs-vsctl", "remove", "open_vswitch", ".", "external-ids", "ovn-bridge-mappings")
			if err != nil {
				return err
			}
		} else {
			// Set updated mapping string back into OVS database.
			_, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(newMappings, ",")))
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// BridgePortList returns a list of ports that are connected to the bridge.
func (o *OVS) BridgePortList(bridgeName string) ([]string, error) {
	// Clear existing ports that were formerly associated to ovnSwitchPortName.
	portString, err := shared.RunCommand("ovs-vsctl", "list-ports", bridgeName)
	if err != nil {
		return nil, err
	}

	ports := []string{}

	portString = strings.TrimSpace(portString)
	if portString != "" {
		for _, port := range strings.Split(portString, "\n") {
			ports = append(ports, strings.TrimSpace(port))
		}
	}

	return ports, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

// PlackPlugin mackerel plugin for Plack
type PlackPlugin struct {
	URI         string
	Prefix      string
	LabelPrefix string
}

// {
//   "Uptime": "1410520211",
//   "TotalAccesses": "2",
//   "IdleWorkers": "2",
//   "TotalKbytes": "0",
//   "BusyWorkers": "1",
//   "stats": [
//     {
//       "pid": 11062,
//       "method": "GET",
//       "ss": 51,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "status": "_",
//       "uri": "/server-status?json"
//     },
//     {
//       "ss": 41,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "pid": 11063,
//       "method": "GET",
//       "status": "_",
//       "uri": "/server-status?json"
//     },
//     {
//       "ss": 0,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "pid": 11064,
//       "method": "GET",
//       "status": "A",
//       "uri": "/server-status?json"
//     }
//   ]
// }

// field types vary between versions

// PlackRequest request
type PlackRequest struct{}

// PlackServerStatus sturct for server-status's json
type PlackServerStatus struct {
	// Uptime        string         `json:"Uptime"`
	TotalAccesses string         `json:"TotalAccesses"`
	TotalKbytes   string         `json:"TotalKbytes"`
	BusyWorkers   string         `json:"BusyWorkers"`
	IdleWorkers   string         `json:"IdleWorkers"`
	Stats         []PlackRequest `json:"stats"`
}

// FetchMetrics interface for mackerelplugin
func (p PlackPlugin) FetchMetrics() (map[string]interface{}, error) {
	resp, err := http.Get(p.URI)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return p.parseStats(resp.Body)
}

func (p PlackPlugin) parseStats(body io.Reader) (map[string]interface{}, error) {
	stat := make(map[string]interface{})
	decoder := json.NewDecoder(body)

	var s PlackServerStatus
	err := decoder.Decode(&s)
	if err != nil {
		return nil, err
	}

	stat["busy_workers"], err = strconv.ParseFloat(s.BusyWorkers, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["idle_workers"], err = strconv.ParseFloat(s.IdleWorkers, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["requests"], err = strconv.ParseUint(s.TotalAccesses, 10, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["bytes_sent"], err = strconv.ParseUint(s.TotalKbytes, 10, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}
	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (p PlackPlugin) GraphDefinition() map[string](mp.Graphs) {
	var graphdef = map[string](mp.Graphs){
		(p.Prefix + ".workers"): mp.Graphs{
			Label: p.LabelPrefix + " Workers",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "busy_workers", Label: "Busy Workers", Diff: false, Stacked: true},
				mp.Metrics{Name: "idle_workers", Label: "Idle Workers", Diff: false, Stacked: true},
			},
		},
		(p.Prefix + ".req"): mp.Graphs{
			Label: p.LabelPrefix + " Requests",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "requests", Label: "Requests", Diff: true, Type: "uint64"},
			},
		},
		(p.Prefix + ".bytes"): mp.Graphs{
			Label: p.LabelPrefix + " Bytes",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "bytes_sent", Label: "Bytes Sent", Diff: true, Type: "uint64"},
			},
		},
	}

	return graphdef
}

func main() {
	optURI := flag.String("uri", "", "URI")
	optScheme := flag.String("scheme", "http", "Scheme")
	optHost := flag.String("host", "localhost", "Hostname")
	optPort := flag.String("port", "5000", "Port")
	optPath := flag.String("path", "/server-status?json", "Path")
	optPrefix := flag.String("metric-key-prefix", "plack", "Prefix")
	optLabelPrefix := flag.String("metric-label-prefix", "", "Label Prefix")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	plack := PlackPlugin{URI: *optURI, Prefix: *optPrefix, LabelPrefix: *optLabelPrefix}
	if plack.URI == "" {
		plack.URI = fmt.Sprintf("%s://%s:%s%s", *optScheme, *optHost, *optPort, *optPath)
	}
	if plack.LabelPrefix == "" {
		plack.LabelPrefix = strings.Title(plack.Prefix)
	}

	helper := mp.NewMackerelPlugin(plack)
	if *optTempfile != "" {
		helper.Tempfile = *optTempfile
	} else {
		helper.Tempfile = fmt.Sprintf("/tmp/mackerel-plugin-plack")
	}

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<commit_msg>change to interface{} and add comment<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

// PlackPlugin mackerel plugin for Plack
type PlackPlugin struct {
	URI         string
	Prefix      string
	LabelPrefix string
}

// {
//   "Uptime": "1410520211",
//   "TotalAccesses": "2",
//   "IdleWorkers": "2",
//   "TotalKbytes": "0",
//   "BusyWorkers": "1",
//   "stats": [
//     {
//       "pid": 11062,
//       "method": "GET",
//       "ss": 51,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "status": "_",
//       "uri": "/server-status?json"
//     },
//     {
//       "ss": 41,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "pid": 11063,
//       "method": "GET",
//       "status": "_",
//       "uri": "/server-status?json"
//     },
//     {
//       "ss": 0,
//       "remote_addr": "127.0.0.1",
//       "host": "localhost:8000",
//       "protocol": "HTTP/1.1",
//       "pid": 11064,
//       "method": "GET",
//       "status": "A",
//       "uri": "/server-status?json"
//     }
//   ]
// }

// field types vary between versions

// PlackRequest request
type PlackRequest struct{}

// PlackServerStatus sturct for server-status's json
type PlackServerStatus struct {
	Uptime        interface{}    `json:"Uptime"` // Plack::Middleware::ServerStatus::Lite 0.35 outputs Uptime as a JSON number, though pre-0.35 outputs it as a JSON string.
	TotalAccesses string         `json:"TotalAccesses"`
	TotalKbytes   string         `json:"TotalKbytes"`
	BusyWorkers   string         `json:"BusyWorkers"`
	IdleWorkers   string         `json:"IdleWorkers"`
	Stats         []PlackRequest `json:"stats"`
}

// FetchMetrics interface for mackerelplugin
func (p PlackPlugin) FetchMetrics() (map[string]interface{}, error) {
	resp, err := http.Get(p.URI)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return p.parseStats(resp.Body)
}

func (p PlackPlugin) parseStats(body io.Reader) (map[string]interface{}, error) {
	stat := make(map[string]interface{})
	decoder := json.NewDecoder(body)

	var s PlackServerStatus
	err := decoder.Decode(&s)
	if err != nil {
		return nil, err
	}

	stat["busy_workers"], err = strconv.ParseFloat(s.BusyWorkers, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["idle_workers"], err = strconv.ParseFloat(s.IdleWorkers, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["requests"], err = strconv.ParseUint(s.TotalAccesses, 10, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}

	stat["bytes_sent"], err = strconv.ParseUint(s.TotalKbytes, 10, 64)
	if err != nil {
		return nil, errors.New("cannot get values")
	}
	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (p PlackPlugin) GraphDefinition() map[string](mp.Graphs) {
	var graphdef = map[string](mp.Graphs){
		(p.Prefix + ".workers"): mp.Graphs{
			Label: p.LabelPrefix + " Workers",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "busy_workers", Label: "Busy Workers", Diff: false, Stacked: true},
				mp.Metrics{Name: "idle_workers", Label: "Idle Workers", Diff: false, Stacked: true},
			},
		},
		(p.Prefix + ".req"): mp.Graphs{
			Label: p.LabelPrefix + " Requests",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "requests", Label: "Requests", Diff: true, Type: "uint64"},
			},
		},
		(p.Prefix + ".bytes"): mp.Graphs{
			Label: p.LabelPrefix + " Bytes",
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "bytes_sent", Label: "Bytes Sent", Diff: true, Type: "uint64"},
			},
		},
	}

	return graphdef
}

func main() {
	optURI := flag.String("uri", "", "URI")
	optScheme := flag.String("scheme", "http", "Scheme")
	optHost := flag.String("host", "localhost", "Hostname")
	optPort := flag.String("port", "5000", "Port")
	optPath := flag.String("path", "/server-status?json", "Path")
	optPrefix := flag.String("metric-key-prefix", "plack", "Prefix")
	optLabelPrefix := flag.String("metric-label-prefix", "", "Label Prefix")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	plack := PlackPlugin{URI: *optURI, Prefix: *optPrefix, LabelPrefix: *optLabelPrefix}
	if plack.URI == "" {
		plack.URI = fmt.Sprintf("%s://%s:%s%s", *optScheme, *optHost, *optPort, *optPath)
	}
	if plack.LabelPrefix == "" {
		plack.LabelPrefix = strings.Title(plack.Prefix)
	}

	helper := mp.NewMackerelPlugin(plack)
	if *optTempfile != "" {
		helper.Tempfile = *optTempfile
	} else {
		helper.Tempfile = fmt.Sprintf("/tmp/mackerel-plugin-plack")
	}

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 usb

import (
	"bytes"
	"log"
	"os"
	"testing"
)

func TestListDevices(t *testing.T) {
	orig := libusb
	defer func() { libusb = orig }()
	libusb = newFakeLibusb()

	c := NewContext()
	defer c.Close()
	c.Debug(0)

	descs := []*Descriptor{}
	devs, err := c.ListDevices(func(desc *Descriptor) bool {
		descs = append(descs, desc)
		return true
	})
	defer func() {
		for _, d := range devs {
			d.Close()
		}
	}()
	if err != nil {
		t.Fatalf("ListDevices(): %s", err)
	}

	if got, want := len(devs), len(fakeDevices); got != want {
		t.Fatalf("len(devs) = %d, want %d (based on num fake devs)", got, want)
	}
	if got, want := len(devs), len(descs); got != want {
		t.Fatalf("len(devs) = %d, want %d (based on num opened devices)", got, want)
	}

	for i := range devs {
		if got, want := devs[i].Descriptor, descs[i]; got != want {
			t.Errorf("dev[%d].Descriptor = %p, want %p", i, got, want)
		}
	}
}
<commit_msg>remove superfluous imports<commit_after>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 usb

import "testing"

func TestListDevices(t *testing.T) {
	orig := libusb
	defer func() { libusb = orig }()
	libusb = newFakeLibusb()

	c := NewContext()
	defer c.Close()
	c.Debug(0)

	descs := []*Descriptor{}
	devs, err := c.ListDevices(func(desc *Descriptor) bool {
		descs = append(descs, desc)
		return true
	})
	defer func() {
		for _, d := range devs {
			d.Close()
		}
	}()
	if err != nil {
		t.Fatalf("ListDevices(): %s", err)
	}

	if got, want := len(devs), len(fakeDevices); got != want {
		t.Fatalf("len(devs) = %d, want %d (based on num fake devs)", got, want)
	}
	if got, want := len(devs), len(descs); got != want {
		t.Fatalf("len(devs) = %d, want %d (based on num opened devices)", got, want)
	}

	for i := range devs {
		if got, want := devs[i].Descriptor, descs[i]; got != want {
			t.Errorf("dev[%d].Descriptor = %p, want %p", i, got, want)
		}
	}
}
<|endoftext|>


<commit_before>package dex

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"net/url"
	"path"
	"strconv"
	"strings"

	log "github.com/sirupsen/logrus"

	"github.com/argoproj/argo-cd/v2/util/errors"
)

func decorateDirector(director func(req *http.Request), target *url.URL) func(req *http.Request) {
	return func(req *http.Request) {
		director(req)
		req.Host = target.Host
	}
}

type DexTLSConfig struct {
	DisableTLS       bool
	StrictValidation bool
	RootCAs          *x509.CertPool
	Certificate      []byte
}

func TLSConfig(tlsConfig *DexTLSConfig) *tls.Config {
	if tlsConfig == nil || tlsConfig.DisableTLS {
		return nil
	}
	if !tlsConfig.StrictValidation {
		return &tls.Config{
			InsecureSkipVerify: true,
		}
	}
	return &tls.Config{
		InsecureSkipVerify: false,
		RootCAs:            tlsConfig.RootCAs,
		VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
			if !bytes.Equal(rawCerts[0], tlsConfig.Certificate) {
				return fmt.Errorf("dex server certificate does not match")
			}
			return nil
		},
	}
}

// NewDexHTTPReverseProxy returns a reverse proxy to the Dex server. Dex is assumed to be configured
// with the external issuer URL muxed to the same path configured in server.go. In other words, if
// Argo CD API server wants to proxy requests at /api/dex, then the dex config yaml issuer URL should
// also be /api/dex (e.g. issuer: https://argocd.example.com/api/dex)
func NewDexHTTPReverseProxy(serverAddr string, baseHRef string, tlsConfig *DexTLSConfig) func(writer http.ResponseWriter, request *http.Request) {

	fullAddr := DexServerAddressWithProtocol(serverAddr, tlsConfig)

	target, err := url.Parse(fullAddr)
	errors.CheckError(err)
	target.Path = baseHRef

	proxy := httputil.NewSingleHostReverseProxy(target)

	if tlsConfig != nil && !tlsConfig.DisableTLS {
		proxy.Transport = &http.Transport{
			TLSClientConfig: TLSConfig(tlsConfig),
		}
	}

	proxy.ModifyResponse = func(resp *http.Response) error {
		if resp.StatusCode == 500 {
			b, err := io.ReadAll(resp.Body)
			if err != nil {
				return err
			}
			err = resp.Body.Close()
			if err != nil {
				return err
			}
			log.Errorf("received error from dex: %s", string(b))
			resp.ContentLength = 0
			resp.Header.Set("Content-Length", strconv.Itoa(0))
			resp.Header.Set("Location", fmt.Sprintf("%s?has_sso_error=true", path.Join(baseHRef, "login")))
			resp.StatusCode = http.StatusSeeOther
			resp.Body = io.NopCloser(bytes.NewReader(make([]byte, 0)))
			return nil
		}
		return nil
	}
	proxy.Director = decorateDirector(proxy.Director, target)
	return func(w http.ResponseWriter, r *http.Request) {
		proxy.ServeHTTP(w, r)
	}
}

// NewDexRewriteURLRoundTripper creates a new DexRewriteURLRoundTripper
func NewDexRewriteURLRoundTripper(dexServerAddr string, T http.RoundTripper) DexRewriteURLRoundTripper {
	dexURL, _ := url.Parse(dexServerAddr)
	return DexRewriteURLRoundTripper{
		DexURL: dexURL,
		T:      T,
	}
}

// DexRewriteURLRoundTripper is an HTTP RoundTripper to rewrite HTTP requests to the specified
// dex server address. This is used when reverse proxying Dex to avoid the API server from
// unnecessarily communicating to Argo CD through its externally facing load balancer, which is not
// always permitted in firewalled/air-gapped networks.
type DexRewriteURLRoundTripper struct {
	DexURL *url.URL
	T      http.RoundTripper
}

func (s DexRewriteURLRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	r.URL.Host = s.DexURL.Host
	r.URL.Scheme = s.DexURL.Scheme
	return s.T.RoundTrip(r)
}

func DexServerAddressWithProtocol(orig string, tlsConfig *DexTLSConfig) string {
	if strings.Contains(orig, "://") {
		return orig
	} else {
		if tlsConfig == nil || tlsConfig.DisableTLS {
			return "http://" + orig
		} else {
			return "https://" + orig
		}
	}
}
<commit_msg>chore: Add security logging for Dex errors (#10455)<commit_after>package dex

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"net/url"
	"path"
	"strconv"
	"strings"

	log "github.com/sirupsen/logrus"

	"github.com/argoproj/argo-cd/v2/common"
	"github.com/argoproj/argo-cd/v2/util/errors"
)

func decorateDirector(director func(req *http.Request), target *url.URL) func(req *http.Request) {
	return func(req *http.Request) {
		director(req)
		req.Host = target.Host
	}
}

type DexTLSConfig struct {
	DisableTLS       bool
	StrictValidation bool
	RootCAs          *x509.CertPool
	Certificate      []byte
}

func TLSConfig(tlsConfig *DexTLSConfig) *tls.Config {
	if tlsConfig == nil || tlsConfig.DisableTLS {
		return nil
	}
	if !tlsConfig.StrictValidation {
		return &tls.Config{
			InsecureSkipVerify: true,
		}
	}
	return &tls.Config{
		InsecureSkipVerify: false,
		RootCAs:            tlsConfig.RootCAs,
		VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
			if !bytes.Equal(rawCerts[0], tlsConfig.Certificate) {
				return fmt.Errorf("dex server certificate does not match")
			}
			return nil
		},
	}
}

// NewDexHTTPReverseProxy returns a reverse proxy to the Dex server. Dex is assumed to be configured
// with the external issuer URL muxed to the same path configured in server.go. In other words, if
// Argo CD API server wants to proxy requests at /api/dex, then the dex config yaml issuer URL should
// also be /api/dex (e.g. issuer: https://argocd.example.com/api/dex)
func NewDexHTTPReverseProxy(serverAddr string, baseHRef string, tlsConfig *DexTLSConfig) func(writer http.ResponseWriter, request *http.Request) {

	fullAddr := DexServerAddressWithProtocol(serverAddr, tlsConfig)

	target, err := url.Parse(fullAddr)
	errors.CheckError(err)
	target.Path = baseHRef

	proxy := httputil.NewSingleHostReverseProxy(target)

	if tlsConfig != nil && !tlsConfig.DisableTLS {
		proxy.Transport = &http.Transport{
			TLSClientConfig: TLSConfig(tlsConfig),
		}
	}

	proxy.ModifyResponse = func(resp *http.Response) error {
		if resp.StatusCode == 500 {
			b, err := io.ReadAll(resp.Body)
			if err != nil {
				return err
			}
			err = resp.Body.Close()
			if err != nil {
				return err
			}
			log.WithFields(log.Fields{
				common.SecurityField: common.SecurityMedium,
			}).Errorf("received error from dex: %s", string(b))
			resp.ContentLength = 0
			resp.Header.Set("Content-Length", strconv.Itoa(0))
			resp.Header.Set("Location", fmt.Sprintf("%s?has_sso_error=true", path.Join(baseHRef, "login")))
			resp.StatusCode = http.StatusSeeOther
			resp.Body = io.NopCloser(bytes.NewReader(make([]byte, 0)))
			return nil
		}
		return nil
	}
	proxy.Director = decorateDirector(proxy.Director, target)
	return func(w http.ResponseWriter, r *http.Request) {
		proxy.ServeHTTP(w, r)
	}
}

// NewDexRewriteURLRoundTripper creates a new DexRewriteURLRoundTripper
func NewDexRewriteURLRoundTripper(dexServerAddr string, T http.RoundTripper) DexRewriteURLRoundTripper {
	dexURL, _ := url.Parse(dexServerAddr)
	return DexRewriteURLRoundTripper{
		DexURL: dexURL,
		T:      T,
	}
}

// DexRewriteURLRoundTripper is an HTTP RoundTripper to rewrite HTTP requests to the specified
// dex server address. This is used when reverse proxying Dex to avoid the API server from
// unnecessarily communicating to Argo CD through its externally facing load balancer, which is not
// always permitted in firewalled/air-gapped networks.
type DexRewriteURLRoundTripper struct {
	DexURL *url.URL
	T      http.RoundTripper
}

func (s DexRewriteURLRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	r.URL.Host = s.DexURL.Host
	r.URL.Scheme = s.DexURL.Scheme
	return s.T.RoundTrip(r)
}

func DexServerAddressWithProtocol(orig string, tlsConfig *DexTLSConfig) string {
	if strings.Contains(orig, "://") {
		return orig
	} else {
		if tlsConfig == nil || tlsConfig.DisableTLS {
			return "http://" + orig
		} else {
			return "https://" + orig
		}
	}
}
<|endoftext|>


<commit_before>// Package dns ...
package dns

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

type DomainName struct {
	IP     string
	Domain string
}

var (
	hostsFile = detectHostsFile()
	newline   = detectNewlineChar()
)

// Entry generate the DNS entry to be added
func Entry(ip, name, env string) string {
	return fmt.Sprintf("%s     %s # dns added for '%s' by nanobox", ip, name, env)
}

// Exists ...
func Exists(entry string) bool {

	// open the hosts file for scanning...
	f, err := os.Open(hostsFile)
	if err != nil {
		return false
	}
	defer f.Close()

	// scan each line of the hosts file to see if there is a match for this
	// entry
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if scanner.Text() == entry {
			return true
		}
	}

	return false
}

func List(filter string) []DomainName {

	// open the hosts file
	f, err := os.Open(hostsFile)
	if err != nil {
		return nil
	}
	defer f.Close()

	entries := []DomainName{}

	// scan each line of the hosts file to see if there is a match for this
	// entry
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), filter) {
			fields := strings.Fields(scanner.Text())
			if len(fields) >= 2 {
				entries = append(entries, DomainName{IP: fields[0], Domain: fields[1]})
			}
		}
	}

	return entries
}

// Add ...
func Add(entry string) error {
	if entry == "" {
		return nil
	}

	// open hosts file
	f, err := os.OpenFile(hostsFile, os.O_RDWR|os.O_APPEND, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	// write the DNS entry to the file
	if _, err := f.WriteString(fmt.Sprintf("%s%s", entry, newline)); err != nil {
		return err
	}

	return nil
}

// Remove ...
func Remove(entry string) error {
	if entry == "" {
		return nil
	}

	// "contents" will end up storing the entire contents of the file excluding the
	// entry that is trying to be removed
	var contents string

	// open hosts file
	f, err := os.OpenFile(hostsFile, os.O_RDWR, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	// remove entry from /etc/hosts
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {

		// if the line contain the entry skip it
		// make it do a loose string check
		// if its exactly the entry then remove it.
		// if it contains the same environment
		// also remove it
		if strings.Contains(scanner.Text(), entry) {
			continue
		}

		// add each line back into the file
		contents += fmt.Sprintf("%s%s", scanner.Text(), newline)
	}

	// trim the contents to avoid any extra newlines
	contents = strings.TrimSpace(contents)

	// add a single newline for completeness
	contents += newline

	// write back the contents of the hosts file minus the removed entry
	if err := ioutil.WriteFile(hostsFile, []byte(contents), 0644); err != nil {
		return err
	}

	return nil
}

// RemoveAll removes all dns entries added by nanobox
func RemoveAll() error {

	// short-circuit if no entries were added by nanobox
	if len(List("by nanobox")) == 0 {
		return nil
	}

	return Remove("by nanobox")
}
<commit_msg>add in a check when adding a dns to ensure no duplicates fixes #288<commit_after>// Package dns ...
package dns

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

type DomainName struct {
	IP     string
	Domain string
}

var (
	hostsFile = detectHostsFile()
	newline   = detectNewlineChar()
)

// Entry generate the DNS entry to be added
func Entry(ip, name, env string) string {
	return fmt.Sprintf("%s     %s # dns added for '%s' by nanobox", ip, name, env)
}

// Exists ...
func Exists(entry string) bool {

	// open the hosts file for scanning...
	f, err := os.Open(hostsFile)
	if err != nil {
		return false
	}
	defer f.Close()

	// scan each line of the hosts file to see if there is a match for this
	// entry
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if scanner.Text() == entry {
			return true
		}
	}

	return false
}

func List(filter string) []DomainName {

	// open the hosts file
	f, err := os.Open(hostsFile)
	if err != nil {
		return nil
	}
	defer f.Close()

	entries := []DomainName{}

	// scan each line of the hosts file to see if there is a match for this
	// entry
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), filter) {
			fields := strings.Fields(scanner.Text())
			if len(fields) >= 2 {
				entries = append(entries, DomainName{IP: fields[0], Domain: fields[1]})
			}
		}
	}

	return entries
}

// Add ...
func Add(entry string) error {
	// break early if there is no entry
	// or we have already added this entry
	if entry == "" || Exists(entry) {
		return nil
	}

	// open hosts file
	f, err := os.OpenFile(hostsFile, os.O_RDWR|os.O_APPEND, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	// write the DNS entry to the file
	if _, err := f.WriteString(fmt.Sprintf("%s%s", entry, newline)); err != nil {
		return err
	}

	return nil
}

// Remove ...
func Remove(entry string) error {
	if entry == "" {
		return nil
	}

	// "contents" will end up storing the entire contents of the file excluding the
	// entry that is trying to be removed
	var contents string

	// open hosts file
	f, err := os.OpenFile(hostsFile, os.O_RDWR, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	// remove entry from /etc/hosts
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {

		// if the line contain the entry skip it
		// make it do a loose string check
		// if its exactly the entry then remove it.
		// if it contains the same environment
		// also remove it
		if strings.Contains(scanner.Text(), entry) {
			continue
		}

		// add each line back into the file
		contents += fmt.Sprintf("%s%s", scanner.Text(), newline)
	}

	// trim the contents to avoid any extra newlines
	contents = strings.TrimSpace(contents)

	// add a single newline for completeness
	contents += newline

	// write back the contents of the hosts file minus the removed entry
	if err := ioutil.WriteFile(hostsFile, []byte(contents), 0644); err != nil {
		return err
	}

	return nil
}

// RemoveAll removes all dns entries added by nanobox
func RemoveAll() error {

	// short-circuit if no entries were added by nanobox
	if len(List("by nanobox")) == 0 {
		return nil
	}

	return Remove("by nanobox")
}
<|endoftext|>