<commit_before>// Copyright 2013 The Prometheus Authors
// 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 model

import (
	"strings"
)

const (
	// ExporterLabelPrefix is the label name prefix to prepend if a
	// synthetic label is already present in the exported metrics.
	ExporterLabelPrefix LabelName = "exporter_"

	// MetricNameLabel is the label name indicating the metric name of a
	// timeseries.
	MetricNameLabel LabelName = "__name__"

	// AddressLabel is the name of the label that holds the address of
	// a scrape target.
	AddressLabel LabelName = "__address__"

	// MetricsPathLabel is the name of the label that holds the path on which to
	// scrape a target.
	MetricsPathLabel LabelName = "__metrics_path__"

	// ReservedLabelPrefix is a prefix which is not legal in user-supplied
	// label names.
	ReservedLabelPrefix = "__"

	// MetaLabelPrefix is a prefix for labels that provide meta information.
	// Labels with this prefix are used for intermediate label processing and
	// will not be attached to time series.
	MetaLabelPrefix = "__meta_"

	// JobLabel is the label name indicating the job from which a timeseries
	// was scraped.
	JobLabel LabelName = "job"

	// InstanceLabel is the label name used for the instance label.
	InstanceLabel LabelName = "instance"

	// BucketLabel is used for the label that defines the upper bound of a
	// bucket of a histogram ("le" -> "less or equal").
	BucketLabel = "le"

	// QuantileLabel is used for the label that defines the quantile in a
	// summary.
	QuantileLabel = "quantile"
)

// A LabelName is a key for a LabelSet or Metric.  It has a value associated
// therewith.
type LabelName string

// LabelNames is a sortable LabelName slice. In implements sort.Interface.
type LabelNames []LabelName

func (l LabelNames) Len() int {
	return len(l)
}

func (l LabelNames) Less(i, j int) bool {
	return l[i] < l[j]
}

func (l LabelNames) Swap(i, j int) {
	l[i], l[j] = l[j], l[i]
}

func (l LabelNames) String() string {
	labelStrings := make([]string, 0, len(l))
	for _, label := range l {
		labelStrings = append(labelStrings, string(label))
	}
	return strings.Join(labelStrings, ", ")
}
<commit_msg>Add YAML parsing for LabelName<commit_after>// Copyright 2013 The Prometheus Authors
// 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 model

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	// ExporterLabelPrefix is the label name prefix to prepend if a
	// synthetic label is already present in the exported metrics.
	ExporterLabelPrefix LabelName = "exporter_"

	// MetricNameLabel is the label name indicating the metric name of a
	// timeseries.
	MetricNameLabel LabelName = "__name__"

	// AddressLabel is the name of the label that holds the address of
	// a scrape target.
	AddressLabel LabelName = "__address__"

	// MetricsPathLabel is the name of the label that holds the path on which to
	// scrape a target.
	MetricsPathLabel LabelName = "__metrics_path__"

	// ReservedLabelPrefix is a prefix which is not legal in user-supplied
	// label names.
	ReservedLabelPrefix = "__"

	// MetaLabelPrefix is a prefix for labels that provide meta information.
	// Labels with this prefix are used for intermediate label processing and
	// will not be attached to time series.
	MetaLabelPrefix = "__meta_"

	// JobLabel is the label name indicating the job from which a timeseries
	// was scraped.
	JobLabel LabelName = "job"

	// InstanceLabel is the label name used for the instance label.
	InstanceLabel LabelName = "instance"

	// BucketLabel is used for the label that defines the upper bound of a
	// bucket of a histogram ("le" -> "less or equal").
	BucketLabel = "le"

	// QuantileLabel is used for the label that defines the quantile in a
	// summary.
	QuantileLabel = "quantile"
)

// A LabelName is a key for a LabelSet or Metric.  It has a value associated
// therewith.
type LabelName string

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var s string
	if err := unmarshal(&s); err != nil {
		return err
	}
	if !labelNameRE.MatchString(s) {
		return fmt.Errorf("%q is not a valid label name", s)
	}
	*ln = LabelName(s)
	return nil
}

// LabelNames is a sortable LabelName slice. In implements sort.Interface.
type LabelNames []LabelName

func (l LabelNames) Len() int {
	return len(l)
}

func (l LabelNames) Less(i, j int) bool {
	return l[i] < l[j]
}

func (l LabelNames) Swap(i, j int) {
	l[i], l[j] = l[j], l[i]
}

func (l LabelNames) String() string {
	labelStrings := make([]string, 0, len(l))
	for _, label := range l {
		labelStrings = append(labelStrings, string(label))
	}
	return strings.Join(labelStrings, ", ")
}
<|endoftext|>


<commit_before>package model
<commit_msg>Add link test<commit_after>package model

import (
	"testing"
	"time"

	"github.com/davidlu1997/fast-shortener/config"
)

const configPath = "../config/config.json"

func TestIsValid(t *testing.T) {
	config, err := config.GetConfig(configPath)
	if config == nil {
		t.Fatal(err)
	}

	link1 := Link{
		URL:      "https://google.com",
		Key:      "a",
		Duration: 5 * time.Minute,
	}

	if link1.IsValid(config) {
		t.Fatal("should be invalid, key too short")
	}

	link2 := Link{
		URL:      "https://google.com",
		Key:      "derp-herp",
		Duration: 1 * time.Second,
	}

	if link2.IsValid(config) {
		t.Fatal("should be invalid, duration too short")
	}

	link3 := Link{
		URL:      "https://google.com",
		Key:      "derp-herp",
		Duration: 5 * time.Minute,
	}

	if !link3.IsValid(config) {
		t.Fatal("should be valid")
	}

	link4 := Link{
		URL:      "https://google.com",
		Key:      "abcdefghijklmnopqrstuvwxyz",
		Duration: 5 * time.Minute,
	}

	if link4.IsValid(config) {
		t.Fatal("should be invalid, key too long")
	}

	link5 := Link{
		URL:      "https://google.com",
		Key:      "derp-herp",
		Duration: 100 * time.Hour,
	}

	if link5.IsValid(config) {
		t.Fatal("should be invalid, duration too long")
	}
}
<|endoftext|>


<commit_before>package gocore

import (
	"errors"
	"os"

	"github.com/eaciit/acl/v1.0"
	"github.com/eaciit/dbox"
	"github.com/eaciit/toolkit"
)

var ConfigPath string

func GetConnectionInfo(db_type string) (string, *dbox.ConnectionInfo) {
	config := new(Configuration)

	config.ID = db_type
	db, err := config.GetDB()
	if err != nil {
		toolkit.Printf("Error get DB config: %s \n", err.Error())
	}

	setting, _ := toolkit.ToM(db["setting"])

	ci := &dbox.ConnectionInfo{
		db.GetString("host"),
		db.GetString("db"),
		db.GetString("user"),
		db.GetString("pass"),
		setting}

	return db.GetString("driver"), ci
}

func PrepareConnection(db_type string) (conn dbox.IConnection, err error) {
	driver, ci := GetConnectionInfo(db_type)
	conn, err = dbox.NewConnection(driver, ci)
	if err != nil {
		return
	}
	err = conn.Connect()
	return
}

func InitialSetDatabase() error {
	conn_acl, err := PrepareConnection(CONF_DB_ACL)
	if err != nil {
		return err
	}

	if err = acl.SetDb(conn_acl); err != nil {
		return err
	}

	conn_ostro, err := PrepareConnection(CONF_DB_OSTRO)
	if err != nil {
		return err
	}

	if err := SetDb(conn_ostro); err != nil {
		toolkit.Printf("Error set ostro database: %s \n", err.Error())
		return err
	}

	// if err := SetSession(conn_ostro); err != nil {
	// 	toolkit.Printf("Error set session mgo: %s \n", err.Error())
	// 	return err
	// }

	conn_reatime, err := PrepareConnection(CONF_DB_REALTIME)
	if err != nil {
		return err
	}

	if err := SetDbRealTime(conn_reatime); err != nil {
		toolkit.Printf("Error set realtime database: %s \n", err.Error())
		return err
	}

	return nil
}

func validateConfig() error {
	if ConfigPath == "" {
		return errors.New("gocore.validateConfig: ConfigPath is empty")
	}
	_, e := os.Stat(ConfigPath)
	if e != nil {
		return errors.New("gocore.validateConfig: " + e.Error())
	}
	return nil
}

func getConnection() (dbox.IConnection, error) {
	if e := validateConfig(); e != nil {
		return nil, errors.New("gocore.GetConnection: " + e.Error())
	}
	c, e := dbox.NewConnection("jsons", &dbox.ConnectionInfo{ConfigPath, "", "", "", toolkit.M{}.Set("newfile", true)})
	if e != nil {
		return nil, errors.New("gocore.GetConnection: " + e.Error())
	}
	e = c.Connect()
	if e != nil {
		return nil, errors.New("gocore.GetConnection: Connect: " + e.Error())
	}
	return c, nil
}
<commit_msg>add option for expiry session time<commit_after>package gocore

import (
	"errors"
	"os"
	"time"

	"github.com/eaciit/acl/v1.0"
	"github.com/eaciit/dbox"
	"github.com/eaciit/toolkit"
)

var ConfigPath string

func GetConnectionInfo(db_type string) (string, *dbox.ConnectionInfo) {
	config := new(Configuration)

	config.ID = db_type
	db, err := config.GetDB()
	if err != nil {
		toolkit.Printf("Error get DB config: %s \n", err.Error())
	}

	setting, _ := toolkit.ToM(db["setting"])

	ci := &dbox.ConnectionInfo{
		db.GetString("host"),
		db.GetString("db"),
		db.GetString("user"),
		db.GetString("pass"),
		setting}

	return db.GetString("driver"), ci
}

func PrepareConnection(db_type string) (conn dbox.IConnection, err error) {
	driver, ci := GetConnectionInfo(db_type)
	conn, err = dbox.NewConnection(driver, ci)
	if err != nil {
		return
	}
	err = conn.Connect()
	return
}

func InitialSetDatabase() error {
	conn_acl, err := PrepareConnection(CONF_DB_ACL)
	if err != nil {
		return err
	}

	if err = acl.SetDb(conn_acl); err != nil {
		return err
	}

	acl.SetExpiredDuration(time.Hour * 240)

	conn_ostro, err := PrepareConnection(CONF_DB_OSTRO)
	if err != nil {
		return err
	}

	if err := SetDb(conn_ostro); err != nil {
		toolkit.Printf("Error set ostro database: %s \n", err.Error())
		return err
	}

	// if err := SetSession(conn_ostro); err != nil {
	// 	toolkit.Printf("Error set session mgo: %s \n", err.Error())
	// 	return err
	// }

	conn_reatime, err := PrepareConnection(CONF_DB_REALTIME)
	if err != nil {
		return err
	}

	if err := SetDbRealTime(conn_reatime); err != nil {
		toolkit.Printf("Error set realtime database: %s \n", err.Error())
		return err
	}

	return nil
}

