<commit_before>package validator

import (
	"reflect"
	"strconv"
	"strings"
)

const (
	namespaceSeparator = "."
	leftBracket        = "["
	rightBracket       = "]"
)

func (v *Validate) extractType(current reflect.Value) (reflect.Value, reflect.Kind) {

	switch current.Kind() {
	case reflect.Ptr:

		if current.IsNil() {
			return current, reflect.Ptr
		}

		return v.extractType(current.Elem())

	case reflect.Interface:

		if current.IsNil() {
			return current, reflect.Interface
		}

		return v.extractType(current.Elem())

	case reflect.Invalid:

		return current, reflect.Invalid

	default:

		if v.config.hasCustomFuncs {
			if fn, ok := v.config.CustomTypeFuncs[current.Type()]; ok {
				return v.extractType(reflect.ValueOf(fn(current)))
			}
		}

		return current, current.Kind()
	}
}

func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {

	current, kind := v.extractType(current)

	// fmt.Println("SOK:", current, kind, namespace)

	// if len(namespace) == 0 {
	// 	// if kind == reflect.Invalid {
	// 	// 	return current, kind, false
	// 	// }
	// 	return current, kind, true
	// }

	if kind == reflect.Invalid {
		return current, kind, false
	}

	if len(namespace) == 0 {
		return current, kind, true
	}

	switch kind {
	// case reflect.Invalid:
	// 	return current, kind, false

	case reflect.Ptr, reflect.Interface:

		return current, kind, false

	case reflect.Struct:

		typ := current.Type()
		fld := namespace
		ns := namespace

		if typ != timeType && typ != timePtrType {

			idx := strings.Index(namespace, namespaceSeparator)

			if idx != -1 {
				fld = namespace[:idx]
				ns = namespace[idx+1:]
			} else {
				ns = ""
				idx = len(namespace)
			}

			// ns := namespace[idx+1:]

			bracketIdx := strings.Index(fld, leftBracket)
			if bracketIdx != -1 {
				fld = fld[:bracketIdx]

				ns = namespace[bracketIdx:]
				// if idx == -1 {
				// 	ns = namespace[bracketIdx:]
				// } else {
				// 	ns = namespace[bracketIdx:]
				// }
			}

			current = current.FieldByName(fld)

			// if current.Kind() == reflect.Invalid {
			// 	return current, reflect.Invalid, false
			// }

			// fmt.Println("NS:", ns, idx)

			return v.getStructFieldOK(current, ns)
		}

	case reflect.Array, reflect.Slice:
		idx := strings.Index(namespace, leftBracket)
		idx2 := strings.Index(namespace, rightBracket)

		arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])

		if arrIdx >= current.Len() {
			return current, kind, false
		}

		startIdx := idx2 + 1

		if startIdx < len(namespace) {
			if namespace[startIdx:startIdx+1] == namespaceSeparator {
				startIdx++
			}
		}

		return v.getStructFieldOK(current.Index(arrIdx), namespace[startIdx:])

	case reflect.Map:
		idx := strings.Index(namespace, leftBracket) + 1
		idx2 := strings.Index(namespace, rightBracket)

		endIdx := idx2

		if endIdx+1 < len(namespace) {
			if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
				endIdx++
			}
		}

		key := namespace[idx:idx2]

		switch current.Type().Key().Kind() {
		case reflect.Int:
			i, _ := strconv.Atoi(key)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Int8:
			i, _ := strconv.ParseInt(key, 10, 8)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:])
		case reflect.Int16:
			i, _ := strconv.ParseInt(key, 10, 16)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:])
		case reflect.Int32:
			i, _ := strconv.ParseInt(key, 10, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:])
		case reflect.Int64:
			i, _ := strconv.ParseInt(key, 10, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Uint:
			i, _ := strconv.ParseUint(key, 10, 0)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:])
		case reflect.Uint8:
			i, _ := strconv.ParseUint(key, 10, 8)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:])
		case reflect.Uint16:
			i, _ := strconv.ParseUint(key, 10, 16)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:])
		case reflect.Uint32:
			i, _ := strconv.ParseUint(key, 10, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:])
		case reflect.Uint64:
			i, _ := strconv.ParseUint(key, 10, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Float32:
			f, _ := strconv.ParseFloat(key, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:])
		case reflect.Float64:
			f, _ := strconv.ParseFloat(key, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:])
		case reflect.Bool:
			b, _ := strconv.ParseBool(key)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:])

		// reflect.Type = string
		default:
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:])
		}
		// v.Type().Key().Kind()

		// return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:])
	}

	// if got here there was more namespace, cannot go any deeper
	panic("Invalid field namespace")
	// return current, kind, false
}

// asInt retuns the parameter as a int64
// or panics if it can't convert
func asInt(param string) int64 {

	i, err := strconv.ParseInt(param, 0, 64)
	panicIf(err)

	return i
}

// asUint returns the parameter as a uint64
// or panics if it can't convert
func asUint(param string) uint64 {

	i, err := strconv.ParseUint(param, 0, 64)
	panicIf(err)

	return i
}

// asFloat returns the parameter as a float64
// or panics if it can't convert
func asFloat(param string) float64 {

	i, err := strconv.ParseFloat(param, 64)
	panicIf(err)

	return i
}

func panicIf(err error) {
	if err != nil {
		panic(err.Error())
	}
}
<commit_msg>code cleanup<commit_after>package validator

import (
	"reflect"
	"strconv"
	"strings"
)

const (
	namespaceSeparator = "."
	leftBracket        = "["
	rightBracket       = "]"
)

func (v *Validate) extractType(current reflect.Value) (reflect.Value, reflect.Kind) {

	switch current.Kind() {
	case reflect.Ptr:

		if current.IsNil() {
			return current, reflect.Ptr
		}

		return v.extractType(current.Elem())

	case reflect.Interface:

		if current.IsNil() {
			return current, reflect.Interface
		}

		return v.extractType(current.Elem())

	case reflect.Invalid:

		return current, reflect.Invalid

	default:

		if v.config.hasCustomFuncs {
			if fn, ok := v.config.CustomTypeFuncs[current.Type()]; ok {
				return v.extractType(reflect.ValueOf(fn(current)))
			}
		}

		return current, current.Kind()
	}
}

func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {

	current, kind := v.extractType(current)

	if kind == reflect.Invalid {
		return current, kind, false
	}

	if len(namespace) == 0 {
		return current, kind, true
	}

	switch kind {

	case reflect.Ptr, reflect.Interface:

		return current, kind, false

	case reflect.Struct:

		typ := current.Type()
		fld := namespace
		ns := namespace

		if typ != timeType && typ != timePtrType {

			idx := strings.Index(namespace, namespaceSeparator)

			if idx != -1 {
				fld = namespace[:idx]
				ns = namespace[idx+1:]
			} else {
				ns = ""
				idx = len(namespace)
			}

			bracketIdx := strings.Index(fld, leftBracket)
			if bracketIdx != -1 {
				fld = fld[:bracketIdx]

				ns = namespace[bracketIdx:]
			}

			current = current.FieldByName(fld)

			return v.getStructFieldOK(current, ns)
		}

	case reflect.Array, reflect.Slice:
		idx := strings.Index(namespace, leftBracket)
		idx2 := strings.Index(namespace, rightBracket)

		arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])

		if arrIdx >= current.Len() {
			return current, kind, false
		}

		startIdx := idx2 + 1

		if startIdx < len(namespace) {
			if namespace[startIdx:startIdx+1] == namespaceSeparator {
				startIdx++
			}
		}

		return v.getStructFieldOK(current.Index(arrIdx), namespace[startIdx:])

	case reflect.Map:
		idx := strings.Index(namespace, leftBracket) + 1
		idx2 := strings.Index(namespace, rightBracket)

		endIdx := idx2

		if endIdx+1 < len(namespace) {
			if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
				endIdx++
			}
		}

		key := namespace[idx:idx2]

		switch current.Type().Key().Kind() {
		case reflect.Int:
			i, _ := strconv.Atoi(key)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Int8:
			i, _ := strconv.ParseInt(key, 10, 8)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:])
		case reflect.Int16:
			i, _ := strconv.ParseInt(key, 10, 16)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:])
		case reflect.Int32:
			i, _ := strconv.ParseInt(key, 10, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:])
		case reflect.Int64:
			i, _ := strconv.ParseInt(key, 10, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Uint:
			i, _ := strconv.ParseUint(key, 10, 0)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:])
		case reflect.Uint8:
			i, _ := strconv.ParseUint(key, 10, 8)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:])
		case reflect.Uint16:
			i, _ := strconv.ParseUint(key, 10, 16)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:])
		case reflect.Uint32:
			i, _ := strconv.ParseUint(key, 10, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:])
		case reflect.Uint64:
			i, _ := strconv.ParseUint(key, 10, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
		case reflect.Float32:
			f, _ := strconv.ParseFloat(key, 32)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:])
		case reflect.Float64:
			f, _ := strconv.ParseFloat(key, 64)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:])
		case reflect.Bool:
			b, _ := strconv.ParseBool(key)
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:])

		// reflect.Type = string
		default:
			return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:])
		}
	}

	// if got here there was more namespace, cannot go any deeper
	panic("Invalid field namespace")
}

// asInt retuns the parameter as a int64
// or panics if it can't convert
func asInt(param string) int64 {

	i, err := strconv.ParseInt(param, 0, 64)
	panicIf(err)

	return i
}

// asUint returns the parameter as a uint64
// or panics if it can't convert
func asUint(param string) uint64 {

	i, err := strconv.ParseUint(param, 0, 64)
	panicIf(err)

	return i
}

// asFloat returns the parameter as a float64
// or panics if it can't convert
func asFloat(param string) float64 {

	i, err := strconv.ParseFloat(param, 64)
	panicIf(err)

	return i
}

func panicIf(err error) {
	if err != nil {
		panic(err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package circonusgometrics

import (
	"github.com/circonus-labs/circonusllhist"
)

// Reset removes all existing counters and gauges.
func (m *CirconusMetrics) Reset() {
	m.cm.Lock()
	defer m.cm.Unlock()

	m.cfm.Lock()
	defer m.cfm.Unlock()

	m.gm.Lock()
	defer m.gm.Unlock()

	m.gfm.Lock()
	defer m.gfm.Unlock()

	m.hm.Lock()
	defer m.hm.Unlock()

	m.tm.Lock()
	defer m.tm.Unlock()

	m.tfm.Lock()
	defer m.tfm.Unlock()

	m.counters = make(map[string]uint64)
	m.counterFuncs = make(map[string]func() uint64)
	m.gauges = make(map[string]string)
	m.gaugeFuncs = make(map[string]func() int64)
	m.histograms = make(map[string]*Histogram)
	m.text = make(map[string]string)
	m.textFuncs = make(map[string]func() string)
}

// snapshot returns a copy of the values of all registered counters and gauges.
func (m *CirconusMetrics) snapshot() (c map[string]uint64, g map[string]string, h map[string]*circonusllhist.Histogram, t map[string]string) {
	m.cm.Lock()
	defer m.cm.Unlock()

	m.cfm.Lock()
	defer m.cfm.Unlock()

	m.gm.Lock()
	defer m.gm.Unlock()

	m.gfm.Lock()
	defer m.gfm.Unlock()

	m.hm.Lock()
	defer m.hm.Unlock()

	m.tm.Lock()
	defer m.tm.Unlock()

	m.tfm.Lock()
	defer m.tfm.Unlock()

	c = make(map[string]uint64, len(m.counters)+len(m.counterFuncs))
	for n, v := range m.counters {
		c[n] = v
	}

	for n, f := range m.counterFuncs {
		c[n] = f()
	}

	//g = make(map[string]int64, len(m.gauges)+len(m.gaugeFuncs))
	g = make(map[string]string, len(m.gauges)+len(m.gaugeFuncs))
	for n, v := range m.gauges {
		g[n] = v
	}

	for n, f := range m.gaugeFuncs {
		g[n] = m.gaugeValString(f())
	}

	h = make(map[string]*circonusllhist.Histogram, len(m.histograms))
	for n, hist := range m.histograms {
		hist.rw.Lock()
		h[n] = hist.hist.CopyAndReset()
		hist.rw.Unlock()
	}

	t = make(map[string]string, len(m.text)+len(m.textFuncs))
	for n, v := range m.text {
		t[n] = v
	}

	for n, f := range m.textFuncs {
		t[n] = f()
	}

	if m.resetCounters {
		m.counters = make(map[string]uint64)
		m.counterFuncs = make(map[string]func() uint64)
	}

	if m.resetGauges {
		m.gauges = make(map[string]string)
		m.gaugeFuncs = make(map[string]func() int64)
	}

	if m.resetHistograms {
		m.histograms = make(map[string]*Histogram)
	}

	if m.resetText {
		m.text = make(map[string]string)
		m.textFuncs = make(map[string]func() string)
	}

	return
}
<commit_msg>upd: breakup snapshot, target locking to just when needed to not block submission of new samples<commit_after>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package circonusgometrics

import (
	"github.com/circonus-labs/circonusllhist"
)

// Reset removes all existing counters and gauges.
func (m *CirconusMetrics) Reset() {
	m.cm.Lock()
	defer m.cm.Unlock()

	m.cfm.Lock()
	defer m.cfm.Unlock()

	m.gm.Lock()
	defer m.gm.Unlock()

	m.gfm.Lock()
	defer m.gfm.Unlock()

	m.hm.Lock()
	defer m.hm.Unlock()

	m.tm.Lock()
	defer m.tm.Unlock()

	m.tfm.Lock()
	defer m.tfm.Unlock()

	m.counters = make(map[string]uint64)
	m.counterFuncs = make(map[string]func() uint64)
	m.gauges = make(map[string]string)
	m.gaugeFuncs = make(map[string]func() int64)
	m.histograms = make(map[string]*Histogram)
	m.text = make(map[string]string)
	m.textFuncs = make(map[string]func() string)
}

// snapshot returns a copy of the values of all registered counters and gauges.
func (m *CirconusMetrics) snapshot() (c map[string]uint64, g map[string]string, h map[string]*circonusllhist.Histogram, t map[string]string) {
	c = m.snapCounters()
	g = m.snapGauges()
	h = m.snapHistograms()
	t = m.snapText()

	return
}

func (m *CirconusMetrics) snapCounters() map[string]uint64 {
	c := make(map[string]uint64, len(m.counters)+len(m.counterFuncs))

	m.cm.Lock()
	for n, v := range m.counters {
		c[n] = v
	}
	if m.resetCounters && len(c) > 0 {
		m.counters = make(map[string]uint64)
	}
	m.cm.Unlock()

	m.cfm.Lock()
	for n, f := range m.counterFuncs {
		c[n] = f()
	}
	if m.resetCounters && len(c) > 0 {
		m.counterFuncs = make(map[string]func() uint64)
	}
	m.cfm.Unlock()

	return c
}

func (m *CirconusMetrics) snapGauges() map[string]string {
	g := make(map[string]string, len(m.gauges)+len(m.gaugeFuncs))

	m.gm.Lock()
	for n, v := range m.gauges {
		g[n] = v
	}
	if m.resetGauges && len(g) > 0 {
		m.gauges = make(map[string]string)
	}
	m.gm.Unlock()

	m.gfm.Lock()
	for n, f := range m.gaugeFuncs {
		g[n] = m.gaugeValString(f())
	}
	if m.resetGauges && len(g) > 0 {
		m.gaugeFuncs = make(map[string]func() int64)
	}
	m.gfm.Unlock()

	return g
}

func (m *CirconusMetrics) snapHistograms() map[string]*circonusllhist.Histogram {
	h := make(map[string]*circonusllhist.Histogram, len(m.histograms))

	m.hm.Lock()
	for n, hist := range m.histograms {
		hist.rw.Lock()
		h[n] = hist.hist.CopyAndReset()
		hist.rw.Unlock()
	}
	if m.resetHistograms && len(h) > 0 {
		m.histograms = make(map[string]*Histogram)
	}
	m.hm.Unlock()

	return h
}

func (m *CirconusMetrics) snapText() map[string]string {
	t := make(map[string]string, len(m.text)+len(m.textFuncs))

	m.tm.Lock()
	for n, v := range m.text {
		t[n] = v
	}
	if m.resetText && len(t) > 0 {
		m.text = make(map[string]string)
	}
	m.tm.Unlock()

	m.tfm.Lock()
	for n, f := range m.textFuncs {
		t[n] = f()
	}
	if m.resetText && len(t) > 0 {
		m.textFuncs = make(map[string]func() string)
	}
	m.tfm.Unlock()

	return t
}
<|endoftext|>


<commit_before>package dbr

import (
	"bytes"
	"database/sql/driver"
	"reflect"
	"unicode"
)

func camelCaseToSnakeCase(name string) string {
	buf := new(bytes.Buffer)

	runes := []rune(name)

	for i := 0; i < len(runes); i++ {
		buf.WriteRune(unicode.ToLower(runes[i]))
		if i != len(runes)-1 && unicode.IsUpper(runes[i+1]) &&
			(unicode.IsLower(runes[i]) || unicode.IsDigit(runes[i]) ||
				(i != len(runes)-2 && unicode.IsLower(runes[i+2]))) {
			buf.WriteRune('_')
		}
	}

	return buf.String()
}

func structMap(value reflect.Value) map[string]reflect.Value {
	m := make(map[string]reflect.Value)
	structValue(m, value)
	return m
}

var (
	typeValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
)

var nilablesIndex map[int]bool
var nilables = map[string]reflect.Type {
	"uint":      reflect.TypeOf(*new(NullInt64)),
	"uint8":     reflect.TypeOf(*new(NullInt64)),
	"uint16":    reflect.TypeOf(*new(NullInt64)),
	"uint32":    reflect.TypeOf(*new(NullInt64)),
	"uint64":    reflect.TypeOf(*new(NullInt64)),
	"int":       reflect.TypeOf(*new(NullInt64)),
	"int8":      reflect.TypeOf(*new(NullInt64)),
	"int16":     reflect.TypeOf(*new(NullInt64)),
	"int32":     reflect.TypeOf(*new(NullInt64)),
	"int64":     reflect.TypeOf(*new(NullInt64)),
	"float32":   reflect.TypeOf(*new(NullFloat64)),
	"float64":   reflect.TypeOf(*new(NullFloat64)),
	"string":    reflect.TypeOf(*new(NullString)),
	"time.Time": reflect.TypeOf(*new(NullTime)),
	"bool":      reflect.TypeOf(*new(NullBool)),
}

func structValue(m map[string]reflect.Value, value reflect.Value) {
	if value.Type().Implements(typeValuer) {
		return
	}
	switch value.Kind() {
	case reflect.Ptr:
		if value.IsNil() {
			return
		}
		structValue(m, value.Elem())
	case reflect.Struct:
		t := value.Type()
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if field.PkgPath != "" && !field.Anonymous {
				// unexported
				continue
			}
			tag := field.Tag.Get("db")
			if tag == "-" {
				// ignore
				continue
			}
			nilable := false
			if tag == "!" {
				nilable = true
				tag = ""
			}
			if tag == "" {
				// no tag, but we can record the field name
				tag = camelCaseToSnakeCase(field.Name)
			}
			fieldValue := value.Field(i)
			if _, ok := m[tag]; !ok {
				_, supportedNilable := nilables[field.Type.String()]
				if nilable && supportedNilable {
						m[tag] = reflect.New(nilables[field.Type.String()]).Elem()
						nilablesIndex[len(m) - 1] = true
				} else {
					m[tag] = fieldValue
				}
			}
			structValue(m, fieldValue)
		}
	}
}
<commit_msg>resolved bug on nilable tyoe<commit_after>package dbr

import (
	"bytes"
	"database/sql/driver"
	"reflect"
	"unicode"
)

func camelCaseToSnakeCase(name string) string {
	buf := new(bytes.Buffer)

	runes := []rune(name)

	for i := 0; i < len(runes); i++ {
		buf.WriteRune(unicode.ToLower(runes[i]))
		if i != len(runes)-1 && unicode.IsUpper(runes[i+1]) &&
			(unicode.IsLower(runes[i]) || unicode.IsDigit(runes[i]) ||
				(i != len(runes)-2 && unicode.IsLower(runes[i+2]))) {
			buf.WriteRune('_')
		}
	}

	return buf.String()
}

func structMap(value reflect.Value) map[string]reflect.Value {
	m := make(map[string]reflect.Value)
	structValue(m, value)
	return m
}

var (
	typeValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
)

var nilablesIndex = make(map[int]bool)
var nilables = map[string]reflect.Type{
	"uint":      reflect.TypeOf(*new(NullInt64)),
	"uint8":     reflect.TypeOf(*new(NullInt64)),
	"uint16":    reflect.TypeOf(*new(NullInt64)),
	"uint32":    reflect.TypeOf(*new(NullInt64)),
	"uint64":    reflect.TypeOf(*new(NullInt64)),
	"int":       reflect.TypeOf(*new(NullInt64)),
	"int8":      reflect.TypeOf(*new(NullInt64)),
	"int16":     reflect.TypeOf(*new(NullInt64)),
	"int32":     reflect.TypeOf(*new(NullInt64)),
	"int64":     reflect.TypeOf(*new(NullInt64)),
	"float32":   reflect.TypeOf(*new(NullFloat64)),
	"float64":   reflect.TypeOf(*new(NullFloat64)),
	"string":    reflect.TypeOf(*new(NullString)),
	"time.Time": reflect.TypeOf(*new(NullTime)),
	"bool":      reflect.TypeOf(*new(NullBool)),
}

func structValue(m map[string]reflect.Value, value reflect.Value) {
	if value.Type().Implements(typeValuer) {
		return
	}
	switch value.Kind() {
	case reflect.Ptr:
		if value.IsNil() {
			return
		}
		structValue(m, value.Elem())
	case reflect.Struct:
		t := value.Type()
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if field.PkgPath != "" && !field.Anonymous {
				// unexported
				continue
			}
			tag := field.Tag.Get("db")
			if tag == "-" {
				// ignore
				continue
			}
			nilable := false
			if tag == "!" {
				nilable = true
				tag = ""
			}
			if tag == "" {
				// no tag, but we can record the field name
				tag = camelCaseToSnakeCase(field.Name)
			}
			fieldValue := value.Field(i)
			if _, ok := m[tag]; !ok {
				_, supportedNilable := nilables[field.Type.String()]
				if nilable && supportedNilable {
					m[tag] = reflect.New(nilables[field.Type.String()]).Elem()
					nilablesIndex[len(m)-1] = true
				} else {
					m[tag] = fieldValue
				}
			}
			structValue(m, fieldValue)
		}
	}
}
<|endoftext|>


<commit_before>package main

import "net/http"

// GetStatusCode checks and returns status code for URL
func GetStatusCode(url string) (int, error) {
	resp, err := http.Get(url)

	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	return resp.StatusCode, nil
}

// IsSuccessfulStatus returns whether status code is successful. (2xx or 3xx)
func IsSuccessfulStatus(statusCode int) bool {
	n := statusCode / 100

	// Successful: 2xx, 3xx
	return n == 2 || n == 3
}
<commit_msg>use 'Zatsu_Monitor/:verion(:revision)' as ua instead of 'Go-http-client/:go_version'<commit_after>package main

import "net/http"

// GetStatusCode checks and returns status code for URL
func GetStatusCode(url string) (int, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return 0, err
	}
	req.Header.Add("User-Agent", "Zatsu_Monitor/"+Version+"("+Revision+")")

	resp, err := http.DefaultClient.Do(req)

	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	return resp.StatusCode, nil
}