func validateConfig() error {
	if ConfigPath == "" {
		return errors.New("gocore.validateConfig: ConfigPath is empty")
	}
	_, e := os.Stat(ConfigPath)
	if e != nil {
		return errors.New("gocore.validateConfig: " + e.Error())
	}
	return nil
}

func getConnection() (dbox.IConnection, error) {
	if e := validateConfig(); e != nil {
		return nil, errors.New("gocore.GetConnection: " + e.Error())
	}
	c, e := dbox.NewConnection("jsons", &dbox.ConnectionInfo{ConfigPath, "", "", "", toolkit.M{}.Set("newfile", true)})
	if e != nil {
		return nil, errors.New("gocore.GetConnection: " + e.Error())
	}
	e = c.Connect()
	if e != nil {
		return nil, errors.New("gocore.GetConnection: Connect: " + e.Error())
	}
	return c, nil
}
<|endoftext|>


<commit_before>// Packing chain is a reflection-based dependency-injected handler chain that
// powers the sandwich middleware framework.
package chain

import (
	"bytes"
	"fmt"
	"log"
	"reflect"
	"runtime"
	"sort"
	"strings"
	"text/tabwriter"
)

var errorType = reflect.TypeOf((*error)(nil)).Elem()

// DefaultErrorHandler is called when an error in the chain occurs and no error
// handler has been registered.  Warning!  The default error handler is not
// checked to verify that it's arguments can be provided.  It's STRONGLY
// recommended to keep this as absolutely simple as possible.
var DefaultErrorHandler interface{} = func(err error) {
	log.Printf("Unhandled error: %v", err)
}

// Chain holds the stack of middleware handlers to execute.  Chain is immutable:
// all operations will return a new chain.
type Chain struct{ steps []step }

// step is a single value or handler in the middleware stack.  Each step has a
// typ flag that indicates what kind of step it is.
type step struct {
	typ stepType
	val reflect.Value
	// For tVALUE steps, this may optionally be non-nil to specific an
	// additional interface type that is provided.
	// For tRESERVE steps, this must be non-nil to declare the reserved type.
	// For t*_HANDLER steps, this is the function type.
	valTyp reflect.Type
}

type stepType uint8

const (
	tRESERVE stepType = iota
	tVALUE
	tPRE_HANDLER  // PRE handlers are the normal handlers
	tPOST_HANDLER // POST handlers are deferred handlers
	tERROR_HANDLER
)

// Clone this chain and add the extra steps to the clone.
func (c Chain) with(steps ...step) Chain {
	s := make([]step, 0, len(c.steps)+len(steps))
	s = append(s, c.steps...)
	s = append(s, steps...)
	return Chain{s}
}

// Reserve indicates that the specified type will provided by the Run(...) call
// when the chain starts.  This is typically necessary to start the chain for
// a given middleware framework.  Reserve should not be exposed to users of
// sandwich since it bypasses the causal checks and risks runtime errors.
func (c Chain) Reserve(typePtr interface{}) Chain {
	typ := reflect.TypeOf(typePtr)
	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface {
		typ = typ.Elem()
	}
	return c.with(step{tRESERVE, reflect.Value{}, typ})
}

// Provide an immediate value.  This cannot be used to provide an interface,
// instead use ProvideAs(...) or With(...) with a function that returns the
// interface.
func (c Chain) Provide(value interface{}) Chain {
	if value == nil {
		panicf("Provide(nil) is not allowed -- " +
			"did you mean to use ProvideAs(val, (*IFace)(nil))?")
	}
	return c.with(step{tVALUE, reflect.ValueOf(value), reflect.TypeOf(value)})
}

// ProvideAs provides an immediate value as the specified interface type.
func (c Chain) ProvideAs(value, ifacePtr interface{}) Chain {
	val := reflect.ValueOf(value)
	typ := reflect.TypeOf(ifacePtr)
	if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Interface {
		panicf("ifacePtr must be a pointer to an interface for "+
			"ProvideAs, instead got %s", typ)
	}
	typ = typ.Elem()
	if !val.Type().Implements(typ) {
		panicf("%s doesn't implement %s", val.Type(), typ)
	}
	return c.with(step{tVALUE, val, typ})
}

// Compute what types are available from the reserved values, provide values,
// and function return values of the current handler chain.  This excludes
// error handlers and deferred handlers.
func (c Chain) typesAvailable() map[reflect.Type]bool {
	m := map[reflect.Type]bool{}
	for _, s := range c.steps {
		switch s.typ {
		case tRESERVE:
			m[s.valTyp] = true
		case tVALUE:
			m[s.val.Type()] = true
			m[s.valTyp] = true
		case tPRE_HANDLER:
			for i := 0; i < s.valTyp.NumOut(); i++ {
				m[s.valTyp.Out(i)] = true
			}
		case tPOST_HANDLER, tERROR_HANDLER:
			// ignored, we don't allow any return values for these.
		}
	}
	return m
}

// With adds one or more handlers to the middleware chain.
func (c Chain) With(handlers ...interface{}) Chain {
	steps := make([]step, len(handlers))
	available := c.typesAvailable()
	for i, handler := range handlers {
		fn, err := valueOfFunction(handler)
		if err != nil {
			panicf("%s arg of With(...) %v", ordinalize(i+1), err)
		}
		if err := checkCanCall(available, fn); err != nil {
			panicf("%s arg of With(...) %v", ordinalize(i+1), err)
		}
		fnType := fn.Func.Type()
		steps[i] = step{tPRE_HANDLER, fn.Func, fnType}
		for i := 0; i < fnType.NumOut(); i++ {
			available[fnType.Out(i)] = true
		}
	}
	return c.with(steps...)
}

// OnErr registers an error handler to be called for failures of subsequent
// handlers.
func (c Chain) OnErr(errorHandler interface{}) Chain {
	fn, err := valueOfFunction(errorHandler)
	if err != nil {
		panicf("Error handler %v", err)
	}
	available := c.typesAvailable()
	available[errorType] = true // Set internally by chain.
	if err := checkCanCall(available, fn); err != nil {
		panicf("Error handler %v", err)
	}
	if fn.Func.Type().NumOut() > 0 {
		panicf("Error handler %s may not have any return values, signature is %s",
			fn.Name, fn.Func.Type())
	}
	return c.with(step{tERROR_HANDLER, fn.Func, fn.Func.Type()})
}

// Defer adds a deferred handler to be executed after all normal handlers and
// error handlers have been called.  Deferred handlers are executed in reverse
// order that they were registered (most recent first).  Deferred handlers can
// accept the error type even if it hasn't been explicitly provided yet.  If no
// error has occurred, it will be nil.
func (c Chain) Defer(handler interface{}) Chain {
	fn, err := valueOfFunction(handler)
	if err != nil {
		panicf("Defer(...) arg %v", err)
	}
	available := c.typesAvailable()
	available[errorType] = true // Set internally by chain.
	if err := checkCanCall(available, fn); err != nil {
		panicf("Defer(...) arg %v", err)
	}
	if fn.Func.Type().NumOut() > 0 {
		panicf("Defer'd handler %s may not have any return values, signature is %s",
			fn.Name, fn.Func.Type())
	}
	return c.with(step{tPOST_HANDLER, fn.Func, fn.Func.Type()})
}

// Run executes the middleware chain using the specified values as initial
// values for all reserved types. All reserved types must be specified, and no
// non-reserved types may be provided here.
func (c Chain) Run(reservedValues ...interface{}) error {
	data := map[reflect.Type]reflect.Value{}
	postSteps := []step{} // collect post steps here
	errHandler := step{   // Initialize using the default error handler.
		tERROR_HANDLER,
		reflect.ValueOf(DefaultErrorHandler),
		reflect.TypeOf(DefaultErrorHandler),
	}
	stack := []step{}

	// 1: Apply all of the reserved values.  Make sure that the reserved values
	// match the reserve calls, because otherwise they will be ignored!

	// Apply all of the provided reserved values.
	rvMap := map[reflect.Type]bool{}
	for i, val := range reservedValues {
		if val == nil {
			return fmt.Errorf("reserved value may not be <nil> (%s arg of Run(...))",
				ordinalize(i+1))
		}
		rv := reflect.ValueOf(val)
		rvt := rv.Type()
		if rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Interface {
			rv = rv.Elem()
			rvt = rv.Type()
		}
		data[rv.Type()] = rv
		data[rvt] = rv
		rvMap[rvt] = true
	}

	// Ensure that all of the reserved values have been provided
	for _, step := range c.steps {
		if step.typ == tRESERVE {
			if _, provided := data[step.valTyp]; !provided {
				providedReservedValues := make([]string, len(reservedValues))
				for i, val := range reservedValues {
					providedReservedValues[i] = reflect.TypeOf(val).String()
				}
				return fmt.Errorf("Cannot run chain, type %s was reserved "+
					"but no initial value was provided.  Provided types: %s",
					step.valTyp, providedReservedValues)
			}
			delete(rvMap, step.valTyp)
		}
	}

	// Make sure that no non-reserved types have bene provided.
	if len(rvMap) != 0 {
		var extra []string
		for t := range rvMap {
			extra = append(extra, t.String())
		}
		sort.Strings(extra)
		return fmt.Errorf("Run(...) was called with additional types that were "+
			"not reserved: %s", extra)
	}

	// Start executing handlers.  First pass through is the normal call chain,
	// so we skip execution of error handlers and deferred handlers, although
	// we keep track of them.
execution:
	for _, step := range c.steps {
		switch step.typ {
		case tRESERVE:
			// ignored now, already handled during initialization above.
		case tVALUE:
			data[step.val.Type()] = step.val
			data[step.valTyp] = step.val
		case tPRE_HANDLER:
			c.call(step, data, &stack)
			// Check to see if there's an error.  If so, abort the chain.
			if errorVal := data[errorType]; errorVal.IsValid() && !errorVal.IsNil() {
				break execution
			}
		case tPOST_HANDLER:
			postSteps = append(postSteps, step)
		case tERROR_HANDLER:
			errHandler = step
		}
	}

	// Execute the error handler if there is any error.
	if errorVal := data[errorType]; errorVal.IsValid() && !errorVal.IsNil() {
		c.call(errHandler, data, &stack)
	} else {
		data[errorType] = reflect.Zero(errorType)
	}

	// Finally, call any deferred functions that we've gotten to.
	for i := len(postSteps) - 1; i >= 0; i-- {
		c.call(postSteps[i], data, &stack)
	}

	return nil
}