// IsSuccessfulStatus returns whether status code is successful. (2xx or 3xx)
func IsSuccessfulStatus(statusCode int) bool {
	n := statusCode / 100

	// Successful: 2xx, 3xx
	return n == 2 || n == 3
}
<|endoftext|>


<commit_before>// Template for console based debug tracing

package dbg

import (
	"fmt"
	"github.com/rmohid/go-template/config"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"time"
)

var (
	writers = map[string](io.Writer){}
)

func init() {
	writers[""] = devnull()
	writers["devnull"] = devnull()
	writers["stdout"] = os.Stdout
	writers["stderr"] = os.Stderr
	writers["http"] = httpwriter()

	// define all default options
	var opts = [][]string{
		{"dbg.debugWriter", "stderr", "default debug log output"},
		{"dbg.verbosity", "0", "verbosity level for debug output"},
		{"dbg.httpUrl", "", "http server for log delivery"},
	}

	config.PushArgs(opts)
}
func ErrLog(verbosity int, format string, a ...interface{}) {
	val, err := strconv.Atoi(config.Get("dbg.verbosity"))
	if err != nil {
		log.Fatal("dbg.ErrLog:", err)
	}
	if val >= verbosity {
		fmt.Fprintf(os.Stderr, format, a...)
	}
}
func Log(verbosity int, a ...interface{}) {
	val, err := strconv.Atoi(config.Get("dbg.verbosity"))
	if err != nil {
		log.Fatal("dbg.Log:", err)
	}
	if val >= verbosity {
		fmt.Fprintln(writers[config.Get("dbg.debugWriter")],
			a...)
	}
}
func devnull() io.Writer {
	null, err := os.Open(os.DevNull)
	if err != nil {
		log.Fatal("dbg.devnull:", err)
	}
	return null
}

func httpwriter() io.Writer {
	var h httpWriter
	return h
}

type httpWriter struct {
}

func (h httpWriter) Write(p []byte) (n int, err error) {
	str := config.Get("dbg.httpUrl")
	if str == "" {
		return 0, nil
	}
	payload := fmt.Sprintf(string(p[:]))
	str = fmt.Sprintf("http://%s?%s=%s", str, time.Now().Format("2006-01-02T15:04:05.999Z07:00"), url.QueryEscape(payload))
	resp, err := http.Get(str)
	if err != nil {
		return 0, fmt.Errorf("dbg.httpWriter:", err)
	}
	defer resp.Body.Close()
	return 0, nil
}
<commit_msg>added file log target<commit_after>// Template for console based debug tracing

package dbg

import (
	"fmt"
	"github.com/rmohid/go-template/config"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"time"
)

var (
	writers = map[string](io.Writer){}
)

func init() {
	writers[""] = devnull()
	writers["devnull"] = devnull()
	writers["stdout"] = os.Stdout
	writers["stderr"] = os.Stderr
	writers["http"] = httpwriter()
	writers["file"] = filewriter()

	// define all default options
	var opts = [][]string{
		{"dbg.debugWriter", "stderr", "default debug log output"},
		{"dbg.verbosity", "0", "verbosity level for debug output"},
		{"dbg.logfile", "config.log", "filename for log collection"},
		{"dbg.httpUrl", "", "http server for log delivery"},
	}

	config.PushArgs(opts)
}
func ErrLog(verbosity int, format string, a ...interface{}) {
	val, err := strconv.Atoi(config.Get("dbg.verbosity"))
	if err != nil {
		log.Fatal("dbg.ErrLog:", err)
	}
	if val >= verbosity {
		fmt.Fprintf(os.Stderr, format, a...)
	}
}
func Log(verbosity int, a ...interface{}) {
	val, err := strconv.Atoi(config.Get("dbg.verbosity"))
	if err != nil {
		log.Fatal("dbg.Log:", err)
	}
	if val >= verbosity {
		fmt.Fprintln(writers[config.Get("dbg.debugWriter")],
			a...)
	}
}
func devnull() io.Writer {
	null, err := os.Open(os.DevNull)
	if err != nil {
		log.Fatal("dbg.devnull:", err)
	}
	return null
}

func httpwriter() io.Writer {
	var h httpWriter
	return h
}

type httpWriter struct {
}

func (h httpWriter) Write(p []byte) (n int, err error) {
	str := config.Get("dbg.httpUrl")
	if str == "" {
		return 0, nil
	}
	payload := fmt.Sprintf(string(p[:]))
	str = fmt.Sprintf("http://%s?%s=%s", str, time.Now().Format("2006-01-02T15:04:05.999Z07:00"), url.QueryEscape(payload))
	resp, err := http.Get(str)
	if err != nil {
		return 0, fmt.Errorf("dbg.httpWriter:", err)
	}
	defer resp.Body.Close()
	return 0, nil
}

func filewriter() io.Writer {
	var h fileWriter
	return h
}

type fileWriter struct {
}

func (h fileWriter) Write(p []byte) (n int, err error) {
	str := config.Get("dbg.logfile")
	if str == "" {
		return 0, nil
	}
	f, err := os.OpenFile(str, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal("dbg.filewriter:", err)
	}
	defer f.Close()
	return f.Write(p)
}
<|endoftext|>


<commit_before>package dockermachine

import (
	"encoding/json"
	"fmt"

	"github.com/andrewsmedina/yati/tsuru/iaas"
	"github.com/docker/machine/drivers/virtualbox"
	"github.com/docker/machine/libmachine"
	"github.com/docker/machine/libmachine/host"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) createMachine() (*host.Host, error) {
	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	driver := virtualbox.NewDriver("tsuru", "/tmp/automatic")
	data, err := json.Marshal(driver)
	if err != nil {
		return nil, err
	}
	h, err := client.NewHost("virtualbox", data)
	if err != nil {
		return nil, err
	}
	err = client.Create(h)
	return h, err
}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	host, err := i.createMachine()
	if err != nil {
		return nil, err
	}
	config := map[string]string{}
	ip, err := host.Driver.GetIP()
	if err != nil {
		return nil, err
	}
	m := iaas.Machine{
		Address: fmt.Sprintf("https://%s:2376", ip),
		Iaas:    "docker-machine",
		Config:  config,
	}
	return &m, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	defer client.Close()
	h, err := client.Load("tsuru")
	if err != nil {
		return err
	}
	return h.Driver.Remove()
}
<commit_msg>iaas/dm: unify create machine method<commit_after>package dockermachine

import (
	"encoding/json"
	"fmt"

	"github.com/andrewsmedina/yati/tsuru/iaas"
	"github.com/docker/machine/drivers/virtualbox"
	"github.com/docker/machine/libmachine"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	defer client.Close()
	driver := virtualbox.NewDriver("tsuru", "/tmp/automatic")
	data, err := json.Marshal(driver)
	if err != nil {
		return nil, err
	}
	host, err := client.NewHost("virtualbox", data)
	if err != nil {
		return nil, err
	}
	err = client.Create(host)
	config := map[string]string{}
	ip, err := host.Driver.GetIP()
	if err != nil {
		return nil, err
	}
	m := iaas.Machine{
		Address: fmt.Sprintf("https://%s:2376", ip),
		Iaas:    "docker-machine",
		Config:  config,
	}
	return &m, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	defer client.Close()
	h, err := client.Load("tsuru")
	if err != nil {
		return err
	}
	return h.Driver.Remove()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/joyent/gosdc/cloudapi"
	"regexp"
	"time"
)

var (
	machineStateRunning = "running"
	machineStateStopped = "stopped"

	machineStateChangeTimeout       = 10 * time.Minute
	machineStateChangeCheckInterval = 10 * time.Second
)

func resourceMachine() *schema.Resource {
	return &schema.Resource{
		Create: wrapCallback(resourceMachineCreate),
		Exists: wrapExistsCallback(resourceMachineExists),
		Read:   wrapCallback(resourceMachineRead),
		Update: wrapCallback(resourceMachineUpdate),
		Delete: wrapCallback(resourceMachineDelete),

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Description:  "friendly name",
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: resourceMachineValidateName,
			},
			"type": &schema.Schema{
				Description: "machine type (smartmachine or virtualmachine)",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"state": &schema.Schema{
				Description: "current state of the machine",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"dataset": &schema.Schema{
				Description: "dataset URN the machine was provisioned with",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"memory": &schema.Schema{
				Description: "amount of memory the machine has (in Mb)",
				Type:        schema.TypeInt,
				Computed:    true,
			},
			"disk": &schema.Schema{
				Description: "amount of disk the machine has (in Gb)",
				Type:        schema.TypeInt,
				Computed:    true,
			},
			"ips": &schema.Schema{
				Description: "IP addresses the machine has",
				Type:        schema.TypeList,
				Computed:    true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
			"metadata": &schema.Schema{
				Description: "machine metadata, e.g. authorized-keys",
				Type:        schema.TypeMap,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
			},
			"tags": &schema.Schema{
				Description: "machine tags",
				Type:        schema.TypeMap,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
			},
			"created": &schema.Schema{
				Description: "when the machine was created",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"updated": &schema.Schema{
				Description: "when the machine was update",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"package": &schema.Schema{
				Description: "name of the pakcage to use on provisioning",
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true, // TODO: remove when Update is added
				// TODO: validate that the package is available
			},
			"image": &schema.Schema{
				Description: "image UUID",
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true, // TODO: remove when Update is added
				// TODO: validate that the UUID is valid
			},
			"primaryip": &schema.Schema{
				Description: "the primary (public) IP address for the machine",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"networks": &schema.Schema{
				Description: "desired network IDs",
				Type:        schema.TypeList,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				// Default:     []string{"public", "private"},
				// TODO: validate that a valid network is presented
			},
			// TODO: firewall_enabled
		},
	}
}

func resourceMachineCreate(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	var networks []string
	for _, network := range d.Get("networks").([]interface{}) {
		networks = append(networks, network.(string))
	}

	metadata := map[string]string{}
	for k, v := range d.Get("metadata").(map[string]interface{}) {
		metadata[k] = v.(string)
	}

	tags := map[string]string{}
	for k, v := range d.Get("tags").(map[string]interface{}) {
		tags[k] = v.(string)
	}

	machine, err := api.CreateMachine(cloudapi.CreateMachineOpts{
		Name:            d.Get("name").(string),
		Package:         d.Get("package").(string),
		Image:           d.Get("image").(string),
		Networks:        networks,
		Metadata:        metadata,
		Tags:            tags,
		FirewallEnabled: true, // TODO: turn this into another schema field
	})
	if err != nil {
		return err
	}

	err = waitForMachineState(api, machine.Id, machineStateRunning, machineStateChangeTimeout)
	if err != nil {
		return err
	}

	// refresh state after it provisions
	machine, err = api.GetMachine(machine.Id)
	if err != nil {
		return err
	}

	setFromMachine(d, machine)

	return nil
}

func resourceMachineExists(d ResourceData, config *Config) (bool, error) {
	api, err := config.Cloud()
	if err != nil {
		return false, err
	}

	machine, err := api.GetMachine(d.Id())

	return machine != nil && err == nil, err
}

func resourceMachineRead(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	machine, err := api.GetMachine(d.Id())
	if err != nil {
		return err
	}

	setFromMachine(d, machine)

	return nil
}

func resourceMachineUpdate(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	d.Partial(true)

	if d.HasChange("name") {
		if err := api.RenameMachine(d.Id(), d.Get("name").(string)); err != nil {
			return err
		}

		d.SetPartial("name")
	}

	d.Partial(false)

	return nil
}

func resourceMachineDelete(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	state, err := readMachineState(api, d.Id())
	if state != machineStateStopped {
		err = api.StopMachine(d.Id())
		if err != nil {
			return err
		}

		waitForMachineState(api, d.Id(), machineStateStopped, machineStateChangeTimeout)
	}

	err = api.DeleteMachine(d.Id())
	if err != nil {
		return err
	}

	d.SetId("")

	return nil
}

func readMachineState(api *cloudapi.Client, id string) (string, error) {
	machine, err := api.GetMachine(id)
	if err != nil {
		return "", err
	}

	return machine.State, nil
}

// waitForMachineState waits for a machine to be in the desired state (waiting
// some seconds between each poll). If it doesn't reach the state within the
// duration specified in `timeout`, it returns ErrMachineStateTimeout.
func waitForMachineState(api *cloudapi.Client, id, state string, timeout time.Duration) error {
	return waitFor(
		func() (bool, error) {
			currentState, err := readMachineState(api, id)
			return currentState == state, err
		},
		machineStateChangeCheckInterval,
		machineStateChangeTimeout,
	)
}

// setFromMachine sets resource data from a machine. This includes the ID.
func setFromMachine(d ResourceData, machine *cloudapi.Machine) {
	d.SetId(machine.Id)
	d.Set("name", machine.Name)
	d.Set("type", machine.Type)
	d.Set("state", machine.State)
	d.Set("dataset", machine.Dataset)
	d.Set("memory", machine.Memory)
	d.Set("disk", machine.Disk)
	d.Set("ips", machine.IPs)
	d.Set("metadata", machine.Metadata)
	d.Set("tags", machine.Tags)
	d.Set("created", machine.Created)
	d.Set("updated", machine.Updated)
	d.Set("package", machine.Package)
	d.Set("image", machine.Image)
	d.Set("primaryip", machine.PrimaryIP)
	d.Set("networks", machine.Networks)
}

func resourceMachineValidateName(value interface{}, name string) (warnings []string, errors []error) {
	warnings = []string{}
	errors = []error{}

	r := regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\_\.\-]*$`)
	if !r.Match([]byte(value.(string))) {
		errors = append(errors, fmt.Errorf(`"%s" is not a valid %s`, value.(string), name))
	}

	return warnings, errors
}
<commit_msg>machine: wait for name change<commit_after>package main

import (
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/joyent/gosdc/cloudapi"
	"regexp"
	"time"
)

var (
	machineStateRunning = "running"
	machineStateStopped = "stopped"

	machineStateChangeTimeout       = 10 * time.Minute
	machineStateChangeCheckInterval = 10 * time.Second
)

func resourceMachine() *schema.Resource {
	return &schema.Resource{
		Create: wrapCallback(resourceMachineCreate),
		Exists: wrapExistsCallback(resourceMachineExists),
		Read:   wrapCallback(resourceMachineRead),
		Update: wrapCallback(resourceMachineUpdate),
		Delete: wrapCallback(resourceMachineDelete),

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Description:  "friendly name",
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: resourceMachineValidateName,
			},
			"type": &schema.Schema{
				Description: "machine type (smartmachine or virtualmachine)",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"state": &schema.Schema{
				Description: "current state of the machine",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"dataset": &schema.Schema{
				Description: "dataset URN the machine was provisioned with",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"memory": &schema.Schema{
				Description: "amount of memory the machine has (in Mb)",
				Type:        schema.TypeInt,
				Computed:    true,
			},
			"disk": &schema.Schema{
				Description: "amount of disk the machine has (in Gb)",
				Type:        schema.TypeInt,
				Computed:    true,
			},
			"ips": &schema.Schema{
				Description: "IP addresses the machine has",
				Type:        schema.TypeList,
				Computed:    true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
			"metadata": &schema.Schema{
				Description: "machine metadata, e.g. authorized-keys",
				Type:        schema.TypeMap,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
			},
			"tags": &schema.Schema{
				Description: "machine tags",
				Type:        schema.TypeMap,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
			},
			"created": &schema.Schema{
				Description: "when the machine was created",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"updated": &schema.Schema{
				Description: "when the machine was update",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"package": &schema.Schema{
				Description: "name of the pakcage to use on provisioning",
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true, // TODO: remove when Update is added
				// TODO: validate that the package is available
			},
			"image": &schema.Schema{
				Description: "image UUID",
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true, // TODO: remove when Update is added
				// TODO: validate that the UUID is valid
			},
			"primaryip": &schema.Schema{
				Description: "the primary (public) IP address for the machine",
				Type:        schema.TypeString,
				Computed:    true,
			},
			"networks": &schema.Schema{
				Description: "desired network IDs",
				Type:        schema.TypeList,
				Optional:    true,
				ForceNew:    true, // TODO: remove when Update is added
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				// Default:     []string{"public", "private"},
				// TODO: validate that a valid network is presented
			},
			// TODO: firewall_enabled
		},
	}
}

func resourceMachineCreate(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	var networks []string
	for _, network := range d.Get("networks").([]interface{}) {
		networks = append(networks, network.(string))
	}

	metadata := map[string]string{}
	for k, v := range d.Get("metadata").(map[string]interface{}) {
		metadata[k] = v.(string)
	}

	tags := map[string]string{}
	for k, v := range d.Get("tags").(map[string]interface{}) {
		tags[k] = v.(string)
	}

	machine, err := api.CreateMachine(cloudapi.CreateMachineOpts{
		Name:            d.Get("name").(string),
		Package:         d.Get("package").(string),
		Image:           d.Get("image").(string),
		Networks:        networks,
		Metadata:        metadata,
		Tags:            tags,
		FirewallEnabled: true, // TODO: turn this into another schema field
	})
	if err != nil {
		return err
	}

	err = waitForMachineState(api, machine.Id, machineStateRunning, machineStateChangeTimeout)
	if err != nil {
		return err
	}

	// refresh state after it provisions
	machine, err = api.GetMachine(machine.Id)
	if err != nil {
		return err
	}

	setFromMachine(d, machine)

	return nil
}

func resourceMachineExists(d ResourceData, config *Config) (bool, error) {
	api, err := config.Cloud()
	if err != nil {
		return false, err
	}

	machine, err := api.GetMachine(d.Id())

	return machine != nil && err == nil, err
}

func resourceMachineRead(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	machine, err := api.GetMachine(d.Id())
	if err != nil {
		return err
	}

	setFromMachine(d, machine)

	return nil
}

func resourceMachineUpdate(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	d.Partial(true)

	if d.HasChange("name") {
		if err := api.RenameMachine(d.Id(), d.Get("name").(string)); err != nil {
			return err
		}

		err := waitFor(
			func() (bool, error) {
				machine, err := api.GetMachine(d.Id())
				return machine.Name == d.Get("name").(string), err
			},
			machineStateChangeCheckInterval,
			1*time.Minute,
		)
		if err != nil {
			return err
		}

		d.SetPartial("name")
	}

	d.Partial(false)

	return nil
}

func resourceMachineDelete(d ResourceData, config *Config) error {
	api, err := config.Cloud()
	if err != nil {
		return err
	}

	state, err := readMachineState(api, d.Id())
	if state != machineStateStopped {
		err = api.StopMachine(d.Id())
		if err != nil {
			return err
		}

		waitForMachineState(api, d.Id(), machineStateStopped, machineStateChangeTimeout)
	}

	err = api.DeleteMachine(d.Id())
	if err != nil {
		return err
	}

	d.SetId("")

	return nil
}

func readMachineState(api *cloudapi.Client, id string) (string, error) {
	machine, err := api.GetMachine(id)
	if err != nil {
		return "", err
	}

	return machine.State, nil
}

// waitForMachineState waits for a machine to be in the desired state (waiting
// some seconds between each poll). If it doesn't reach the state within the
// duration specified in `timeout`, it returns ErrMachineStateTimeout.
func waitForMachineState(api *cloudapi.Client, id, state string, timeout time.Duration) error {
	return waitFor(
		func() (bool, error) {
			currentState, err := readMachineState(api, id)
			return currentState == state, err
		},
		machineStateChangeCheckInterval,
		machineStateChangeTimeout,
	)
}

// setFromMachine sets resource data from a machine. This includes the ID.
func setFromMachine(d ResourceData, machine *cloudapi.Machine) {
	d.SetId(machine.Id)
	d.Set("name", machine.Name)
	d.Set("type", machine.Type)
	d.Set("state", machine.State)
	d.Set("dataset", machine.Dataset)
	d.Set("memory", machine.Memory)
	d.Set("disk", machine.Disk)
	d.Set("ips", machine.IPs)
	d.Set("metadata", machine.Metadata)
	d.Set("tags", machine.Tags)
	d.Set("created", machine.Created)
	d.Set("updated", machine.Updated)
	d.Set("package", machine.Package)
	d.Set("image", machine.Image)
	d.Set("primaryip", machine.PrimaryIP)
	d.Set("networks", machine.Networks)
}

func resourceMachineValidateName(value interface{}, name string) (warnings []string, errors []error) {
	warnings = []string{}
	errors = []error{}

	r := regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\_\.\-]*$`)
	if !r.Match([]byte(value.(string))) {
		errors = append(errors, fmt.Errorf(`"%s" is not a valid %s`, value.(string), name))
	}

	return warnings, errors
}
<|endoftext|>


<commit_before>package sdp

import (
	"fmt"
	"strconv"

	"time"

	"github.com/pkg/errors"
)

// Attributes is set of k:v.
type Attributes map[string]string

// Value returns string v.
func (a Attributes) Value(attribute string) string { return a[attribute] }

// Flag returns true if set.
func (a Attributes) Flag(flag string) bool { return len(a[flag]) > 0 }

// Message is top level abstraction.
type Message struct {
	Version       int
	Origin        Origin
	Name          string
	Info          string
	Email         string
	Phone         string
	URI           string
	Connection    ConnectionData
	Attributes    Attributes
	Medias        Medias
	Encryption    Encryption
	Bandwidth     int
	BandwidthType BandwidthType
	Start         time.Time
	End           time.Time
}

// Flag returns true if set.
func (m Message) Flag(flag string) bool {
	if len(m.Attributes) > 0 {
		return m.Attributes.Flag(flag)
	}
	return false
}

const blank = ""

// Attribute returns string v.
func (m Message) Attribute(attribute string) string {
	if len(m.Attributes) > 0 {
		m.Attributes.Value(attribute)
	}

	return blank
}

// Medias is list of Media.
type Medias []Media

// Encryption wraps encryption Key and Method.
type Encryption struct {
	Method string
	Key    string
}

// Media is media description and attributes.
type Media struct {
	Title         string
	Description   MediaDescription
	Connection    ConnectionData
	Attributes    Attributes
	Encryption    Encryption
	Bandwidth     int
	BandwidthType BandwidthType
}

// Decoder decodes session.
type Decoder struct {
	s       Session
	pos     int
	t       Type
	v       []byte
	l       Line
	section section
	sPos    int
	m       Media
}

func (d *Decoder) next() bool {
	//time.Sleep(time.Millisecond * 100)
	if d.pos >= len(d.s) {
		return false
	}
	d.l = d.s[d.pos]
	d.v = d.l.Value
	d.t = d.l.Type
	d.pos++
	return true
}

func (d *Decoder) line() Line {
	return d.l
}

type section int

const (
	sectionSession section = iota
	sectionTime
	sectionMedia
)

func (s section) String() string {
	switch s {
	case sectionSession:
		return "s"
	case sectionTime:
		return "t"
	case sectionMedia:
		return "m"
	default:
		panic("unexpected")
	}
}

type ordering []Type

var orderingSession = ordering{
	TypeProtocolVersion,
	TypeOrigin,
	TypeSessionName,
	TypeSessionInformation,
	TypeURI,
	TypeEmail,
	TypePhone,
	TypeConnectionData,
	TypeBandwidth, // 0 or more
	TypeTimeZones, // ordering after time start
	TypeEncryptionKey,
	TypeAttribute, // 0 or more
}

const orderingAfterTime = 9

var orderingTime = ordering{
	TypeTiming,
	TypeRepeatTimes,
}

var orderingMedia = ordering{
	TypeMediaDescription,
	TypeSessionInformation, // title
	TypeConnectionData,
	TypeBandwidth,
	TypeEncryptionKey,
	TypeAttribute,
}

// isExpected determines if t is expected on pos in s section and returns nil,
// if it is expected and DecodeError if not.
func isExpected(t Type, s section, pos int) error {
	//logger := log.WithField("t", t).WithFields(log.Fields{
	//	"s": s,
	//	"p": pos,
	//})
	//logger.Printf("isExpected(%s, %s, %d)", t, s, pos)
	o := getOrdering(s)
	if len(o) <= pos {
		msg := fmt.Sprintf("position %d is out of range (>%d)",
			pos, len(o),
		)
		err := newSectionDecodeError(s, msg)
		return errors.Wrapf(err, "field %s is unexpected", t)
	}
	for _, expected := range o[pos:] {
		if expected == t {
			//logger.Printf("%s is expected", expected)
			return nil
		}
		if isOptional(expected) {
			continue
		}
		if isZeroOrMore(expected) {
			//logger.Printf("%s is not necessary", expected)
			continue
		}
	}

	// checking possible section transitions
	switch s {
	case sectionSession:
		if pos < orderingAfterTime && isExpected(t, sectionTime, 0) == nil {
			//logger.Printf("s->t")
			return nil
		}
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("s->m")
			return nil
		}
	case sectionTime:
		if isExpected(t, sectionSession, orderingAfterTime) == nil {
			//logger.Printf("t->s")
			return nil
		}
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("t->m")
			return nil
		}
	case sectionMedia:
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("m->m")
			return nil
		}
	}
	msg := fmt.Sprintf("no matches in ordering array at %s[%d]",
		s, pos,
	)
	err := newSectionDecodeError(s, msg)
	return errors.Wrapf(err, "field %s is unexpected", t)
}