func (c Chain) call(s step, data map[reflect.Type]reflect.Value, stack *[]step) {
	t := s.valTyp
	in := make([]reflect.Value, t.NumIn())
	for i := range in {
		in[i] = data[t.In(i)]
		// This isn't supposed to happen if we've done all our checks right.
		if !in[i].IsValid() {
			name := runtime.FuncForPC(s.val.Pointer()).Name()
			panicf("Cannot inject %s arg of type %s into %s (%s).  Data: %v",
				ordinalize(i+1), t.In(i), name, t, data)
		}
	}
	defer func() {
		if err := c.wrapPanic(recover(), *stack); err != nil {
			data[errorType] = reflect.ValueOf((*error)(&err)).Elem()
		}
	}()
	*stack = append(*stack, s)
	out := s.val.Call(in)
	for _, val := range out {
		data[val.Type()] = val
	}
}

func (c Chain) wrapPanic(x interface{}, steps []step) error {
	if x == nil {
		return nil
	}
	var stack [8192]byte
	n := runtime.Stack(stack[:], false)

	N := len(steps)
	mwStack := make([]FuncInfo, N)
	for i := range steps {
		step := steps[N-i-1]
		info := runtime.FuncForPC(step.val.Pointer())
		file, line := info.FileLine(step.val.Pointer())
		mwStack[i] = FuncInfo{info.Name(), file, line, step.val}
	}

	return PanicError{
		Val:             x,
		RawStack:        string(stack[:n]),
		MiddlewareStack: mwStack,
	}
}

// PanicError is the error that is returned if a handler panics.  It includes
// the panic'd value (Val), the raw Go stack trace (RawStack), and the
// middleware execution history (MiddlewareStack) that shows what middleware
// functions have already been called.
type PanicError struct {
	Val             interface{}
	RawStack        string
	MiddlewareStack []FuncInfo
}

// FuncInfo describes a registered middleware function.
type FuncInfo struct {
	Name string // fully-qualified name, e.g.: github.com/foo/bar.FuncName
	File string
	Line int
	Func reflect.Value
}

// FilteredStack returns the stack trace without some internal chain.* functions
// and without reflect.Value.call stack frames, since these are generally just
// noise.  The reflect.Value.call removal could affect user stack frames.
//
// TODO(aroman): Refine filtering so that it only removes reflect.Value.call
// frames due to sandwich.
func (p PanicError) FilteredStack() []string {
	lines := strings.Split(p.RawStack, "\n")
	var filtered []string
	for i := 0; i < len(lines); i++ {
		line := lines[i]
		if strings.HasPrefix(line, "github.com/augustoroman/sandwich/chain") &&
			!strings.HasPrefix(line, "github.com/augustoroman/sandwich/chain.Chain.Run(") {
			i++
			continue
		}
		if strings.HasPrefix(line, "reflect.Value.call") || strings.HasPrefix(line, "reflect.Value.Call") {
			i++
			continue
		}
		filtered = append(filtered, line)
	}
	return filtered
}

func (p PanicError) Error() string {
	var mwStack bytes.Buffer
	w := tabwriter.NewWriter(&mwStack, 5, 7, 2, ' ', 0)
	for _, fn := range p.MiddlewareStack {
		fmt.Fprintf(w, "    %s\t%s\n", fn.Name, fn.Func.Type())
	}
	w.Flush()
	return fmt.Sprintf(
		"Panic executing middleware %s: %v\n"+
			"  Middleware executed:\n%s"+
			"  Filtered call stack:\n    %s",
		p.MiddlewareStack[0].Name, p.Val,
		mwStack.String(),
		strings.Join(p.FilteredStack(), "\n    "))
}
<commit_msg>Fix package docs for chain.<commit_after>// Package chain is a reflection-based dependency-injected handler chain that
// powers the sandwich middleware framework.
package chain

import (
	"bytes"
	"fmt"
	"log"
	"reflect"
	"runtime"
	"sort"
	"strings"
	"text/tabwriter"
)

var errorType = reflect.TypeOf((*error)(nil)).Elem()

// DefaultErrorHandler is called when an error in the chain occurs and no error
// handler has been registered.  Warning!  The default error handler is not
// checked to verify that it's arguments can be provided.  It's STRONGLY
// recommended to keep this as absolutely simple as possible.
var DefaultErrorHandler interface{} = func(err error) {
	log.Printf("Unhandled error: %v", err)
}

// Chain holds the stack of middleware handlers to execute.  Chain is immutable:
// all operations will return a new chain.
type Chain struct{ steps []step }

// step is a single value or handler in the middleware stack.  Each step has a
// typ flag that indicates what kind of step it is.
type step struct {
	typ stepType
	val reflect.Value
	// For tVALUE steps, this may optionally be non-nil to specific an
	// additional interface type that is provided.
	// For tRESERVE steps, this must be non-nil to declare the reserved type.
	// For t*_HANDLER steps, this is the function type.
	valTyp reflect.Type
}

type stepType uint8

const (
	tRESERVE stepType = iota
	tVALUE
	tPRE_HANDLER  // PRE handlers are the normal handlers
	tPOST_HANDLER // POST handlers are deferred handlers
	tERROR_HANDLER
)

// Clone this chain and add the extra steps to the clone.
func (c Chain) with(steps ...step) Chain {
	s := make([]step, 0, len(c.steps)+len(steps))
	s = append(s, c.steps...)
	s = append(s, steps...)
	return Chain{s}
}

// Reserve indicates that the specified type will provided by the Run(...) call
// when the chain starts.  This is typically necessary to start the chain for
// a given middleware framework.  Reserve should not be exposed to users of
// sandwich since it bypasses the causal checks and risks runtime errors.
func (c Chain) Reserve(typePtr interface{}) Chain {
	typ := reflect.TypeOf(typePtr)
	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface {
		typ = typ.Elem()
	}
	return c.with(step{tRESERVE, reflect.Value{}, typ})
}

// Provide an immediate value.  This cannot be used to provide an interface,
// instead use ProvideAs(...) or With(...) with a function that returns the
// interface.
func (c Chain) Provide(value interface{}) Chain {
	if value == nil {
		panicf("Provide(nil) is not allowed -- " +
			"did you mean to use ProvideAs(val, (*IFace)(nil))?")
	}
	return c.with(step{tVALUE, reflect.ValueOf(value), reflect.TypeOf(value)})
}

// ProvideAs provides an immediate value as the specified interface type.
func (c Chain) ProvideAs(value, ifacePtr interface{}) Chain {
	val := reflect.ValueOf(value)
	typ := reflect.TypeOf(ifacePtr)
	if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Interface {
		panicf("ifacePtr must be a pointer to an interface for "+
			"ProvideAs, instead got %s", typ)
	}
	typ = typ.Elem()
	if !val.Type().Implements(typ) {
		panicf("%s doesn't implement %s", val.Type(), typ)
	}
	return c.with(step{tVALUE, val, typ})
}

// Compute what types are available from the reserved values, provide values,
// and function return values of the current handler chain.  This excludes
// error handlers and deferred handlers.
func (c Chain) typesAvailable() map[reflect.Type]bool {
	m := map[reflect.Type]bool{}
	for _, s := range c.steps {
		switch s.typ {
		case tRESERVE:
			m[s.valTyp] = true
		case tVALUE:
			m[s.val.Type()] = true
			m[s.valTyp] = true
		case tPRE_HANDLER:
			for i := 0; i < s.valTyp.NumOut(); i++ {
				m[s.valTyp.Out(i)] = true
			}
		case tPOST_HANDLER, tERROR_HANDLER:
			// ignored, we don't allow any return values for these.
		}
	}
	return m
}

// With adds one or more handlers to the middleware chain.
func (c Chain) With(handlers ...interface{}) Chain {
	steps := make([]step, len(handlers))
	available := c.typesAvailable()
	for i, handler := range handlers {
		fn, err := valueOfFunction(handler)
		if err != nil {
			panicf("%s arg of With(...) %v", ordinalize(i+1), err)
		}
		if err := checkCanCall(available, fn); err != nil {
			panicf("%s arg of With(...) %v", ordinalize(i+1), err)
		}
		fnType := fn.Func.Type()
		steps[i] = step{tPRE_HANDLER, fn.Func, fnType}
		for i := 0; i < fnType.NumOut(); i++ {
			available[fnType.Out(i)] = true
		}
	}
	return c.with(steps...)
}

// OnErr registers an error handler to be called for failures of subsequent
// handlers.
func (c Chain) OnErr(errorHandler interface{}) Chain {
	fn, err := valueOfFunction(errorHandler)
	if err != nil {
		panicf("Error handler %v", err)
	}
	available := c.typesAvailable()
	available[errorType] = true // Set internally by chain.
	if err := checkCanCall(available, fn); err != nil {
		panicf("Error handler %v", err)
	}
	if fn.Func.Type().NumOut() > 0 {
		panicf("Error handler %s may not have any return values, signature is %s",
			fn.Name, fn.Func.Type())
	}
	return c.with(step{tERROR_HANDLER, fn.Func, fn.Func.Type()})
}

// Defer adds a deferred handler to be executed after all normal handlers and
// error handlers have been called.  Deferred handlers are executed in reverse
// order that they were registered (most recent first).  Deferred handlers can
// accept the error type even if it hasn't been explicitly provided yet.  If no
// error has occurred, it will be nil.
func (c Chain) Defer(handler interface{}) Chain {
	fn, err := valueOfFunction(handler)
	if err != nil {
		panicf("Defer(...) arg %v", err)
	}
	available := c.typesAvailable()
	available[errorType] = true // Set internally by chain.
	if err := checkCanCall(available, fn); err != nil {
		panicf("Defer(...) arg %v", err)
	}
	if fn.Func.Type().NumOut() > 0 {
		panicf("Defer'd handler %s may not have any return values, signature is %s",
			fn.Name, fn.Func.Type())
	}
	return c.with(step{tPOST_HANDLER, fn.Func, fn.Func.Type()})
}

// Run executes the middleware chain using the specified values as initial
// values for all reserved types. All reserved types must be specified, and no
// non-reserved types may be provided here.
func (c Chain) Run(reservedValues ...interface{}) error {
	data := map[reflect.Type]reflect.Value{}
	postSteps := []step{} // collect post steps here
	errHandler := step{   // Initialize using the default error handler.
		tERROR_HANDLER,
		reflect.ValueOf(DefaultErrorHandler),
		reflect.TypeOf(DefaultErrorHandler),
	}
	stack := []step{}

	// 1: Apply all of the reserved values.  Make sure that the reserved values
	// match the reserve calls, because otherwise they will be ignored!

	// Apply all of the provided reserved values.
	rvMap := map[reflect.Type]bool{}
	for i, val := range reservedValues {
		if val == nil {
			return fmt.Errorf("reserved value may not be <nil> (%s arg of Run(...))",
				ordinalize(i+1))
		}
		rv := reflect.ValueOf(val)
		rvt := rv.Type()
		if rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Interface {
			rv = rv.Elem()
			rvt = rv.Type()
		}
		data[rv.Type()] = rv
		data[rvt] = rv
		rvMap[rvt] = true
	}

	// Ensure that all of the reserved values have been provided
	for _, step := range c.steps {
		if step.typ == tRESERVE {
			if _, provided := data[step.valTyp]; !provided {
				providedReservedValues := make([]string, len(reservedValues))
				for i, val := range reservedValues {
					providedReservedValues[i] = reflect.TypeOf(val).String()
				}
				return fmt.Errorf("Cannot run chain, type %s was reserved "+
					"but no initial value was provided.  Provided types: %s",
					step.valTyp, providedReservedValues)
			}
			delete(rvMap, step.valTyp)
		}
	}

	// Make sure that no non-reserved types have bene provided.
	if len(rvMap) != 0 {
		var extra []string
		for t := range rvMap {
			extra = append(extra, t.String())
		}
		sort.Strings(extra)
		return fmt.Errorf("Run(...) was called with additional types that were "+
			"not reserved: %s", extra)
	}

	// Start executing handlers.  First pass through is the normal call chain,
	// so we skip execution of error handlers and deferred handlers, although
	// we keep track of them.
execution:
	for _, step := range c.steps {
		switch step.typ {
		case tRESERVE:
			// ignored now, already handled during initialization above.
		case tVALUE:
			data[step.val.Type()] = step.val
			data[step.valTyp] = step.val
		case tPRE_HANDLER:
			c.call(step, data, &stack)
			// Check to see if there's an error.  If so, abort the chain.
			if errorVal := data[errorType]; errorVal.IsValid() && !errorVal.IsNil() {
				break execution
			}
		case tPOST_HANDLER:
			postSteps = append(postSteps, step)
		case tERROR_HANDLER:
			errHandler = step
		}
	}

	// Execute the error handler if there is any error.
	if errorVal := data[errorType]; errorVal.IsValid() && !errorVal.IsNil() {
		c.call(errHandler, data, &stack)
	} else {
		data[errorType] = reflect.Zero(errorType)
	}

	// Finally, call any deferred functions that we've gotten to.
	for i := len(postSteps) - 1; i >= 0; i-- {
		c.call(postSteps[i], data, &stack)
	}

	return nil
}

func (c Chain) call(s step, data map[reflect.Type]reflect.Value, stack *[]step) {
	t := s.valTyp
	in := make([]reflect.Value, t.NumIn())
	for i := range in {
		in[i] = data[t.In(i)]
		// This isn't supposed to happen if we've done all our checks right.
		if !in[i].IsValid() {
			name := runtime.FuncForPC(s.val.Pointer()).Name()
			panicf("Cannot inject %s arg of type %s into %s (%s).  Data: %v",
				ordinalize(i+1), t.In(i), name, t, data)
		}
	}
	defer func() {
		if err := c.wrapPanic(recover(), *stack); err != nil {
			data[errorType] = reflect.ValueOf((*error)(&err)).Elem()
		}
	}()
	*stack = append(*stack, s)
	out := s.val.Call(in)
	for _, val := range out {
		data[val.Type()] = val
	}
}

func (c Chain) wrapPanic(x interface{}, steps []step) error {
	if x == nil {
		return nil
	}
	var stack [8192]byte
	n := runtime.Stack(stack[:], false)

	N := len(steps)
	mwStack := make([]FuncInfo, N)
	for i := range steps {
		step := steps[N-i-1]
		info := runtime.FuncForPC(step.val.Pointer())
		file, line := info.FileLine(step.val.Pointer())
		mwStack[i] = FuncInfo{info.Name(), file, line, step.val}
	}

	return PanicError{
		Val:             x,
		RawStack:        string(stack[:n]),
		MiddlewareStack: mwStack,
	}
}

// PanicError is the error that is returned if a handler panics.  It includes
// the panic'd value (Val), the raw Go stack trace (RawStack), and the
// middleware execution history (MiddlewareStack) that shows what middleware
// functions have already been called.
type PanicError struct {
	Val             interface{}
	RawStack        string
	MiddlewareStack []FuncInfo
}

// FuncInfo describes a registered middleware function.
type FuncInfo struct {
	Name string // fully-qualified name, e.g.: github.com/foo/bar.FuncName
	File string
	Line int
	Func reflect.Value
}

// FilteredStack returns the stack trace without some internal chain.* functions
// and without reflect.Value.call stack frames, since these are generally just
// noise.  The reflect.Value.call removal could affect user stack frames.
//
// TODO(aroman): Refine filtering so that it only removes reflect.Value.call
// frames due to sandwich.
func (p PanicError) FilteredStack() []string {
	lines := strings.Split(p.RawStack, "\n")
	var filtered []string
	for i := 0; i < len(lines); i++ {
		line := lines[i]
		if strings.HasPrefix(line, "github.com/augustoroman/sandwich/chain") &&
			!strings.HasPrefix(line, "github.com/augustoroman/sandwich/chain.Chain.Run(") {
			i++
			continue
		}
		if strings.HasPrefix(line, "reflect.Value.call") || strings.HasPrefix(line, "reflect.Value.Call") {
			i++
			continue
		}
		filtered = append(filtered, line)
	}
	return filtered
}

func (p PanicError) Error() string {
	var mwStack bytes.Buffer
	w := tabwriter.NewWriter(&mwStack, 5, 7, 2, ' ', 0)
	for _, fn := range p.MiddlewareStack {
		fmt.Fprintf(w, "    %s\t%s\n", fn.Name, fn.Func.Type())
	}
	w.Flush()
	return fmt.Sprintf(
		"Panic executing middleware %s: %v\n"+
			"  Middleware executed:\n%s"+
			"  Filtered call stack:\n    %s",
		p.MiddlewareStack[0].Name, p.Val,
		mwStack.String(),
		strings.Join(p.FilteredStack(), "\n    "))
}
<|endoftext|>


<commit_before>package core

import (
	"errors"
	"strings"

	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	merkledag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"
)

// ErrNoNamesys is an explicit error for when an IPFS node doesn't
// (yet) have a name system
var ErrNoNamesys = errors.New(
	"core/resolve: no Namesys on IpfsNode - can't resolve ipns entry")

// Resolve resolves the given path by parsing out protocol-specific
// entries (e.g. /ipns/<node-key>) and then going through the /ipfs/
// entries and returning the final merkledage node.  Effectively
// enables /ipns/, /dns/, etc. in commands.
func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) {
	if strings.HasPrefix(p.String(), "/ipns/") {
		// resolve ipns paths

		// TODO(cryptix): we sould be able to query the local cache for the path
		if n.Namesys == nil {
			return nil, ErrNoNamesys
		}

		seg := p.Segments()

		if len(seg) < 2 || seg[1] == "" { // just "/<protocol/>" without further segments
			return nil, path.ErrNoComponents
		}

		extensions := seg[2:]
		resolvable, err := path.FromSegments("/", seg[0], seg[1])
		if err != nil {
			return nil, err
		}

		respath, err := n.Namesys.Resolve(ctx, resolvable.String())
		if err != nil {
			return nil, err
		}

		segments := append(respath.Segments(), extensions...)
		p, err = path.FromSegments("/", segments...)
		if err != nil {
			return nil, err
		}
	}

	// ok, we have an ipfs path now (or what we'll treat as one)
	return n.Resolver.ResolvePath(ctx, p)
}
<commit_msg>Fix typo<commit_after>package core

import (
	"errors"
	"strings"

	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	merkledag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"
)

// ErrNoNamesys is an explicit error for when an IPFS node doesn't
// (yet) have a name system
var ErrNoNamesys = errors.New(
	"core/resolve: no Namesys on IpfsNode - can't resolve ipns entry")

// Resolve resolves the given path by parsing out protocol-specific
// entries (e.g. /ipns/<node-key>) and then going through the /ipfs/
// entries and returning the final merkledag node.  Effectively
// enables /ipns/, /dns/, etc. in commands.
func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) {
	if strings.HasPrefix(p.String(), "/ipns/") {
		// resolve ipns paths

		// TODO(cryptix): we sould be able to query the local cache for the path
		if n.Namesys == nil {
			return nil, ErrNoNamesys
		}

		seg := p.Segments()

		if len(seg) < 2 || seg[1] == "" { // just "/<protocol/>" without further segments
			return nil, path.ErrNoComponents
		}

		extensions := seg[2:]
		resolvable, err := path.FromSegments("/", seg[0], seg[1])
		if err != nil {
			return nil, err
		}

		respath, err := n.Namesys.Resolve(ctx, resolvable.String())
		if err != nil {
			return nil, err
		}

		segments := append(respath.Segments(), extensions...)
		p, err = path.FromSegments("/", segments...)
		if err != nil {
			return nil, err
		}
	}

	// ok, we have an ipfs path now (or what we'll treat as one)
	return n.Resolver.ResolvePath(ctx, p)
}
<|endoftext|>


<commit_before>package cfclient

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

type SecGroupResponse struct {
	Count     int                `json:"total_results"`
	Pages     int                `json:"total_pages"`
	NextUrl   string             `json:"next_url"`
	Resources []SecGroupResource `json:"resources"`
}

type SecGroupResource struct {
	Meta   Meta     `json:"metadata"`
	Entity SecGroup `json:"entity"`
}

type SecGroup struct {
	Guid       string          `json:"guid"`
	Name       string          `json:"name"`
	Rules      []SecGroupRule  `json:"rules"`
	Running    bool            `json:"running_default"`
	Staging    bool            `json:"staging_default"`
	SpacesURL  string          `json:"spaces_url"`
	SpacesData []SpaceResource `json:"spaces"`
	c          *Client
}

type SecGroupRule struct {
	Protocol    string `json:"protocol"`
	Ports       string `json:"ports,omitempty"`       //e.g. "4000-5000,9142"
	Destination string `json:"destination"`           //CIDR Format
	Description string `json:"description,omitempty"` //Optional description
	Code        int    `json:"code,omitempty"`        // ICMP code
	Type        int    `json:"type,omitempty"`        //ICMP type. Only valid if Protocol=="icmp"
	Log         bool   `json:"log,omitempty"`         //If true, log this rule
}