func getOrdering(s section) ordering {
	switch s {
	case sectionSession:
		return orderingSession
	case sectionMedia:
		return orderingMedia
	case sectionTime:
		return orderingTime
	default:
		panic("unexpected section")
	}
}

func isOptional(t Type) bool {
	switch t {
	case TypeProtocolVersion, TypeOrigin, TypeSessionName:
		return false
	case TypeTiming:
		return false
	case TypeMediaDescription:
		return false
	default:
		return true
	}
}

func isZeroOrMore(t Type) bool {
	switch t {
	case TypeBandwidth, TypeAttribute:
		return true
	default:
		return false
	}
}

func newSectionDecodeError(s section, m string) DecodeError {
	place := fmt.Sprintf("section %s", s)
	return newDecodeError(place, m)
}

func (d *Decoder) decodeKV() (string, string) {
	var (
		key     []byte
		value   []byte
		isValue bool
	)
	for _, v := range d.v {
		if v == ':' && !isValue {
			isValue = true
			continue
		}
		if isValue {
			value = append(value, v)
		} else {
			key = append(key, v)
		}
	}
	return string(key), string(value)
}

func (d *Decoder) decodeTiming(m *Message) error {
	d.sPos = 0
	d.section = sectionTime
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		switch d.t {
		case TypeTiming, TypeRepeatTimes:
			return d.decodeField(m)
		default:
			// possible switch to Media or Session description
			d.pos--
			return nil
		}
	}
	return nil
}