func (c *Client) ListSecGroups() (secGroups []SecGroup, err error) {
	requestURL := "/v2/security_groups?inline-relations-depth=1"
	for requestURL != "" {
		var secGroupResp SecGroupResponse
		r := c.NewRequest("GET", requestURL)
		resp, err := c.DoRequest(r)

		if err != nil {
			return nil, fmt.Errorf("Error requesting sec groups %v", err)
		}
		resBody, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Printf("Error reading sec group request %v", string(resBody))
		}

		err = json.Unmarshal(resBody, &secGroupResp)
		if err != nil {
			return nil, fmt.Errorf("Error unmarshaling sec group %v", err)
		}

		for _, secGroup := range secGroupResp.Resources {
			secGroup.Entity.Guid = secGroup.Meta.Guid
			secGroup.Entity.c = c
			for i, space := range secGroup.Entity.SpacesData {
				space.Entity.Guid = space.Meta.Guid
				secGroup.Entity.SpacesData[i] = space
			}
			if len(secGroup.Entity.SpacesData) == 0 {
				spaces, err := secGroup.Entity.ListSpaceResources()
				if err != nil {
					return nil, err
				}
				for _, space := range spaces {
					secGroup.Entity.SpacesData = append(secGroup.Entity.SpacesData, space)
				}
			}
			secGroups = append(secGroups, secGroup.Entity)
		}

		requestURL = secGroupResp.NextUrl
		resp.Body.Close()
	}
	return secGroups, nil
}

func (c *Client) GetSecGroupByName(name string) (secGroup SecGroup, err error) {
	requestURL := "/v2/security_groups?q=name:" + name
	var secGroupResp SecGroupResponse
	r := c.NewRequest("GET", requestURL)
	resp, err := c.DoRequest(r)

	if err != nil {
		return secGroup, fmt.Errorf("Error requesting sec groups %v", err)
	}
	resBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error reading sec group request %v", string(resBody))
	}

	err = json.Unmarshal(resBody, &secGroupResp)
	if err != nil {
		return secGroup, fmt.Errorf("Error unmarshaling sec group %v", err)
	}
	if len(secGroupResp.Resources) == 0 {
		return secGroup, fmt.Errorf("No security group with name %v found", name)
	}
	secGroup = secGroupResp.Resources[0].Entity
	secGroup.Guid = secGroupResp.Resources[0].Meta.Guid
	secGroup.c = c

	resp.Body.Close()
	return secGroup, nil
}

func (secGroup *SecGroup) ListSpaceResources() ([]SpaceResource, error) {
	var spaceResources []SpaceResource
	requestURL := secGroup.SpacesURL
	for requestURL != "" {
		spaceResp, err := secGroup.c.getSpaceResponse(requestURL)
		if err != nil {
			return []SpaceResource{}, err
		}
		for i, spaceRes := range spaceResp.Resources {
			spaceRes.Entity.Guid = spaceRes.Meta.Guid
			spaceResp.Resources[i] = spaceRes
		}
		spaceResources = append(spaceResources, spaceResp.Resources...)
		requestURL = spaceResp.NextUrl
	}
	return spaceResources, nil
}

/*
CreateSecGroup contacts the CF endpoint for creating a new security group.
name: the name to give to the created security group
rules: A slice of rule objects that describe the rules that this security group enforces.
	This can technically be nil or an empty slice - we won't judge you
spaceGuids: The security group will be associated with the spaces specified by the contents of this slice.
	If nil, the security group will not be associated with any spaces initially.
*/
func (c *Client) CreateSecGroup(name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	return c.secGroupCreateHelper("/v2/security_groups", "POST", name, rules, spaceGuids)
}

/*
UpdateSecGroup contacts the CF endpoint to update an existing security group.
guid: identifies the security group that you would like to update.
name: the new name to give to the security group
rules: A slice of rule objects that describe the rules that this security group enforces.
	If this is left nil, the rules will not be changed.
spaceGuids: The security group will be associated with the spaces specified by the contents of this slice.
	If nil, the space associations will not be changed.
*/
func (c *Client) UpdateSecGroup(guid, name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	return c.secGroupCreateHelper("/v2/security_groups/"+guid, "PUT", name, rules, spaceGuids)
}