func (d *Decoder) decodeMedia(m *Message) error {
	d.sPos = 0
	d.section = sectionMedia
	d.m = Media{}
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if d.t == TypeMediaDescription && d.sPos != 0 {
			d.pos--
			break
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		if err := d.decodeField(m); err != nil {
			return errors.Wrap(err, "failed to decode field")
		}
	}
	m.Medias = append(m.Medias, d.m)
	return nil
}

func (d *Decoder) decodeVersion(m *Message) error {
	n, err := strconv.Atoi(string(d.v))
	if err != nil {
		return errors.Wrap(err, "failed to parse version")
	}
	m.Version = n
	return nil
}

func addAttribute(a Attributes, k, v string) Attributes {
	if a == nil {
		a = make(Attributes)
	}
	if len(v) == 0 {
		v = "true"
	}
	a[k] = v
	return a
}

func (d *Decoder) decodeAttribute(m *Message) error {
	k, v := d.decodeKV()
	switch d.section {
	case sectionMedia:
		d.m.Attributes = addAttribute(d.m.Attributes, k, v)
	default:
		m.Attributes = addAttribute(m.Attributes, k, v)
	}
	return nil
}

func (d *Decoder) decodeSessionName(m *Message) error {
	m.Name = string(d.v)
	return nil
}

func (d *Decoder) decodeSessionInfo(m *Message) error {
	if d.section == sectionMedia {
		d.m.Title = string(d.v)
	} else {
		m.Info = string(d.v)
	}
	return nil
}

func (d *Decoder) decodeEmail(m *Message) error {
	m.Email = string(d.v)
	return nil
}

func (d *Decoder) decodePhone(m *Message) error {
	m.Phone = string(d.v)
	return nil
}

func (d *Decoder) decodeURI(m *Message) error {
	m.URI = string(d.v)
	return nil
}

func (d *Decoder) decodeEncryption(m *Message) error {
	k, v := d.decodeKV()
	e := Encryption{
		Key:    v,
		Method: k,
	}
	switch d.section {
	case sectionMedia:
		d.m.Encryption = e
	default:
		m.Encryption = e
	}
	return nil
}

func (d *Decoder) decodeBandwidth(m *Message) error {
	k, v := d.decodeKV()
	if len(v) == 0 {
		msg := "no value specified"
		err := newSectionDecodeError(d.section, msg)
		return errors.Wrap(err, "failed to decode bandwidth")
	}
	var (
		t   BandwidthType
		n   int
		err error
	)
	switch bandWidthType := BandwidthType(k); bandWidthType {
	case BandwidthApplicationSpecific, BandwidthConferenceTotal:
		t = bandWidthType
	default:
		msg := fmt.Sprintf("bad bandwidth type %s", k)
		err = newSectionDecodeError(d.section, msg)
		return errors.Wrap(err, "failed to decode bandwidth")
	}
	if n, err = strconv.Atoi(v); err != nil {
		return errors.Wrap(err, "failed to convert decode bandwidth")
	}
	if d.section == sectionMedia {
		d.m.BandwidthType = t
		d.m.Bandwidth = n
	} else {
		m.BandwidthType = t
		m.Bandwidth = n
	}
	return nil
}

func parseNTP(v []byte) (uint64, error) {
	return strconv.ParseUint(string(v), 10, 64)
}

func (d *Decoder) decodeTimingField(m *Message) error {
	var (
		startV, endV []byte
		isEndV       bool
		err          error
	)
	for _, v := range d.v {
		if v == ' ' {
			if isEndV {
				msg := "unexpected second space in timing"
				err = newSectionDecodeError(d.section, msg)
				return errors.Wrap(err, "failed to decode timing")
			}
			isEndV = true
			continue
		}
		if isEndV {
			endV = append(endV, v)
		} else {
			startV = append(startV, v)
		}
	}
	var (
		ntpStart, ntpEnd uint64
	)
	if ntpStart, err = parseNTP(startV); err != nil {
		return errors.Wrap(err, "failed to parse start time")
	}
	if ntpEnd, err = parseNTP(endV); err != nil {
		return errors.Wrap(err, "failed to parse end time")
	}
	m.Start = NTPToTime(ntpStart)
	m.End = NTPToTime(ntpEnd)
	return nil
}

func (d *Decoder) decodeField(m *Message) error {
	switch d.t {
	case TypeProtocolVersion:
		return d.decodeVersion(m)
	case TypeAttribute:
		return d.decodeAttribute(m)
	case TypeSessionName:
		return d.decodeSessionName(m)
	case TypeSessionInformation:
		return d.decodeSessionInfo(m)
	case TypeEmail:
		return d.decodeEmail(m)
	case TypePhone:
		return d.decodePhone(m)
	case TypeURI:
		return d.decodeURI(m)
	case TypeEncryptionKey:
		return d.decodeEncryption(m)
	case TypeBandwidth:
		return d.decodeBandwidth(m)
	case TypeTiming:
		return d.decodeTimingField(m)
	}
	// TODO: uncomment when all decoder methods implemented
	// panic("unexpected field")
	//log.Warnln("skipping decoding of", d.t)
	return nil
}

func (d *Decoder) decodeSession(m *Message) error {
	d.sPos = 0
	d.section = sectionSession
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		switch d.t {
		case TypeTiming:
			d.pos--
			if err := d.decodeTiming(m); err != nil {
				return errors.Wrap(err, "failed to decode timing")
			}
		case TypeMediaDescription:
			d.pos--
			oldPosition := d.sPos
			if err := d.decodeMedia(m); err != nil {
				return errors.Wrap(err, "failed to decode media")
			}
			d.sPos = oldPosition
			d.section = sectionSession
		default:
			if err := d.decodeField(m); err != nil {
				return errors.Wrap(err, "failed to decode field")
			}
		}
	}
	return nil
}

// Decode message from session.
func (d *Decoder) Decode(m *Message) error {
	return d.decodeSession(m)
}
<commit_msg>fix imports order<commit_after>package sdp

import (
	"fmt"
	"strconv"
	"time"

	"github.com/pkg/errors"
)

// Attributes is set of k:v.
type Attributes map[string]string

// Value returns string v.
func (a Attributes) Value(attribute string) string { return a[attribute] }

// Flag returns true if set.
func (a Attributes) Flag(flag string) bool { return len(a[flag]) > 0 }

// Message is top level abstraction.
type Message struct {
	Version       int
	Origin        Origin
	Name          string
	Info          string
	Email         string
	Phone         string
	URI           string
	Connection    ConnectionData
	Attributes    Attributes
	Medias        Medias
	Encryption    Encryption
	Bandwidth     int
	BandwidthType BandwidthType
	Start         time.Time
	End           time.Time
}

// Flag returns true if set.
func (m Message) Flag(flag string) bool {
	if len(m.Attributes) > 0 {
		return m.Attributes.Flag(flag)
	}
	return false
}

const blank = ""

// Attribute returns string v.
func (m Message) Attribute(attribute string) string {
	if len(m.Attributes) > 0 {
		m.Attributes.Value(attribute)
	}

	return blank
}

// Medias is list of Media.
type Medias []Media

// Encryption wraps encryption Key and Method.
type Encryption struct {
	Method string
	Key    string
}

// Media is media description and attributes.
type Media struct {
	Title         string
	Description   MediaDescription
	Connection    ConnectionData
	Attributes    Attributes
	Encryption    Encryption
	Bandwidth     int
	BandwidthType BandwidthType
}

// Decoder decodes session.
type Decoder struct {
	s       Session
	pos     int
	t       Type
	v       []byte
	l       Line
	section section
	sPos    int
	m       Media
}

func (d *Decoder) next() bool {
	//time.Sleep(time.Millisecond * 100)
	if d.pos >= len(d.s) {
		return false
	}
	d.l = d.s[d.pos]
	d.v = d.l.Value
	d.t = d.l.Type
	d.pos++
	return true
}

func (d *Decoder) line() Line {
	return d.l
}

type section int

const (
	sectionSession section = iota
	sectionTime
	sectionMedia
)

func (s section) String() string {
	switch s {
	case sectionSession:
		return "s"
	case sectionTime:
		return "t"
	case sectionMedia:
		return "m"
	default:
		panic("unexpected")
	}
}

type ordering []Type

var orderingSession = ordering{
	TypeProtocolVersion,
	TypeOrigin,
	TypeSessionName,
	TypeSessionInformation,
	TypeURI,
	TypeEmail,
	TypePhone,
	TypeConnectionData,
	TypeBandwidth, // 0 or more
	TypeTimeZones, // ordering after time start
	TypeEncryptionKey,
	TypeAttribute, // 0 or more
}

const orderingAfterTime = 9

var orderingTime = ordering{
	TypeTiming,
	TypeRepeatTimes,
}

var orderingMedia = ordering{
	TypeMediaDescription,
	TypeSessionInformation, // title
	TypeConnectionData,
	TypeBandwidth,
	TypeEncryptionKey,
	TypeAttribute,
}

// isExpected determines if t is expected on pos in s section and returns nil,
// if it is expected and DecodeError if not.
func isExpected(t Type, s section, pos int) error {
	//logger := log.WithField("t", t).WithFields(log.Fields{
	//	"s": s,
	//	"p": pos,
	//})
	//logger.Printf("isExpected(%s, %s, %d)", t, s, pos)
	o := getOrdering(s)
	if len(o) <= pos {
		msg := fmt.Sprintf("position %d is out of range (>%d)",
			pos, len(o),
		)
		err := newSectionDecodeError(s, msg)
		return errors.Wrapf(err, "field %s is unexpected", t)
	}
	for _, expected := range o[pos:] {
		if expected == t {
			//logger.Printf("%s is expected", expected)
			return nil
		}
		if isOptional(expected) {
			continue
		}
		if isZeroOrMore(expected) {
			//logger.Printf("%s is not necessary", expected)
			continue
		}
	}

	// checking possible section transitions
	switch s {
	case sectionSession:
		if pos < orderingAfterTime && isExpected(t, sectionTime, 0) == nil {
			//logger.Printf("s->t")
			return nil
		}
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("s->m")
			return nil
		}
	case sectionTime:
		if isExpected(t, sectionSession, orderingAfterTime) == nil {
			//logger.Printf("t->s")
			return nil
		}
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("t->m")
			return nil
		}
	case sectionMedia:
		if isExpected(t, sectionMedia, 0) == nil {
			//logger.Printf("m->m")
			return nil
		}
	}
	msg := fmt.Sprintf("no matches in ordering array at %s[%d]",
		s, pos,
	)
	err := newSectionDecodeError(s, msg)
	return errors.Wrapf(err, "field %s is unexpected", t)
}

func getOrdering(s section) ordering {
	switch s {
	case sectionSession:
		return orderingSession
	case sectionMedia:
		return orderingMedia
	case sectionTime:
		return orderingTime
	default:
		panic("unexpected section")
	}
}

func isOptional(t Type) bool {
	switch t {
	case TypeProtocolVersion, TypeOrigin, TypeSessionName:
		return false
	case TypeTiming:
		return false
	case TypeMediaDescription:
		return false
	default:
		return true
	}
}

func isZeroOrMore(t Type) bool {
	switch t {
	case TypeBandwidth, TypeAttribute:
		return true
	default:
		return false
	}
}

func newSectionDecodeError(s section, m string) DecodeError {
	place := fmt.Sprintf("section %s", s)
	return newDecodeError(place, m)
}

func (d *Decoder) decodeKV() (string, string) {
	var (
		key     []byte
		value   []byte
		isValue bool
	)
	for _, v := range d.v {
		if v == ':' && !isValue {
			isValue = true
			continue
		}
		if isValue {
			value = append(value, v)
		} else {
			key = append(key, v)
		}
	}
	return string(key), string(value)
}

func (d *Decoder) decodeTiming(m *Message) error {
	d.sPos = 0
	d.section = sectionTime
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		switch d.t {
		case TypeTiming, TypeRepeatTimes:
			return d.decodeField(m)
		default:
			// possible switch to Media or Session description
			d.pos--
			return nil
		}
	}
	return nil
}

func (d *Decoder) decodeMedia(m *Message) error {
	d.sPos = 0
	d.section = sectionMedia
	d.m = Media{}
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if d.t == TypeMediaDescription && d.sPos != 0 {
			d.pos--
			break
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		if err := d.decodeField(m); err != nil {
			return errors.Wrap(err, "failed to decode field")
		}
	}
	m.Medias = append(m.Medias, d.m)
	return nil
}

func (d *Decoder) decodeVersion(m *Message) error {
	n, err := strconv.Atoi(string(d.v))
	if err != nil {
		return errors.Wrap(err, "failed to parse version")
	}
	m.Version = n
	return nil
}

func addAttribute(a Attributes, k, v string) Attributes {
	if a == nil {
		a = make(Attributes)
	}
	if len(v) == 0 {
		v = "true"
	}
	a[k] = v
	return a
}

func (d *Decoder) decodeAttribute(m *Message) error {
	k, v := d.decodeKV()
	switch d.section {
	case sectionMedia:
		d.m.Attributes = addAttribute(d.m.Attributes, k, v)
	default:
		m.Attributes = addAttribute(m.Attributes, k, v)
	}
	return nil
}

func (d *Decoder) decodeSessionName(m *Message) error {
	m.Name = string(d.v)
	return nil
}

func (d *Decoder) decodeSessionInfo(m *Message) error {
	if d.section == sectionMedia {
		d.m.Title = string(d.v)
	} else {
		m.Info = string(d.v)
	}
	return nil
}

func (d *Decoder) decodeEmail(m *Message) error {
	m.Email = string(d.v)
	return nil
}

func (d *Decoder) decodePhone(m *Message) error {
	m.Phone = string(d.v)
	return nil
}

func (d *Decoder) decodeURI(m *Message) error {
	m.URI = string(d.v)
	return nil
}

func (d *Decoder) decodeEncryption(m *Message) error {
	k, v := d.decodeKV()
	e := Encryption{
		Key:    v,
		Method: k,
	}
	switch d.section {
	case sectionMedia:
		d.m.Encryption = e
	default:
		m.Encryption = e
	}
	return nil
}

func (d *Decoder) decodeBandwidth(m *Message) error {
	k, v := d.decodeKV()
	if len(v) == 0 {
		msg := "no value specified"
		err := newSectionDecodeError(d.section, msg)
		return errors.Wrap(err, "failed to decode bandwidth")
	}
	var (
		t   BandwidthType
		n   int
		err error
	)
	switch bandWidthType := BandwidthType(k); bandWidthType {
	case BandwidthApplicationSpecific, BandwidthConferenceTotal:
		t = bandWidthType
	default:
		msg := fmt.Sprintf("bad bandwidth type %s", k)
		err = newSectionDecodeError(d.section, msg)
		return errors.Wrap(err, "failed to decode bandwidth")
	}
	if n, err = strconv.Atoi(v); err != nil {
		return errors.Wrap(err, "failed to convert decode bandwidth")
	}
	if d.section == sectionMedia {
		d.m.BandwidthType = t
		d.m.Bandwidth = n
	} else {
		m.BandwidthType = t
		m.Bandwidth = n
	}
	return nil
}

func parseNTP(v []byte) (uint64, error) {
	return strconv.ParseUint(string(v), 10, 64)
}

func (d *Decoder) decodeTimingField(m *Message) error {
	var (
		startV, endV []byte
		isEndV       bool
		err          error
	)
	for _, v := range d.v {
		if v == ' ' {
			if isEndV {
				msg := "unexpected second space in timing"
				err = newSectionDecodeError(d.section, msg)
				return errors.Wrap(err, "failed to decode timing")
			}
			isEndV = true
			continue
		}
		if isEndV {
			endV = append(endV, v)
		} else {
			startV = append(startV, v)
		}
	}
	var (
		ntpStart, ntpEnd uint64
	)
	if ntpStart, err = parseNTP(startV); err != nil {
		return errors.Wrap(err, "failed to parse start time")
	}
	if ntpEnd, err = parseNTP(endV); err != nil {
		return errors.Wrap(err, "failed to parse end time")
	}
	m.Start = NTPToTime(ntpStart)
	m.End = NTPToTime(ntpEnd)
	return nil
}

func (d *Decoder) decodeField(m *Message) error {
	switch d.t {
	case TypeProtocolVersion:
		return d.decodeVersion(m)
	case TypeAttribute:
		return d.decodeAttribute(m)
	case TypeSessionName:
		return d.decodeSessionName(m)
	case TypeSessionInformation:
		return d.decodeSessionInfo(m)
	case TypeEmail:
		return d.decodeEmail(m)
	case TypePhone:
		return d.decodePhone(m)
	case TypeURI:
		return d.decodeURI(m)
	case TypeEncryptionKey:
		return d.decodeEncryption(m)
	case TypeBandwidth:
		return d.decodeBandwidth(m)
	case TypeTiming:
		return d.decodeTimingField(m)
	}
	// TODO: uncomment when all decoder methods implemented
	// panic("unexpected field")
	//log.Warnln("skipping decoding of", d.t)
	return nil
}

func (d *Decoder) decodeSession(m *Message) error {
	d.sPos = 0
	d.section = sectionSession
	for d.next() {
		if err := isExpected(d.t, d.section, d.sPos); err != nil {
			return errors.Wrap(err, "decode failed")
		}
		if !isZeroOrMore(d.t) {
			d.sPos++
		}
		switch d.t {
		case TypeTiming:
			d.pos--
			if err := d.decodeTiming(m); err != nil {
				return errors.Wrap(err, "failed to decode timing")
			}
		case TypeMediaDescription:
			d.pos--
			oldPosition := d.sPos
			if err := d.decodeMedia(m); err != nil {
				return errors.Wrap(err, "failed to decode media")
			}
			d.sPos = oldPosition
			d.section = sectionSession
		default:
			if err := d.decodeField(m); err != nil {
				return errors.Wrap(err, "failed to decode field")
			}
		}
	}
	return nil
}

// Decode message from session.
func (d *Decoder) Decode(m *Message) error {
	return d.decodeSession(m)
}
<|endoftext|>


<commit_before>package auth

import (
	"crypto/rand"
	"crypto/rsa"
	"errors"
	"fmt"
	"io/ioutil"

	"github.com/dgrijalva/jwt-go"
	"github.com/sensu/uchiwa/uchiwa/logger"
	"github.com/sensu/uchiwa/uchiwa/structs"
)