/*
DeleteSecGroup contacts the CF endpoint to delete an existing security group.
guid: Indentifies the security group to be deleted.
*/
func (c *Client) DeleteSecGroup(guid string) error {
	//Perform the DELETE and check for errors
	resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/security_groups/%s", guid)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 { //204 No Content
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
GetSecGroup contacts the CF endpoint for fetching the info for a particular security group.
guid: Identifies the security group to fetch information from
*/
func (c *Client) GetSecGroup(guid string) (*SecGroup, error) {
	//Perform the GET and check for errors
	resp, err := c.DoRequest(c.NewRequest("GET", "/v2/security_groups/"+guid))
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	//get the json out of the response body
	return respBodyToSecGroup(resp.Body, c)
}

/*
BindSecGroup contacts the CF endpoint to associate a space with a security group
secGUID: identifies the security group to add a space to
spaceGUID: identifies the space to associate
*/
func (c *Client) BindSecGroup(secGUID, spaceGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/security_groups/%s/spaces/%s", secGUID, spaceGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 201 { //201 Created
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
BindRunningSecGroup contacts the CF endpoint to associate  a security group
secGUID: identifies the security group to add a space to
*/
func (c *Client) BindRunningSecGroup(secGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/config/running_security_groups/%s", secGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 { //200
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
BindStagingSecGroup contacts the CF endpoint to associate a space with a security group
secGUID: identifies the security group to add a space to
*/
func (c *Client) BindStagingSecGroup(secGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/config/staging_security_groups/%s", secGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 { //200
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
UnbindSecGroup contacts the CF endpoint to dissociate a space from a security group
secGUID: identifies the security group to remove a space from
spaceGUID: identifies the space to dissociate from the security group
*/
func (c *Client) UnbindSecGroup(secGUID, spaceGUID string) error {
	//Perform the DELETE and check for errors
	resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/security_groups/%s/spaces/%s", secGUID, spaceGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 { //204 No Content
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

//Reads most security group response bodies into a SecGroup object
func respBodyToSecGroup(body io.ReadCloser, c *Client) (*SecGroup, error) {
	//get the json from the response body
	bodyRaw, err := ioutil.ReadAll(body)
	if err != nil {
		return nil, fmt.Errorf("Could not read response body: %s", err.Error())
	}
	jStruct := SecGroupResource{}
	//make it a SecGroup
	err = json.Unmarshal([]byte(bodyRaw), &jStruct)
	if err != nil {
		return nil, fmt.Errorf(`Could not unmarshal response body as json.
		body: %s
		error: %s`, bodyRaw, err.Error())
	}
	//pull a few extra fields from other places
	ret := jStruct.Entity
	ret.Guid = jStruct.Meta.Guid
	ret.c = c
	return &ret, nil
}

//Create and Update secGroup pretty much do the same thing, so this function abstracts those out.
func (c *Client) secGroupCreateHelper(url, method, name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	req := c.NewRequest(method, url)
	//set up request body
	req.obj = map[string]interface{}{
		"name":        name,
		"rules":       rules,
		"space_guids": spaceGuids,
	}
	//fire off the request and check for problems
	resp, err := c.DoRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 201 { // Both create and update should give 201 CREATED
		return nil, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	//get the json from the response body
	return respBodyToSecGroup(resp.Body, c)
}
<commit_msg>Added some better error output around creating/updating security groups (#75)<commit_after>package cfclient

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

type SecGroupResponse struct {
	Count     int                `json:"total_results"`
	Pages     int                `json:"total_pages"`
	NextUrl   string             `json:"next_url"`
	Resources []SecGroupResource `json:"resources"`
}

type SecGroupCreateResponse struct {
	Code        int    `json:"code"`
	ErrorCode   string `json:"error_code"`
	Description string `json:"description"`
}

type SecGroupResource struct {
	Meta   Meta     `json:"metadata"`
	Entity SecGroup `json:"entity"`
}

type SecGroup struct {
	Guid       string          `json:"guid"`
	Name       string          `json:"name"`
	Rules      []SecGroupRule  `json:"rules"`
	Running    bool            `json:"running_default"`
	Staging    bool            `json:"staging_default"`
	SpacesURL  string          `json:"spaces_url"`
	SpacesData []SpaceResource `json:"spaces"`
	c          *Client
}

type SecGroupRule struct {
	Protocol    string `json:"protocol"`
	Ports       string `json:"ports,omitempty"`       //e.g. "4000-5000,9142"
	Destination string `json:"destination"`           //CIDR Format
	Description string `json:"description,omitempty"` //Optional description
	Code        int    `json:"code,omitempty"`        // ICMP code
	Type        int    `json:"type,omitempty"`        //ICMP type. Only valid if Protocol=="icmp"
	Log         bool   `json:"log,omitempty"`         //If true, log this rule
}

func (c *Client) ListSecGroups() (secGroups []SecGroup, err error) {
	requestURL := "/v2/security_groups?inline-relations-depth=1"
	for requestURL != "" {
		var secGroupResp SecGroupResponse
		r := c.NewRequest("GET", requestURL)
		resp, err := c.DoRequest(r)

		if err != nil {
			return nil, fmt.Errorf("Error requesting sec groups %v", err)
		}
		resBody, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Printf("Error reading sec group request %v", string(resBody))
		}

		err = json.Unmarshal(resBody, &secGroupResp)
		if err != nil {
			return nil, fmt.Errorf("Error unmarshaling sec group %v", err)
		}

		for _, secGroup := range secGroupResp.Resources {
			secGroup.Entity.Guid = secGroup.Meta.Guid
			secGroup.Entity.c = c
			for i, space := range secGroup.Entity.SpacesData {
				space.Entity.Guid = space.Meta.Guid
				secGroup.Entity.SpacesData[i] = space
			}
			if len(secGroup.Entity.SpacesData) == 0 {
				spaces, err := secGroup.Entity.ListSpaceResources()
				if err != nil {
					return nil, err
				}
				for _, space := range spaces {
					secGroup.Entity.SpacesData = append(secGroup.Entity.SpacesData, space)
				}
			}
			secGroups = append(secGroups, secGroup.Entity)
		}

		requestURL = secGroupResp.NextUrl
		resp.Body.Close()
	}
	return secGroups, nil
}

func (c *Client) GetSecGroupByName(name string) (secGroup SecGroup, err error) {
	requestURL := "/v2/security_groups?q=name:" + name
	var secGroupResp SecGroupResponse
	r := c.NewRequest("GET", requestURL)
	resp, err := c.DoRequest(r)

	if err != nil {
		return secGroup, fmt.Errorf("Error requesting sec groups %v", err)
	}
	resBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error reading sec group request %v", string(resBody))
	}

	err = json.Unmarshal(resBody, &secGroupResp)
	if err != nil {
		return secGroup, fmt.Errorf("Error unmarshaling sec group %v", err)
	}
	if len(secGroupResp.Resources) == 0 {
		return secGroup, fmt.Errorf("No security group with name %v found", name)
	}
	secGroup = secGroupResp.Resources[0].Entity
	secGroup.Guid = secGroupResp.Resources[0].Meta.Guid
	secGroup.c = c

	resp.Body.Close()
	return secGroup, nil
}

func (secGroup *SecGroup) ListSpaceResources() ([]SpaceResource, error) {
	var spaceResources []SpaceResource
	requestURL := secGroup.SpacesURL
	for requestURL != "" {
		spaceResp, err := secGroup.c.getSpaceResponse(requestURL)
		if err != nil {
			return []SpaceResource{}, err
		}
		for i, spaceRes := range spaceResp.Resources {
			spaceRes.Entity.Guid = spaceRes.Meta.Guid
			spaceResp.Resources[i] = spaceRes
		}
		spaceResources = append(spaceResources, spaceResp.Resources...)
		requestURL = spaceResp.NextUrl
	}
	return spaceResources, nil
}

/*
CreateSecGroup contacts the CF endpoint for creating a new security group.
name: the name to give to the created security group
rules: A slice of rule objects that describe the rules that this security group enforces.
	This can technically be nil or an empty slice - we won't judge you
spaceGuids: The security group will be associated with the spaces specified by the contents of this slice.
	If nil, the security group will not be associated with any spaces initially.
*/
func (c *Client) CreateSecGroup(name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	return c.secGroupCreateHelper("/v2/security_groups", "POST", name, rules, spaceGuids)
}

/*
UpdateSecGroup contacts the CF endpoint to update an existing security group.
guid: identifies the security group that you would like to update.
name: the new name to give to the security group
rules: A slice of rule objects that describe the rules that this security group enforces.
	If this is left nil, the rules will not be changed.
spaceGuids: The security group will be associated with the spaces specified by the contents of this slice.
	If nil, the space associations will not be changed.
*/
func (c *Client) UpdateSecGroup(guid, name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	return c.secGroupCreateHelper("/v2/security_groups/"+guid, "PUT", name, rules, spaceGuids)
}

/*
DeleteSecGroup contacts the CF endpoint to delete an existing security group.
guid: Indentifies the security group to be deleted.
*/
func (c *Client) DeleteSecGroup(guid string) error {
	//Perform the DELETE and check for errors
	resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/security_groups/%s", guid)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 { //204 No Content
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
GetSecGroup contacts the CF endpoint for fetching the info for a particular security group.
guid: Identifies the security group to fetch information from
*/
func (c *Client) GetSecGroup(guid string) (*SecGroup, error) {
	//Perform the GET and check for errors
	resp, err := c.DoRequest(c.NewRequest("GET", "/v2/security_groups/"+guid))
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	//get the json out of the response body
	return respBodyToSecGroup(resp.Body, c)
}

/*
BindSecGroup contacts the CF endpoint to associate a space with a security group
secGUID: identifies the security group to add a space to
spaceGUID: identifies the space to associate
*/
func (c *Client) BindSecGroup(secGUID, spaceGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/security_groups/%s/spaces/%s", secGUID, spaceGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 201 { //201 Created
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
BindRunningSecGroup contacts the CF endpoint to associate  a security group
secGUID: identifies the security group to add a space to
*/
func (c *Client) BindRunningSecGroup(secGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/config/running_security_groups/%s", secGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 { //200
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
BindStagingSecGroup contacts the CF endpoint to associate a space with a security group
secGUID: identifies the security group to add a space to
*/
func (c *Client) BindStagingSecGroup(secGUID string) error {
	//Perform the PUT and check for errors
	resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/config/staging_security_groups/%s", secGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 { //200
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

/*
UnbindSecGroup contacts the CF endpoint to dissociate a space from a security group
secGUID: identifies the security group to remove a space from
spaceGUID: identifies the space to dissociate from the security group
*/
func (c *Client) UnbindSecGroup(secGUID, spaceGUID string) error {
	//Perform the DELETE and check for errors
	resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/security_groups/%s/spaces/%s", secGUID, spaceGUID)))
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 { //204 No Content
		return fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
	}
	return nil
}

//Reads most security group response bodies into a SecGroup object
func respBodyToSecGroup(body io.ReadCloser, c *Client) (*SecGroup, error) {
	//get the json from the response body
	bodyRaw, err := ioutil.ReadAll(body)
	if err != nil {
		return nil, fmt.Errorf("Could not read response body: %s", err.Error())
	}
	jStruct := SecGroupResource{}
	//make it a SecGroup
	err = json.Unmarshal([]byte(bodyRaw), &jStruct)
	if err != nil {
		return nil, fmt.Errorf(`Could not unmarshal response body as json.
		body: %s
		error: %s`, bodyRaw, err.Error())
	}
	//pull a few extra fields from other places
	ret := jStruct.Entity
	ret.Guid = jStruct.Meta.Guid
	ret.c = c
	return &ret, nil
}

//Create and Update secGroup pretty much do the same thing, so this function abstracts those out.
func (c *Client) secGroupCreateHelper(url, method, name string, rules []SecGroupRule, spaceGuids []string) (*SecGroup, error) {
	req := c.NewRequest(method, url)
	//set up request body
	req.obj = map[string]interface{}{
		"name":        name,
		"rules":       rules,
		"space_guids": spaceGuids,
	}
	//fire off the request and check for problems
	resp, err := c.DoRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 201 { // Both create and update should give 201 CREATED
		var response SecGroupCreateResponse

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

		err = json.Unmarshal(bodyRaw, &response)
		if err != nil {
			return nil, fmt.Errorf("Error unmarshaling response %v", err)
		}

		return nil, fmt.Errorf(`Request failed CF API returned with status code %d
-------------------------------
Error Code  %s
Code        %d
Description %s`,
			resp.StatusCode, response.ErrorCode, response.Code, response.Description)
	}
	//get the json from the response body
	return respBodyToSecGroup(resp.Body, c)
}
<|endoftext|>


<commit_before>package level_test

import (
	"bytes"
	"errors"
	"io"
	"strings"
	"testing"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
)

func TestVariousLevels(t *testing.T) {
	testCases := []struct {
		name    string
		allowed level.Option
		want    string
	}{
		{
			"AllowAll",
			level.AllowAll(),
			strings.Join([]string{
				`{"level":"debug","this is":"debug log"}`,
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowDebug",
			level.AllowDebug(),
			strings.Join([]string{
				`{"level":"debug","this is":"debug log"}`,
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowDebug",
			level.AllowInfo(),
			strings.Join([]string{
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowWarn",
			level.AllowWarn(),
			strings.Join([]string{
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowError",
			level.AllowError(),
			strings.Join([]string{
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowNone",
			level.AllowNone(),
			``,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			var buf bytes.Buffer
			logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed)

			level.Debug(logger).Log("this is", "debug log")
			level.Info(logger).Log("this is", "info log")
			level.Warn(logger).Log("this is", "warn log")
			level.Error(logger).Log("this is", "error log")

			if want, have := tc.want, strings.TrimSpace(buf.String()); want != have {
				t.Errorf("\nwant:\n%s\nhave:\n%s", want, have)
			}
		})
	}
}

func TestErrNotAllowed(t *testing.T) {
	myError := errors.New("squelched!")
	opts := []level.Option{
		level.AllowWarn(),
		level.ErrNotAllowed(myError),
	}
	logger := level.NewFilter(log.NewNopLogger(), opts...)

	if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have {
		t.Errorf("want %#+v, have %#+v", want, have)
	}

	if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have {
		t.Errorf("want %#+v, have %#+v", want, have)
	}
}

func TestErrNoLevel(t *testing.T) {
	myError := errors.New("no level specified")

	var buf bytes.Buffer
	opts := []level.Option{
		level.SquelchNoLevel(true),
		level.ErrNoLevel(myError),
	}
	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)

	if want, have := myError, logger.Log("foo", "bar"); want != have {
		t.Errorf("want %v, have %v", want, have)
	}
	if want, have := ``, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestAllowNoLevel(t *testing.T) {
	var buf bytes.Buffer
	opts := []level.Option{
		level.SquelchNoLevel(false),
		level.ErrNoLevel(errors.New("I should never be returned!")),
	}
	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)

	if want, have := error(nil), logger.Log("foo", "bar"); want != have {
		t.Errorf("want %v, have %v", want, have)
	}
	if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestLevelContext(t *testing.T) {
	var buf bytes.Buffer

	// Wrapping the level logger with a context allows users to use
	// log.DefaultCaller as per normal.
	var logger log.Logger
	logger = log.NewLogfmtLogger(&buf)
	logger = level.NewFilter(logger, level.AllowAll())
	logger = log.With(logger, "caller", log.DefaultCaller)

	level.Info(logger).Log("foo", "bar")
	if want, have := `level=info caller=level_test.go:149 foo=bar`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestContextLevel(t *testing.T) {
	var buf bytes.Buffer

	// Wrapping a context with the level logger still works, but requires users
	// to specify a higher callstack depth value.
	var logger log.Logger
	logger = log.NewLogfmtLogger(&buf)
	logger = log.With(logger, "caller", log.Caller(5))
	logger = level.NewFilter(logger, level.AllowAll())

	level.Info(logger).Log("foo", "bar")
	if want, have := `caller=level_test.go:165 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestLevelFormatting(t *testing.T) {
	testCases := []struct {
		name   string
		format func(io.Writer) log.Logger
		output string
	}{
		{
			name:   "logfmt",
			format: log.NewLogfmtLogger,
			output: `level=info foo=bar`,
		},
		{
			name:   "JSON",
			format: log.NewJSONLogger,
			output: `{"foo":"bar","level":"info"}`,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			var buf bytes.Buffer

			logger := tc.format(&buf)
			level.Info(logger).Log("foo", "bar")
			if want, have := tc.output, strings.TrimSpace(buf.String()); want != have {
				t.Errorf("\nwant: '%s'\nhave '%s'", want, have)
			}
		})
	}
}

func TestInjector(t *testing.T) {
	var (
		output []interface{}
		logger log.Logger
	)

	logger = log.LoggerFunc(func(keyvals ...interface{}) error {
		output = keyvals
		return nil
	})
	logger = level.NewInjector(logger, level.InfoValue())

	logger.Log("foo", "bar")
	if got, want := len(output), 4; got != want {
		t.Errorf("missing level not injected: got len==%d, want len==%d", got, want)
	}
	if got, want := output[0], level.Key(); got != want {
		t.Errorf("wrong level key: got %#v, want %#v", got, want)
	}
	if got, want := output[1], level.InfoValue(); got != want {
		t.Errorf("wrong level value: got %#v, want %#v", got, want)
	}

	level.Error(logger).Log("foo", "bar")
	if got, want := len(output), 4; got != want {
		t.Errorf("leveled record modified: got len==%d, want len==%d", got, want)
	}
	if got, want := output[0], level.Key(); got != want {
		t.Errorf("wrong level key: got %#v, want %#v", got, want)
	}
	if got, want := output[1], level.ErrorValue(); got != want {
		t.Errorf("wrong level value: got %#v, want %#v", got, want)
	}
}
<commit_msg>Type in level test cases<commit_after>package level_test

import (
	"bytes"
	"errors"
	"io"
	"strings"
	"testing"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
)

func TestVariousLevels(t *testing.T) {
	testCases := []struct {
		name    string
		allowed level.Option
		want    string
	}{
		{
			"AllowAll",
			level.AllowAll(),
			strings.Join([]string{
				`{"level":"debug","this is":"debug log"}`,
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowDebug",
			level.AllowDebug(),
			strings.Join([]string{
				`{"level":"debug","this is":"debug log"}`,
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowInfo",
			level.AllowInfo(),
			strings.Join([]string{
				`{"level":"info","this is":"info log"}`,
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowWarn",
			level.AllowWarn(),
			strings.Join([]string{
				`{"level":"warn","this is":"warn log"}`,
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowError",
			level.AllowError(),
			strings.Join([]string{
				`{"level":"error","this is":"error log"}`,
			}, "\n"),
		},
		{
			"AllowNone",
			level.AllowNone(),
			``,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			var buf bytes.Buffer
			logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed)

			level.Debug(logger).Log("this is", "debug log")
			level.Info(logger).Log("this is", "info log")
			level.Warn(logger).Log("this is", "warn log")
			level.Error(logger).Log("this is", "error log")

			if want, have := tc.want, strings.TrimSpace(buf.String()); want != have {
				t.Errorf("\nwant:\n%s\nhave:\n%s", want, have)
			}
		})
	}
}

func TestErrNotAllowed(t *testing.T) {
	myError := errors.New("squelched!")
	opts := []level.Option{
		level.AllowWarn(),
		level.ErrNotAllowed(myError),
	}
	logger := level.NewFilter(log.NewNopLogger(), opts...)

	if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have {
		t.Errorf("want %#+v, have %#+v", want, have)
	}

	if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have {
		t.Errorf("want %#+v, have %#+v", want, have)
	}
}

func TestErrNoLevel(t *testing.T) {
	myError := errors.New("no level specified")

	var buf bytes.Buffer
	opts := []level.Option{
		level.SquelchNoLevel(true),
		level.ErrNoLevel(myError),
	}
	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)

	if want, have := myError, logger.Log("foo", "bar"); want != have {
		t.Errorf("want %v, have %v", want, have)
	}
	if want, have := ``, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestAllowNoLevel(t *testing.T) {
	var buf bytes.Buffer
	opts := []level.Option{
		level.SquelchNoLevel(false),
		level.ErrNoLevel(errors.New("I should never be returned!")),
	}
	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)

	if want, have := error(nil), logger.Log("foo", "bar"); want != have {
		t.Errorf("want %v, have %v", want, have)
	}
	if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestLevelContext(t *testing.T) {
	var buf bytes.Buffer

	// Wrapping the level logger with a context allows users to use
	// log.DefaultCaller as per normal.
	var logger log.Logger
	logger = log.NewLogfmtLogger(&buf)
	logger = level.NewFilter(logger, level.AllowAll())
	logger = log.With(logger, "caller", log.DefaultCaller)

	level.Info(logger).Log("foo", "bar")
	if want, have := `level=info caller=level_test.go:149 foo=bar`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestContextLevel(t *testing.T) {
	var buf bytes.Buffer

	// Wrapping a context with the level logger still works, but requires users
	// to specify a higher callstack depth value.
	var logger log.Logger
	logger = log.NewLogfmtLogger(&buf)
	logger = log.With(logger, "caller", log.Caller(5))
	logger = level.NewFilter(logger, level.AllowAll())

	level.Info(logger).Log("foo", "bar")
	if want, have := `caller=level_test.go:165 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have {
		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
	}
}

func TestLevelFormatting(t *testing.T) {
	testCases := []struct {
		name   string
		format func(io.Writer) log.Logger
		output string
	}{
		{
			name:   "logfmt",
			format: log.NewLogfmtLogger,
			output: `level=info foo=bar`,
		},
		{
			name:   "JSON",
			format: log.NewJSONLogger,
			output: `{"foo":"bar","level":"info"}`,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			var buf bytes.Buffer

			logger := tc.format(&buf)
			level.Info(logger).Log("foo", "bar")
			if want, have := tc.output, strings.TrimSpace(buf.String()); want != have {
				t.Errorf("\nwant: '%s'\nhave '%s'", want, have)
			}
		})
	}
}

func TestInjector(t *testing.T) {
	var (
		output []interface{}
		logger log.Logger
	)

	logger = log.LoggerFunc(func(keyvals ...interface{}) error {
		output = keyvals
		return nil
	})
	logger = level.NewInjector(logger, level.InfoValue())

	logger.Log("foo", "bar")
	if got, want := len(output), 4; got != want {
		t.Errorf("missing level not injected: got len==%d, want len==%d", got, want)
	}
	if got, want := output[0], level.Key(); got != want {
		t.Errorf("wrong level key: got %#v, want %#v", got, want)
	}
	if got, want := output[1], level.InfoValue(); got != want {
		t.Errorf("wrong level value: got %#v, want %#v", got, want)
	}

	level.Error(logger).Log("foo", "bar")
	if got, want := len(output), 4; got != want {
		t.Errorf("leveled record modified: got len==%d, want len==%d", got, want)
	}
	if got, want := output[0], level.Key(); got != want {
		t.Errorf("wrong level key: got %#v, want %#v", got, want)
	}
	if got, want := output[1], level.ErrorValue(); got != want {
		t.Errorf("wrong level value: got %#v, want %#v", got, want)
	}
}
<|endoftext|>


<commit_before>package logging

var log = Init()
var olog = New("subsystem #42", LevelNotice)

func Example() {
	log.Notice("Hello, world.")
	log.Warning("this program is about to end")

	olog.Print("now online")
	Suppress("olog")
	olog.Print("extraneous information")

	Enable("olog")
	olog.Print("relevant now")

	SuppressAll()
	log.Alert("screaming into the void")
	olog.Critical("can anyone hear me?")

	log.Enable()
	log.Notice("i'm baaack")
	log.Suppress()
	log.Warning("but not for long")

	EnableAll()
	log.Notice("fare thee well")
	olog.Print("all good journeys must come to an end")
}
<commit_msg>Example is better.<commit_after>package logging_test

import "github.com/kisom/goutils/logging"

var log = logging.Init()
var olog = logging.New("subsystem #42", logging.LevelNotice)

func Example() {
	log.Notice("Hello, world.")
	log.Warning("this program is about to end")

	olog.Print("now online")
	logging.Suppress("olog")
	olog.Print("extraneous information")

	logging.Enable("olog")
	olog.Print("relevant now")

	logging.SuppressAll()
	log.Alert("screaming into the void")
	olog.Critical("can anyone hear me?")

	log.Enable()
	log.Notice("i'm baaack")
	log.Suppress()
	log.Warning("but not for long")

	logging.EnableAll()
	log.Notice("fare thee well")
	olog.Print("all good journeys must come to an end")
}
<|endoftext|>


<commit_before>//go:build linux && cgo
// +build linux,cgo

package endpoints

import (
	"fmt"
	"net"
	"os"
	"os/user"
	"strconv"

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

// Bind to the given unix socket path.
func socketUnixListen(path string) (net.Listener, error) {
	addr, err := net.ResolveUnixAddr("unix", path)
	if err != nil {
		return nil, fmt.Errorf("cannot resolve socket address: %v", err)
	}

	listener, err := net.ListenUnix("unix", addr)
	if err != nil {
		return nil, fmt.Errorf("cannot bind socket: %v", err)
	}

	return listener, err

}

// CheckAlreadyRunning checks if the socket at the given path is already
// bound to a running LXD process, and return an error if so.
//
// FIXME: We should probably rather just try a regular unix socket
//        connection without using the client. However this is the way
//        this logic has historically behaved, so let's keep it like it
//        was.
func CheckAlreadyRunning(path string) error {
	// If socket activated, nothing to do
	pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
	if err == nil {
		if pid == os.Getpid() {
			return nil
		}
	}

	// If there's no socket file at all, there's nothing to do.
	if !shared.PathExists(path) {
		return nil
	}

	_, err = lxd.ConnectLXDUnix(path, nil)

	// If the connection succeeded it means there's another LXD running.
	if err == nil {
		return fmt.Errorf("LXD is already running")
	}

	return nil
}

// Remove any stale socket file at the given path.
func socketUnixRemoveStale(path string) error {
	// If there's no socket file at all, there's nothing to do.
	if !shared.PathExists(path) {
		return nil
	}

	logger.Debugf("Detected stale unix socket, deleting")
	err := os.Remove(path)
	if err != nil {
		return fmt.Errorf("could not delete stale local socket: %v", err)
	}

	return nil
}

// Change the file mode of the given unix socket file,
func socketUnixSetPermissions(path string, mode os.FileMode) error {
	err := os.Chmod(path, mode)
	if err != nil {
		return fmt.Errorf("cannot set permissions on local socket: %v", err)
	}
	return nil
}

// Change the ownership of the given unix socket file,
func socketUnixSetOwnership(path string, groupName string) error {
	var gid int
	var err error

	if groupName != "" {
		g, err := user.LookupGroup(groupName)
		if err != nil {
			return fmt.Errorf("cannot get group ID of '%s': %v", groupName, err)
		}

		gid, err = strconv.Atoi(g.Gid)
		if err != nil {
			return err
		}
	} else {
		gid = os.Getgid()
	}

	err = os.Chown(path, os.Getuid(), gid)
	if err != nil {
		return fmt.Errorf("cannot change ownership on local socket: %v", err)

	}

	return nil
}
<commit_msg>lxd/endpoints: Make socketUnixListen return a UnixListener<commit_after>//go:build linux && cgo
// +build linux,cgo

package endpoints

import (
	"fmt"
	"net"
	"os"
	"os/user"
	"strconv"

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

// Bind to the given unix socket path.
func socketUnixListen(path string) (*net.UnixListener, error) {
	addr, err := net.ResolveUnixAddr("unix", path)
	if err != nil {
		return nil, fmt.Errorf("cannot resolve socket address: %v", err)
	}

	listener, err := net.ListenUnix("unix", addr)
	if err != nil {
		return nil, fmt.Errorf("cannot bind socket: %v", err)
	}

	return listener, err
}

// CheckAlreadyRunning checks if the socket at the given path is already
// bound to a running LXD process, and return an error if so.
//
// FIXME: We should probably rather just try a regular unix socket
//        connection without using the client. However this is the way
//        this logic has historically behaved, so let's keep it like it
//        was.
func CheckAlreadyRunning(path string) error {
	// If socket activated, nothing to do
	pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
	if err == nil {
		if pid == os.Getpid() {
			return nil
		}
	}

	// If there's no socket file at all, there's nothing to do.
	if !shared.PathExists(path) {
		return nil
	}

	_, err = lxd.ConnectLXDUnix(path, nil)

	// If the connection succeeded it means there's another LXD running.
	if err == nil {
		return fmt.Errorf("LXD is already running")
	}

	return nil
}

// Remove any stale socket file at the given path.
func socketUnixRemoveStale(path string) error {
	// If there's no socket file at all, there's nothing to do.
	if !shared.PathExists(path) {
		return nil
	}

	logger.Debugf("Detected stale unix socket, deleting")
	err := os.Remove(path)
	if err != nil {
		return fmt.Errorf("could not delete stale local socket: %v", err)
	}

	return nil
}

// Change the file mode of the given unix socket file,
func socketUnixSetPermissions(path string, mode os.FileMode) error {
	err := os.Chmod(path, mode)
	if err != nil {
		return fmt.Errorf("cannot set permissions on local socket: %v", err)
	}
	return nil
}

// Change the ownership of the given unix socket file,
func socketUnixSetOwnership(path string, groupName string) error {
	var gid int
	var err error

	if groupName != "" {
		g, err := user.LookupGroup(groupName)
		if err != nil {
			return fmt.Errorf("cannot get group ID of '%s': %v", groupName, err)
		}

		gid, err = strconv.Atoi(g.Gid)
		if err != nil {
			return err
		}
	} else {
		gid = os.Getgid()
	}

	err = os.Chown(path, os.Getuid(), gid)
	if err != nil {
		return fmt.Errorf("cannot change ownership on local socket: %v", err)

	}

	return nil
}
<|endoftext|>


<commit_before>package mailserver

import (
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/routing"
	"airdispat.ch/server"
	"airdispat.ch/wire"
	"errors"
	"github.com/airdispatch/dpl"
	"github.com/robfig/revel"
	"melange/app/models"
	"net"
	"os"
	"strings"
)

var ServerLocation string

func getServerLocation() string {
	s, _ := os.Hostname()
	ips, _ := net.LookupHost(s)
	return ips[0] + ":2048"
}

func Init() {
	def := getServerLocation()
	ServerLocation = revel.Config.StringDefault("server.location", def)
}

func Messages(r routing.Router,
	db models.Selectable,
	from *identity.Identity,
	fromUser *models.User,
	public bool, private bool, self bool, since int64) ([]dpl.Message, error) {

	var out []dpl.Message
	var err error

	if public {
		var s []*models.UserSubscription
		_, err := db.Select(&s, "select * from dispatch_subscription where userid = $1", fromUser.UserId)
		if err != nil {
			return nil, err
		}

		for _, v := range s {
			msg, err := DownloadPublicMail(r, uint64(since), from, v.Address) // from, to)
			if err != nil {
				return nil, err
			}
			for _, txn := range msg.Content {
				rmsg, err := DownloadMessage(r, txn.Name, nil, v.Address, txn.Location)
				if err != nil {
					return nil, err
				}
				out = append(out, &PluginMail{rmsg})
			}
		}
	}

	if private {
		var ale []*models.Alert
		_, err = db.Select(&ale, "select * from dispatch_alerts where \"to\" = $1 and timestamp > $2", from.Address.String(), since)
		if err != nil {
			return nil, err
		}
		for _, v := range ale {
			msg, err := v.DownloadMessageFromAlert(db, r)
			if err != nil {
				return nil, err
			}
			out = append(out, &PluginMail{msg})
		}
	}

	if self {
		var msg []*models.Message
		_, err = db.Select(&msg, "select * from dispatch_messages where \"from\" = $1 and timestamp > $2", from.Address.String(), since)
		if err != nil {
			return nil, err
		}
		for _, v := range msg {
			dmsg, err := v.ToDispatch(db, strings.Split(v.To, ",")[0])
			if err != nil {
				return nil, err
			}
			out = append(out, &PluginMail{dmsg})
		}
	}

	return out, nil
}

func SendAlert(r routing.Router, msgName string, from *identity.Identity, to string) error {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return err
	}

	msgDescription := server.CreateMessageDescription(msgName, ServerLocation, from.Address, addr)
	err = message.SignAndSend(msgDescription, from, addr)
	if err != nil {
		return err
	}
	return nil
}

func DownloadMessage(r routing.Router, msgName string, from *identity.Identity, to string, toServer string) (*message.Mail, error) {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return nil, err
	}
	addr.Location = toServer

	txMsg := server.CreateTransferMessage(msgName, from.Address, addr)
	bytes, typ, h, err := message.SendMessageAndReceive(txMsg, from, addr)
	if err != nil {
		return nil, err
	}

	if typ != wire.MailCode {
		return nil, errors.New("Wrong message type.")
	}

	return message.CreateMailFromBytes(bytes, h)
}

func DownloadMessageList(r routing.Router, m *server.MessageList, from *identity.Identity, to string) ([]*message.Mail, error) {
	output := make([]*message.Mail, len(m.Content))
	for i, v := range m.Content {
		var err error
		output[i], err = DownloadMessage(r, v.Name, from, to, v.Location)
		if err != nil {
			return nil, err
		}
	}
	return output, nil
}

func DownloadPublicMail(r routing.Router, since uint64, from *identity.Identity, to string) (*server.MessageList, error) {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return nil, err
	}

	txMsg := server.CreateTransferMessageList(since, from.Address, addr)
	bytes, typ, h, err := message.SendMessageAndReceive(txMsg, from, addr)
	if err != nil {
		return nil, err
	}

	if typ != wire.MessageListCode {
		return nil, errors.New("Wrong message type.")
	}

	return server.CreateMessageListFromBytes(bytes, h)
}
<commit_msg>Fixed Download Public Mail for Empty Mail<commit_after>package mailserver

import (
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/routing"
	"airdispat.ch/server"
	"airdispat.ch/wire"
	"errors"
	"github.com/airdispatch/dpl"
	"github.com/robfig/revel"
	"melange/app/models"
	"net"
	"os"
	"strings"
)

var ServerLocation string

func getServerLocation() string {
	s, _ := os.Hostname()
	ips, _ := net.LookupHost(s)
	return ips[0] + ":2048"
}

func Init() {
	def := getServerLocation()
	ServerLocation = revel.Config.StringDefault("server.location", def)
}

func Messages(r routing.Router,
	db models.Selectable,
	from *identity.Identity,
	fromUser *models.User,
	public bool, private bool, self bool, since int64) ([]dpl.Message, error) {

	var out []dpl.Message
	var err error

	if public {
		var s []*models.UserSubscription
		_, err := db.Select(&s, "select * from dispatch_subscription where userid = $1", fromUser.UserId)
		if err != nil {
			return nil, err
		}

		for _, v := range s {
			msg, err := DownloadPublicMail(r, uint64(since), from, v.Address) // from, to)
			if err != nil {
				return nil, err
			}
			for _, txn := range msg.Content {
				rmsg, err := DownloadMessage(r, txn.Name, nil, v.Address, txn.Location)
				if err != nil {
					return nil, err
				}
				out = append(out, &PluginMail{rmsg})
			}
		}
	}

	if private {
		var ale []*models.Alert
		_, err = db.Select(&ale, "select * from dispatch_alerts where \"to\" = $1 and timestamp > $2", from.Address.String(), since)
		if err != nil {
			return nil, err
		}
		for _, v := range ale {
			msg, err := v.DownloadMessageFromAlert(db, r)
			if err != nil {
				return nil, err
			}
			out = append(out, &PluginMail{msg})
		}
	}

	if self {
		var msg []*models.Message
		_, err = db.Select(&msg, "select * from dispatch_messages where \"from\" = $1 and timestamp > $2", from.Address.String(), since)
		if err != nil {
			return nil, err
		}
		for _, v := range msg {
			dmsg, err := v.ToDispatch(db, strings.Split(v.To, ",")[0])
			if err != nil {
				return nil, err
			}
			out = append(out, &PluginMail{dmsg})
		}
	}

	return out, nil
}

func SendAlert(r routing.Router, msgName string, from *identity.Identity, to string) error {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return err
	}

	msgDescription := server.CreateMessageDescription(msgName, ServerLocation, from.Address, addr)
	err = message.SignAndSend(msgDescription, from, addr)
	if err != nil {
		return err
	}
	return nil
}

func DownloadMessage(r routing.Router, msgName string, from *identity.Identity, to string, toServer string) (*message.Mail, error) {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return nil, err
	}
	addr.Location = toServer

	txMsg := server.CreateTransferMessage(msgName, from.Address, addr)
	bytes, typ, h, err := message.SendMessageAndReceive(txMsg, from, addr)
	if err != nil {
		return nil, err
	}

	if typ != wire.MailCode {
		return nil, errors.New("Wrong message type.")
	}

	return message.CreateMailFromBytes(bytes, h)
}

func DownloadMessageList(r routing.Router, m *server.MessageList, from *identity.Identity, to string) ([]*message.Mail, error) {
	output := make([]*message.Mail, len(m.Content))
	for i, v := range m.Content {
		var err error
		output[i], err = DownloadMessage(r, v.Name, from, to, v.Location)
		if err != nil {
			return nil, err
		}
	}
	return output, nil
}

func DownloadPublicMail(r routing.Router, since uint64, from *identity.Identity, to string) (*server.MessageList, error) {
	addr, err := r.LookupAlias(to)
	if err != nil {
		return nil, err
	}

	txMsg := server.CreateTransferMessageList(since, from.Address, addr)
	bytes, typ, h, err := message.SendMessageAndReceive(txMsg, from, addr)
	if err != nil {
		return nil, err
	}

	if typ != wire.MessageListCode {
		return nil, errors.New("Wrong message type.")
	}

	if bytes == nil {
		// No messages available.
		return &server.MessageList{make([]*server.MessageDescription, 0)}, nil
	}
	return server.CreateMessageListFromBytes(bytes, h)
}
<|endoftext|>