var (
	privateKey *rsa.PrivateKey
	publicKey  *rsa.PublicKey
)

// GetToken returns a string that contain the token
func GetToken(role *Role, username string) (string, error) {
	t := jwt.New(jwt.GetSigningMethod("RS256"))
	t.Claims["Role"] = role
	t.Claims["Username"] = username
	tokenString, err := t.SignedString(privateKey)
	return tokenString, err
}

// generateToken generates a private and public RSA keys
// in order to be used for the JWT signature
func generateToken() {
	privateKey = generateKeyPair()
	// Precompute some calculations
	privateKey.Precompute()
	publicKey = &privateKey.PublicKey
}

// loadToken loads a private and public RSA keys from the filesystem
// in order to be used for the JWT signature
func loadToken(a structs.Auth) error {
	logger.Debug("Attempting to load the RSA keys from the filesystem")

	if a.PrivateKey == "" || a.PublicKey == "" {
		return errors.New("The paths to the private and public RSA keys were not provided")
	}

	// Read the files from the filesystem
	prv, err := ioutil.ReadFile(a.PrivateKey)
	if err != nil {
		return fmt.Errorf("Unable to open the private key file: %v", err)
	}
	pub, err := ioutil.ReadFile(a.PublicKey)
	if err != nil {
		return fmt.Errorf("Unable to open the public key file: %v", err)
	}

	// Parse the RSA keys
	privateKey, err = jwt.ParseRSAPrivateKeyFromPEM(prv)
	if err != nil {
		return fmt.Errorf("Unable to parse the private key: %v", err)
	}
	publicKey, err = jwt.ParseRSAPublicKeyFromPEM(pub)
	if err != nil {
		return fmt.Errorf("Unable to parse the public key: %v", err)
	}

	logger.Info("Provided RSA keys successfully loaded")
	return nil
}

// initToken initializes the token by weither loading the keys from the
// filesystem with the loadToken() function or by generating temporarily
// ones with the generateToken() function
func initToken(a structs.Auth) {
	err := loadToken(a)
	if err != nil {
		logger.Debug(err)
		logger.Debug("Generating new temporary RSA keys")
		generateToken()
	}
}

// generateKeyPair generates an RSA keypair of 2048 bits using a random rand.Reader
func generateKeyPair() *rsa.PrivateKey {
	keypair, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		logger.Fatalf("Could not generate an RSA keypair: %s", err)
	}

	return keypair
}
<commit_msg>Exit with a fatal error if one of the provided RSA key is not found or invalid<commit_after>package auth

import (
	"crypto/rand"
	"crypto/rsa"
	"errors"
	"io/ioutil"

	"github.com/dgrijalva/jwt-go"
	"github.com/sensu/uchiwa/uchiwa/logger"
	"github.com/sensu/uchiwa/uchiwa/structs"
)

var (
	privateKey *rsa.PrivateKey
	publicKey  *rsa.PublicKey
)

// GetToken returns a string that contain the token
func GetToken(role *Role, username string) (string, error) {
	t := jwt.New(jwt.GetSigningMethod("RS256"))
	t.Claims["Role"] = role
	t.Claims["Username"] = username
	tokenString, err := t.SignedString(privateKey)
	return tokenString, err
}

// generateToken generates a private and public RSA keys
// in order to be used for the JWT signature
func generateToken() (*rsa.PrivateKey, *rsa.PublicKey) {
	logger.Debug("Generating new temporary RSA keys")
	privateKey := generateKeyPair()
	// Precompute some calculations
	privateKey.Precompute()
	publicKey := &privateKey.PublicKey

	return privateKey, publicKey
}

// loadToken loads a private and public RSA keys from the filesystem
// in order to be used for the JWT signature
func loadToken(a structs.Auth) (*rsa.PrivateKey, *rsa.PublicKey, error) {
	logger.Debug("Attempting to load the RSA keys from the filesystem")

	if a.PrivateKey == "" || a.PublicKey == "" {
		return nil, nil, errors.New("The paths to the private and public RSA keys were not provided")
	}

	// Read the files from the filesystem
	prv, err := ioutil.ReadFile(a.PrivateKey)
	if err != nil {
		logger.Fatalf("Unable to open the private key file: %v", err)
	}
	pub, err := ioutil.ReadFile(a.PublicKey)
	if err != nil {
		logger.Fatalf("Unable to open the public key file: %v", err)
	}

	// Parse the RSA keys
	privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(prv)
	if err != nil {
		logger.Fatalf("Unable to parse the private key: %v", err)
	}
	publicKey, err := jwt.ParseRSAPublicKeyFromPEM(pub)
	if err != nil {
		logger.Fatalf("Unable to parse the public key: %v", err)
	}

	logger.Info("Provided RSA keys successfully loaded")
	return privateKey, publicKey, nil
}

// initToken initializes the token by weither loading the keys from the
// filesystem with the loadToken() function or by generating temporarily
// ones with the generateToken() function
func initToken(a structs.Auth) {
	var err error
	privateKey, publicKey, err = loadToken(a)
	if err != nil {
		// At this point we need to generate temporary RSA keys
		logger.Debug(err)
		privateKey, publicKey = generateToken()
	}
}

// generateKeyPair generates an RSA keypair of 2048 bits using a random rand.Reader
func generateKeyPair() *rsa.PrivateKey {
	keypair, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		logger.Fatalf("Could not generate an RSA keypair: %s", err)
	}

	return keypair
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Mitchell Cooper
package wikiclient

// a Message represents a wikiserver message. the Message struct is used both
// for outgoing messages (client requests) and incoming messages (replies from
// the wikiserver).

import (
	"encoding/json"
	"errors"
)

type messageArgs map[string]interface{}

var idCounter uint

type Message struct {
	Command string      // message type
	Args    messageArgs // message arguments
	ID      uint        // message ID
}

// creates a new Message with an automatically-generated ID
func NewMessage(cmd string, args messageArgs) Message {
	idCounter++
	return NewMessageWithID(cmd, args, idCounter)
}

// creates a new Message with the specified ID
func NewMessageWithID(cmd string, args messageArgs, id uint) Message {
	return Message{cmd, args, id}
}

// creates a new Message from JSON data
// this is ugly, but I don't think there's a nicer way to do it since we use
// a JSON array and not an object?
func MessageFromJson(data []byte) (msg Message, err error) {

	// decode
	var iface interface{}
	if err = json.Unmarshal(data, &iface); err != nil {
		return msg, err
	}

	// top level must be array
	ary, ok := iface.([]interface{})
	if !ok || len(ary) != 3 {
		err = errors.New("Message must be a JSON array of length 3")
		return
	}

	// first element must be command
	cmd, ok := ary[0].(string)
	if !ok || len(cmd) == 0 {
		err = errors.New("Message has no type")
		return
	}

	// second element must be object
	args, ok := ary[1].(map[string]interface{})
	if !ok {
		err = errors.New("Message content must be a JSON object")
		return
	}

	// third element must be integer command ID
	id, ok := ary[2].(float64)
	if !ok || id < 0 {
		err = errors.New("Message has no ID")
		return
	}

	return NewMessageWithID(cmd, args, uint(id)), nil
}

// fetch an arguments as a string
func (msg Message) String(arg string) string {
	iface, ok := msg.Args[arg]
	if !ok {
		return ""
	}
	str, ok := iface.(string)
	if !ok {
		return ""
	}
	return str
}

// translates the Message to JSON
func (msg Message) ToJson() []byte {
	ary := [...]interface{}{msg.Command, msg.Args, msg.ID}
	json, _ := json.Marshal(ary)
	return json
}
<commit_msg>use spintf so that it works for any type<commit_after>// Copyright (c) 2017, Mitchell Cooper
package wikiclient

// a Message represents a wikiserver message. the Message struct is used both
// for outgoing messages (client requests) and incoming messages (replies from
// the wikiserver).

import (
	"encoding/json"
	"errors"
	"fmt"
)

type messageArgs map[string]interface{}

var idCounter uint

type Message struct {
	Command string      // message type
	Args    messageArgs // message arguments
	ID      uint        // message ID
}

// creates a new Message with an automatically-generated ID
func NewMessage(cmd string, args messageArgs) Message {
	idCounter++
	return NewMessageWithID(cmd, args, idCounter)
}

// creates a new Message with the specified ID
func NewMessageWithID(cmd string, args messageArgs, id uint) Message {
	return Message{cmd, args, id}
}

// creates a new Message from JSON data
// this is ugly, but I don't think there's a nicer way to do it since we use
// a JSON array and not an object?
func MessageFromJson(data []byte) (msg Message, err error) {

	// decode
	var iface interface{}
	if err = json.Unmarshal(data, &iface); err != nil {
		return msg, err
	}

	// top level must be array
	ary, ok := iface.([]interface{})
	if !ok || len(ary) != 3 {
		err = errors.New("Message must be a JSON array of length 3")
		return
	}

	// first element must be command
	cmd, ok := ary[0].(string)
	if !ok || len(cmd) == 0 {
		err = errors.New("Message has no type")
		return
	}

	// second element must be object
	args, ok := ary[1].(map[string]interface{})
	if !ok {
		err = errors.New("Message content must be a JSON object")
		return
	}

	// third element must be integer command ID
	id, ok := ary[2].(float64)
	if !ok || id < 0 {
		err = errors.New("Message has no ID")
		return
	}

	return NewMessageWithID(cmd, args, uint(id)), nil
}

// fetch an arguments as a string
func (msg Message) String(arg string) string {
	iface, ok := msg.Args[arg]
	if !ok {
		return ""
	}
	return fmt.Sprintf("%v", iface)
}

// translates the Message to JSON
func (msg Message) ToJson() []byte {
	ary := [...]interface{}{msg.Command, msg.Args, msg.ID}
	json, _ := json.Marshal(ary)
	return json
}
<|endoftext|>