<commit_before>package envcnf

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

// Parser handles a single parsing process for a given (composite) value,
// thous allowing low overhead recursion to account for parsing of composite
// types.
type Parser struct {
	env rawEnv

	val  reflect.Value
	valT reflect.Type

	prefix  string
	sepchar string

	parentNames []string
	name        string
}

// Parse is the main interface to the package. Just pass a pointer to the variable
// you'd like to receive your config values in. If you use a common prefix to
// set your config variable names apart and avoid cluttering, pass it via the
// prefix parameter. SepChar is used to separate the prefix and the subfields
// of your env var. See the examples.
func Parse(val interface{}, prefix, sepchar string) error {
	p, err := NewParser(val, prefix, sepchar)
	if err != nil {
		return err
	}
	return p.parseTypes()
}

// NewParser is the default interface to be used for parsing composite types.
func NewParser(val interface{}, prefix, sepchar string) (*Parser, error) {
	env := newRawEnvWithPrfxSep(prefix, sepchar)
	return newParserWithEnv(env, val, prefix, sepchar, "")
}

// NewParserWithName is the default interface to be used for parsing a single
// non-composite value.
func NewParserWithName(val interface{}, prefix, sepchar, name string) (*Parser, error) {
	env := newRawEnvWithPrfxSep(prefix, sepchar)
	return newParserWithEnv(env, val, prefix, sepchar, name)
}

// newParserWithEnv constructs a Parser from the given values
func newParserWithEnv(env rawEnv, val interface{}, prefix, sepchar, name string) (*Parser, error) {
	ptrRef := reflect.ValueOf(val)
	if ptrRef.Kind() != reflect.Ptr {
		return nil, ErrNeedPointerValue
	}
	v := ptrRef.Elem()
	return &Parser{
		env: env,

		val:  v,
		valT: v.Type(),

		prefix:  prefix,
		sepchar: sepchar,
		name:    name,
	}, nil
}

// getfullname concatenates the parts of the parser's (parent) name(s) in a
// sensible way.
func (p Parser) getfullname() string {
	var key string
	if len(p.parentNames) > 0 {
		key = strings.Join(p.parentNames, p.sepchar) + p.sepchar
	}
	return key + p.name
}

// parseString obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseBool and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseString() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetString(rawval)
	return nil
}

// parseBool obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseBool and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseBool() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}
	val, err := strconv.ParseBool(rawval)
	if err != nil {
		return err
	}
	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetBool(val)
	return nil
}

// parseInt obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseInt and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseInt() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseInt(rawval, 10, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetInt(val)
	return nil
}

// parseUint obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseUint and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseUint() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseUint(rawval, 10, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetUint(val)
	return nil
}

// parseFloat obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseFloat and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseFloat() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseFloat(rawval, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetFloat(val)
	return nil
}

// parseTypes invokes the correct handler method for the reflect.Kind of the
// value passed to NewParser or NewParserWithName.
func (p *Parser) parseTypes() error {
	switch p.val.Kind() {
	case reflect.Bool:
		return p.parseBool()
	case
		reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64:
		return p.parseInt()
	case
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64:
		return p.parseUint()
	case
		reflect.Float32,
		reflect.Float64:
		return p.parseFloat()
	case reflect.Complex64, reflect.Complex128:
		return UnsupportedType("Complex64/Complex128")
	case reflect.String:
		return p.parseString()
	case reflect.Ptr:
		return UnsupportedType("Ptr")
	case reflect.Array, reflect.Slice:
		return UnsupportedType("Array/Slice")
	case reflect.Map:
		return p.parseMap()
	case reflect.Struct:
		return p.parseStruct()
	default:
		return UnsupportedType(p.valT.Name() + " of kind " + p.valT.Kind().String())
	}
}

// parseStruct obtains the values from the env vars that are signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseStruct() error {
	for i := 0; i < p.val.NumField(); i++ {
		field := p.val.Field(i)
		fieldName := p.valT.Field(i).Name
		if !field.CanAddr() {
			return FieldNotAddressable(fieldName)
		}

		subparser, err := newParserWithEnv(p.env, field.Addr().Interface(), p.prefix, p.sepchar, fieldName)
		if err != nil {
			return err
		}

		if len(p.parentNames) > 0 {
			subparser.parentNames = append(subparser.parentNames, p.parentNames...)
		}

		if field.Kind() == reflect.Struct {
			subparser.parentNames = append(subparser.parentNames, fieldName)
		}

		if err := subparser.parseTypes(); err != nil {
			return err
		}

	}
	return nil
}

// parseMap obtains all values from the env vars that are prefixed by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseMap() error {
	prfx := p.getfullname()
	env := p.env.getAllWithPrefix(prfx + p.sepchar)

	if len(env) == 0 {
		return MissingEnvVar(prfx + "_XYZ for map value")
	}

	keyT := p.valT.Key()
	needKeyTrans := keyT.Kind() != reflect.String

	valT := p.valT.Elem()
	needValTrans := valT.Kind() != reflect.String

	for k, v := range env {
		convertedKey := reflect.New(keyT)
		if needKeyTrans {
			valParser, err := newParserWithEnv(env, convertedKey.Interface(), "", "", "")
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else {
			convertedKey.Elem().SetString(k)
		}

		convertedVal := reflect.New(valT)
		if needValTrans {
			valParser, err := newParserWithEnv(env, convertedVal.Interface(), "", "", k)
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else {
			convertedVal.Elem().SetString(v)
		}
		p.val.SetMapIndex(convertedKey.Elem(), convertedVal.Elem())

	}
	return nil
}

// parseSlice obtains all values from the env vars that are prefixed by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseSlice() error {
	prfx := p.getfullname()
	env := p.env.getAllWithPrefix(prfx + p.sepchar)

	if len(env) == 0 {
		return MissingEnvVar(prfx + "_XYZ for slice/array value")
	}

	valT := p.valT.Elem()
	needValTrans := valT.Kind() != reflect.String

	convertedVals := make(map[int]reflect.Value)
	for k, v := range env {
		idx, err := strconv.ParseInt(k, 10, 64)
		if err != nil {
			return err
		}

		convertedVal := reflect.New(valT)
		if needValTrans {
			valParser, err := newParserWithEnv(env, convertedVal.Interface(), "", "", k)
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else {
			convertedVal.Elem().SetString(v)
		}
		// collect unorderd
		convertedVals[int(idx)] = convertedVal
	}

	// finally add values to target container in designated order
	for i := 0; i < len(convertedVals); i++ {
		reflect.Append(p.val, convertedVals[i].Elem())
	}
	return nil
}
<commit_msg>fixed Parser.parseMap to handle composite values properly<commit_after>package envcnf

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

// Parser handles a single parsing process for a given (composite) value,
// thous allowing low overhead recursion to account for parsing of composite
// types.
type Parser struct {
	env rawEnv

	val  reflect.Value
	valT reflect.Type

	prefix  string
	sepchar string

	parentNames []string
	name        string
}

// Parse is the main interface to the package. Just pass a pointer to the variable
// you'd like to receive your config values in. If you use a common prefix to
// set your config variable names apart and avoid cluttering, pass it via the
// prefix parameter. SepChar is used to separate the prefix and the subfields
// of your env var. See the examples.
func Parse(val interface{}, prefix, sepchar string) error {
	p, err := NewParser(val, prefix, sepchar)
	if err != nil {
		return err
	}
	return p.parseTypes()
}

// NewParser is the default interface to be used for parsing composite types.
func NewParser(val interface{}, prefix, sepchar string) (*Parser, error) {
	env := newRawEnvWithPrfxSep(prefix, sepchar)
	return newParserWithEnv(env, val, prefix, sepchar, "")
}

// NewParserWithName is the default interface to be used for parsing a single
// non-composite value.
func NewParserWithName(val interface{}, prefix, sepchar, name string) (*Parser, error) {
	env := newRawEnvWithPrfxSep(prefix, sepchar)
	return newParserWithEnv(env, val, prefix, sepchar, name)
}

// newParserWithEnv constructs a Parser from the given values
func newParserWithEnv(env rawEnv, val interface{}, prefix, sepchar, name string) (*Parser, error) {
	ref := reflect.ValueOf(val)
	if ref.Kind() != reflect.Ptr && ref.Kind() != reflect.Interface {
		return nil, ErrNeedPointerValue
	}
	v := ref.Elem()
	return &Parser{
		env: env,

		val:  v,
		valT: v.Type(),

		prefix:  prefix,
		sepchar: sepchar,
		name:    name,
	}, nil
}

// getfullname concatenates the parts of the parser's (parent) name(s) in a
// sensible way.
func (p Parser) getfullname() string {
	var key string
	if len(p.parentNames) > 0 {
		key = strings.Join(p.parentNames, p.sepchar) + p.sepchar
	}
	return key + p.name
}

// parseString obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseBool and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseString() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetString(rawval)
	return nil
}

// parseBool obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseBool and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseBool() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}
	val, err := strconv.ParseBool(rawval)
	if err != nil {
		return err
	}
	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetBool(val)
	return nil
}

// parseInt obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseInt and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseInt() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseInt(rawval, 10, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetInt(val)
	return nil
}

// parseUint obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseUint and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseUint() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseUint(rawval, 10, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetUint(val)
	return nil
}

// parseFloat obtains the value from the env var that is signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses it via strconv.ParseFloat and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseFloat() error {
	key := p.getfullname()
	rawval, ok := p.env[key]
	if !ok {
		//TODO: use/obtain/signal default falue
		return MissingEnvVar(key)
	}

	val, err := strconv.ParseFloat(rawval, p.valT.Bits())
	if err != nil {
		return err
	}

	// CanAddr/CanSet/AssignableTo/ConvertibleTo are handled by the upper layers
	p.val.SetFloat(val)
	return nil
}

// parseTypes invokes the correct handler method for the reflect.Kind of the
// value passed to NewParser or NewParserWithName.
func (p *Parser) parseTypes() error {
	switch p.val.Kind() {
	case reflect.Bool:
		return p.parseBool()
	case
		reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64:
		return p.parseInt()
	case
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64:
		return p.parseUint()
	case
		reflect.Float32,
		reflect.Float64:
		return p.parseFloat()
	case reflect.Complex64, reflect.Complex128:
		return UnsupportedType("Complex64/Complex128")
	case reflect.String:
		return p.parseString()
	case reflect.Ptr:
		return UnsupportedType("Ptr")
	case reflect.Array, reflect.Slice:
		return UnsupportedType("Array/Slice")
	case reflect.Map:
		return p.parseMap()
	case reflect.Struct:
		return p.parseStruct()
	default:
		return UnsupportedType(p.valT.Name() + " of kind " + p.valT.Kind().String())
	}
}

// parseStruct obtains the values from the env vars that are signified by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseStruct() error {
	for i := 0; i < p.val.NumField(); i++ {
		field := p.val.Field(i)
		fieldName := p.valT.Field(i).Name
		if !field.CanAddr() {
			return FieldNotAddressable(fieldName)
		}

		subparser, err := newParserWithEnv(p.env, field.Addr().Interface(), p.prefix, p.sepchar, fieldName)
		if err != nil {
			return err
		}

		if len(p.parentNames) > 0 {
			subparser.parentNames = append(subparser.parentNames, p.parentNames...)
		}

		if field.Kind() == reflect.Struct {
			subparser.parentNames = append(subparser.parentNames, fieldName)
		}

		if err := subparser.parseTypes(); err != nil {
			return err
		}

	}
	return nil
}

// parseMap obtains all values from the env vars that are prefixed by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseMap() error {
	prfx := p.getfullname()
	env := p.env.getAllWithPrefix(prfx + p.sepchar)

	if len(env) == 0 {
		return MissingEnvVar(prfx + "_XYZ for map value")
	}

	keyT := p.valT.Key()
	keyIsString := keyT.Kind() == reflect.String

	valT := p.valT.Elem()
	var valIsString, valIsContainer bool
	switch valT.Kind() {
	case reflect.String:
		valIsString = true
	case reflect.Struct, reflect.Slice, reflect.Array, reflect.Map:
		valIsContainer = true
	}

	for k, v := range env {
		var mapKey, subTypeKey string

		convertedKey := reflect.New(keyT)
		if !keyIsString {
			valParser, err := newParserWithEnv(env, convertedKey.Interface(), "", p.sepchar, "")
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else if valIsContainer {
			parts := strings.SplitN(k, p.sepchar, 2)
			mapKey, subTypeKey = parts[0], parts[1]
		} else {
			mapKey, subTypeKey = k, k
		}
		convertedKey.Elem().SetString(mapKey)

		convertedVal := reflect.New(valT)
		if valIsString {
			convertedVal.Elem().SetString(v)
		} else if !valIsContainer {
			valParser, err := newParserWithEnv(env, convertedVal.Interface(), "", p.sepchar, subTypeKey)
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else {
			subEnv := env.getAllWithPrefix(mapKey + p.sepchar)
			for subK := range subEnv {
				valParser, err := newParserWithEnv(subEnv, convertedVal.Interface(), "", p.sepchar, subK)
				if err != nil {
					return err
				}
				if err := valParser.parseTypes(); err != nil {
					return err
				}
			}
		}
		p.val.SetMapIndex(convertedKey.Elem(), convertedVal.Elem())
	}
	return nil
}

// parseSlice obtains all values from the env vars that are prefixed by the fully
// nested (and possibly prefixed) name of the parser,
// parses them recursively and assigns
// the obtained result to the (proper subfield of the) variable you handed to
// NewParser or NewParserWithName.
func (p *Parser) parseSlice() error {
	prfx := p.getfullname()
	env := p.env.getAllWithPrefix(prfx + p.sepchar)

	if len(env) == 0 {
		return MissingEnvVar(prfx + "_XYZ for slice/array value")
	}

	valT := p.valT.Elem()
	needValTrans := valT.Kind() != reflect.String

	convertedVals := make(map[int]reflect.Value)
	for k, v := range env {
		idx, err := strconv.ParseInt(k, 10, 64)
		if err != nil {
			return err
		}

		convertedVal := reflect.New(valT)
		if needValTrans {
			valParser, err := newParserWithEnv(env, convertedVal.Interface(), "", "", k)
			if err != nil {
				return err
			}
			if err := valParser.parseTypes(); err != nil {
				return err
			}
		} else {
			convertedVal.Elem().SetString(v)
		}
		// collect unorderd
		convertedVals[int(idx)] = convertedVal
	}

	// finally add values to target container in designated order
	for i := 0; i < len(convertedVals); i++ {
		reflect.Append(p.val, convertedVals[i].Elem())
	}
	return nil
}
<|endoftext|>


<commit_before>package bolt

import (
	"context"
	"fmt"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure OrganizationConfigStore implements chronograf.OrganizationConfigStore.
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}

// OrganizationConfigBucket is used to store chronograf organization configurations
var OrganizationConfigBucket = []byte("OrganizationConfigV1")

// OrganizationConfigStore uses bolt to store and retrieve organization configurations
type OrganizationConfigStore struct {
	client *Client
}

func (s *OrganizationConfigStore) Migrate(ctx context.Context) error {
	return nil
}

// Get retrieves an OrganizationConfig from the store
func (s *OrganizationConfigStore) Get(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
	var cfg chronograf.OrganizationConfig

	err := s.client.db.View(func(tx *bolt.Tx) error {
		return s.get(ctx, tx, orgID, &cfg)
	})

	if err != nil {
		return nil, err
	}

	return &cfg, nil
}

func (s *OrganizationConfigStore) get(ctx context.Context, tx *bolt.Tx, orgID string, cfg *chronograf.OrganizationConfig) error {
	v := tx.Bucket(OrganizationConfigBucket).Get([]byte(orgID))
	if len(v) == 0 {
		return chronograf.ErrOrganizationConfigNotFound
	}
	return internal.UnmarshalOrganizationConfig(v, cfg)
}

// FindOrCreate gets an OrganizationConfig from the store or creates one if none exists for this organization
func (s *OrganizationConfigStore) FindOrCreate(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
	var cfg chronograf.OrganizationConfig
	err := s.client.db.Update(func(tx *bolt.Tx) error {
		err := s.get(ctx, tx, orgID, &cfg)
		if err == chronograf.ErrOrganizationConfigNotFound {
			cfg = newOrganizationConfig(orgID)
			return s.update(ctx, tx, &cfg)
		}
		return err
	})

	if err != nil {
		return nil, err
	}
	return &cfg, nil
}

// Update replaces the OrganizationConfig in the store
func (s *OrganizationConfigStore) Update(ctx context.Context, cfg *chronograf.OrganizationConfig) error {
	if cfg == nil {
		return fmt.Errorf("config provided was nil")
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		return s.update(ctx, tx, cfg)
	})
}

func (s *OrganizationConfigStore) update(ctx context.Context, tx *bolt.Tx, cfg *chronograf.OrganizationConfig) error {
	if v, err := internal.MarshalOrganizationConfig(cfg); err != nil {
		return err
	} else if err := tx.Bucket(OrganizationConfigBucket).Put([]byte(cfg.OrganizationID), v); err != nil {
		return err
	}
	return nil
}

func newOrganizationConfig(orgID string) chronograf.OrganizationConfig {
	return chronograf.OrganizationConfig{
		OrganizationID: orgID,
		LogViewer: chronograf.LogViewerConfig{
			Columns: []chronograf.LogViewerColumn{
				{
					Name:     "time",
					Position: 0,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "hidden",
						},
					},
				},
				{
					Name:     "severity",
					Position: 1,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "label",
							Value: "icon",
						},
						{
							Type:  "label",
							Value: "text",
						},
					},
				},
				{
					Name:     "timestamp",
					Position: 2,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "message",
					Position: 3,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "facility",
					Position: 4,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "procid",
					Position: 5,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "displayName",
							Value: "Proc ID",
						},
					},
				},
				{
					Name:     "appname",
					Position: 6,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "displayName",
							Value: "Application",
						},
					},
				},
				{
					Name:     "host",
					Position: 7,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
			},
		},
	}
}
<commit_msg>Move nil config guard to helper update method<commit_after>package bolt

import (
	"context"
	"fmt"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure OrganizationConfigStore implements chronograf.OrganizationConfigStore.
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}

// OrganizationConfigBucket is used to store chronograf organization configurations
var OrganizationConfigBucket = []byte("OrganizationConfigV1")

// OrganizationConfigStore uses bolt to store and retrieve organization configurations
type OrganizationConfigStore struct {
	client *Client
}

func (s *OrganizationConfigStore) Migrate(ctx context.Context) error {
	return nil
}

// Get retrieves an OrganizationConfig from the store
func (s *OrganizationConfigStore) Get(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
	var cfg chronograf.OrganizationConfig

	err := s.client.db.View(func(tx *bolt.Tx) error {
		return s.get(ctx, tx, orgID, &cfg)
	})

	if err != nil {
		return nil, err
	}

	return &cfg, nil
}

func (s *OrganizationConfigStore) get(ctx context.Context, tx *bolt.Tx, orgID string, cfg *chronograf.OrganizationConfig) error {
	v := tx.Bucket(OrganizationConfigBucket).Get([]byte(orgID))
	if len(v) == 0 {
		return chronograf.ErrOrganizationConfigNotFound
	}
	return internal.UnmarshalOrganizationConfig(v, cfg)
}

// FindOrCreate gets an OrganizationConfig from the store or creates one if none exists for this organization
func (s *OrganizationConfigStore) FindOrCreate(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
	var cfg chronograf.OrganizationConfig
	err := s.client.db.Update(func(tx *bolt.Tx) error {
		err := s.get(ctx, tx, orgID, &cfg)
		if err == chronograf.ErrOrganizationConfigNotFound {
			cfg = newOrganizationConfig(orgID)
			return s.update(ctx, tx, &cfg)
		}
		return err
	})

	if err != nil {
		return nil, err
	}
	return &cfg, nil
}

// Update replaces the OrganizationConfig in the store
func (s *OrganizationConfigStore) Update(ctx context.Context, cfg *chronograf.OrganizationConfig) error {
	return s.client.db.Update(func(tx *bolt.Tx) error {
		return s.update(ctx, tx, cfg)
	})
}

func (s *OrganizationConfigStore) update(ctx context.Context, tx *bolt.Tx, cfg *chronograf.OrganizationConfig) error {
	if cfg == nil {
		return fmt.Errorf("config provided was nil")
	}
	if v, err := internal.MarshalOrganizationConfig(cfg); err != nil {
		return err
	} else if err := tx.Bucket(OrganizationConfigBucket).Put([]byte(cfg.OrganizationID), v); err != nil {
		return err
	}
	return nil
}

func newOrganizationConfig(orgID string) chronograf.OrganizationConfig {
	return chronograf.OrganizationConfig{
		OrganizationID: orgID,
		LogViewer: chronograf.LogViewerConfig{
			Columns: []chronograf.LogViewerColumn{
				{
					Name:     "time",
					Position: 0,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "hidden",
						},
					},
				},
				{
					Name:     "severity",
					Position: 1,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "label",
							Value: "icon",
						},
						{
							Type:  "label",
							Value: "text",
						},
					},
				},
				{
					Name:     "timestamp",
					Position: 2,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "message",
					Position: 3,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "facility",
					Position: 4,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
				{
					Name:     "procid",
					Position: 5,
					Encodings: []chronograf.ColumnEncoding{

						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "displayName",
							Value: "Proc ID",
						},
					},
				},
				{
					Name:     "appname",
					Position: 6,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "visible",
						},
						{
							Type:  "displayName",
							Value: "Application",
						},
					},
				},
				{
					Name:     "host",
					Position: 7,
					Encodings: []chronograf.ColumnEncoding{
						{
							Type:  "visibility",
							Value: "visible",
						},
					},
				},
			},
		},
	}
}
<|endoftext|>


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

package api

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unsafe"

	"github.com/ltick/tick-framework/api/acceptencoder"
	"github.com/ltick/tick-routing"
)

// Wrote returns whether the response has been submitted or not.
func (ctx *Context) Wrote() bool {
	return ctx.Response.Wrote()
}

// Status returns the HTTP status code of the response.
func (ctx *Context) Status() int {
	return ctx.Response.Status()
}

// IsCachable returns boolean of this request is cached.
// HTTP 304 means cached.
func (ctx *Context) IsCachable() bool {
	return ctx.Response.Status() >= 200 && ctx.Response.Status() < 300 || ctx.Response.Status() == 304
}

// IsEmpty returns boolean of this request is empty.
// HTTP 201，204 and 304 means empty.
func (ctx *Context) IsEmpty() bool {
	return ctx.Response.Status() == 201 || ctx.Response.Status() == 204 || ctx.Response.Status() == 304
}

// IsOk returns boolean of this request runs well.
// HTTP 200 means ok.
func (ctx *Context) IsOk() bool {
	return ctx.Response.Status() == 200
}

// IsSuccessful returns boolean of this request runs successfully.
// HTTP 2xx means ok.
func (ctx *Context) IsSuccessful() bool {
	return ctx.Response.Status() >= 200 && ctx.Response.Status() < 300
}

// IsRedirect returns boolean of this request is redirection header.
// HTTP 301,302,307 means redirection.
func (ctx *Context) IsRedirect() bool {
	return ctx.Response.Status() == 301 || ctx.Response.Status() == 302 || ctx.Response.Status() == 303 || ctx.Response.Status() == 307
}

// IsForbidden returns boolean of this request is forbidden.
// HTTP 403 means forbidden.
func (ctx *Context) IsForbidden() bool {
	return ctx.Response.Status() == 403
}

// IsNotFound returns boolean of this request is not found.
// HTTP 404 means forbidden.
func (ctx *Context) IsNotFound() bool {
	return ctx.Response.Status() == 404
}

// IsClientError returns boolean of this request client sends error data.
// HTTP 4xx means forbidden.
func (ctx *Context) IsClientError() bool {
	return ctx.Response.Status() >= 400 && ctx.Response.Status() < 500
}

// IsServerError returns boolean of this server handler errors.
// HTTP 5xx means server internal error.
func (ctx *Context) IsServerError() bool {
	return ctx.Response.Status() >= 500 && ctx.Response.Status() < 600
}

// SetHeader sets response header item string via given key.
func (ctx *Context) SetHeader(key, val string) {
	ctx.Response.Header().Set(key, val)
}

// SetCookie sets cookie value via given key.
// others are ordered as cookie's max age time, path, domain, secure and httponly.
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
	var cookie *http.Cookie = &http.Cookie{
		Name:  name,
		Value: value,
	}
	//fix cookie not work in IE
	if len(others) > 0 {
		var maxAge int
		switch v := others[0].(type) {
		case int:
			maxAge = v
		case int32:
			maxAge = int(v)
		case int64:
			maxAge = int(v)
		}
		switch {
		case maxAge > 0:
			cookie.Expires = time.Now().Add(time.Duration(maxAge) * time.Second)
			cookie.MaxAge = maxAge
		case maxAge < 0:
			cookie.MaxAge = 0
		}
	}
	// the settings below
	// Path, Domain, Secure, HttpOnly
	// can use nil skip set

	// default "/"
	if len(others) > 1 {
		if v, ok := others[1].(string); ok && len(v) > 0 {
			cookie.Path = v
		}
	} else {
		cookie.Path = "/"
	}

	// default empty
	if len(others) > 2 {
		if v, ok := others[2].(string); ok && len(v) > 0 {
			cookie.Domain = v
		}
	}

	// default empty
	if len(others) > 3 {
		var secure bool
		switch v := others[3].(type) {
		case bool:
			secure = v
		default:
			if others[3] != nil {
				secure = true
			}
		}
		cookie.Secure = secure
	}

	// default false. for session cookie default true
	httponly := false
	if len(others) > 4 {
		if v, ok := others[4].(bool); ok && v {
			// HttpOnly = true
			httponly = true
		}
	}
	cookie.HttpOnly = httponly

	ctx.Response.AddCookie(cookie)
}

// SetSecureCookie Set Secure cookie for response.
func (ctx *Context) SetSecureCookie(secret, name, value string, others ...interface{}) {
	vs := base64.URLEncoding.EncodeToString([]byte(value))
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	h := hmac.New(sha1.New, []byte(secret))
	fmt.Fprintf(h, "%s%s", vs, timestamp)
	sig := fmt.Sprintf("%02x", h.Sum(nil))
	cookie := strings.Join([]string{vs, timestamp, sig}, "|")
	ctx.SetCookie(name, cookie, others...)
}

// NoContent sends a response with no body and a status code.
func (ctx *Context) NoContent(status int) {
	ctx.Response.WriteHeader(status)
}

// Bytes writes the data bytes to the connection as part of an HTTP reply.
func (ctx *Context) ResponseBytes(status int, contentType string, content []byte) error {
	if ctx.Response.Wrote() {
		ctx.Response.wroteCallback()
		return nil
	}
	ctx.Response.Header().Set(HeaderContentType, contentType)
	if ctx.enableGzip && len(ctx.Response.Header()[HeaderContentEncoding]) == 0 {
		buf := &bytes.Buffer{}
		ok, encoding, _ := acceptencoder.WriteBody(acceptencoder.ParseEncoding(ctx.Request), buf, content)
		if ok {
			ctx.Response.Header().Set(HeaderContentEncoding, encoding)
			content = buf.Bytes()
		}
	}
	ctx.Response.Header().Set(HeaderContentLength, strconv.Itoa(len(content)))
	return ctx.Response.Write(content)
}

// String writes a string to the client, something like fmt.Fprintf
func (ctx *Context) ResponseString(status int, format string, s ...interface{}) error {
	if len(s) == 0 {
		return ctx.ResponseBytes(status, MIMETextPlainCharsetUTF8, []byte(format))
	}
	return ctx.ResponseBytes(status, MIMETextPlainCharsetUTF8, []byte(fmt.Sprintf(format, s...)))
}

// HTML sends an HTTP response with status code.
func (ctx *Context) ResponseHTML(status int, html string) error {
	x := (*[2]uintptr)(unsafe.Pointer(&html))
	h := [3]uintptr{x[0], x[1], x[1]}
	return ctx.ResponseBytes(status, MIMETextHTMLCharsetUTF8, *(*[]byte)(unsafe.Pointer(&h)))
}

// JSON sends a JSON response with status code.
func (ctx *Context) ResponseJSON(status int, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = json.MarshalIndent(data, "", "  ")
	} else {
		b, err = json.Marshal(data)
	}
	if err != nil {
		return err
	}
	return ctx.ResponseJSONBlob(status, b)
}

// JSONBlob sends a JSON blob response with status code.
func (ctx *Context) ResponseJSONBlob(status int, b []byte) error {
	return ctx.ResponseBytes(status, MIMEApplicationJSONCharsetUTF8, b)
}

// JSONP sends a JSONP response with status code. It uses `callback` to construct
// the JSONP payload.
func (ctx *Context) ResponseJSONP(status int, callback string, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = json.MarshalIndent(data, "", "  ")
	} else {
		b, err = json.Marshal(data)
	}
	if err != nil {
		return err
	}
	callback = template.JSEscapeString(callback)
	callbackContent := bytes.NewBufferString(" if(window." + callback + ")" + callback)
	callbackContent.WriteString("(")
	callbackContent.Write(b)
	callbackContent.WriteString(");\r\n")
	return ctx.ResponseBytes(status, MIMEApplicationJavaScriptCharsetUTF8, callbackContent.Bytes())
}

// XML sends an XML response with status code.
func (ctx *Context) ResponseXML(status int, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = xml.MarshalIndent(data, "", "  ")
	} else {
		b, err = xml.Marshal(data)
	}
	if err != nil {
		return err
	}
	return ctx.ResponseXMLBlob(status, b)
}

// XMLBlob sends a XML blob response with status code.
func (ctx *Context) ResponseXMLBlob(status int, b []byte) error {
	content := bytes.NewBufferString(xml.Header)
	content.Write(b)
	return ctx.ResponseBytes(status, MIMEApplicationXMLCharsetUTF8, content.Bytes())
}

// JSONOrXML serve Xml OR Json, depending on the value of the Accept header
func (ctx *Context) ResponseJSONOrXML(status int, data interface{}, isIndent ...bool) error {
	if ctx.AcceptJSON() || !ctx.AcceptXML() {
		return ctx.ResponseJSON(status, data, isIndent...)
	}
	return ctx.ResponseXML(status, data, isIndent...)
}

func (ctx *Context) ResponseDefault(code string, data interface{}, messages ...string) error {
	responseData := NewResponseData(code, data, messages...)
	err := ctx.Write(responseData)
	if err != nil {
		if ConnectionResetByPeer(err) || Timeout(err) || NetworkUnreachable(err) {
			return routing.NewHTTPError(499, "Response write error: "+err.Error())
		}
		return routing.NewHTTPError(http.StatusRequestTimeout, "Response write error: "+err.Error())
	}
	return err
}

// File forces response for download file.
// it prepares the download response header automatically.
func (ctx *Context) File(localFilename string, showFilename ...string) {
	ctx.Response.Header().Set(HeaderContentDescription, "File Transfer")
	ctx.Response.Header().Set(HeaderContentType, MIMEOctetStream)
	if len(showFilename) > 0 && showFilename[0] != "" {
		ctx.Response.Header().Set(HeaderContentDisposition, "attachment; filename="+showFilename[0])
	} else {
		ctx.Response.Header().Set(HeaderContentDisposition, "attachment; filename="+filepath.Base(localFilename))
	}
	ctx.Response.Header().Set(HeaderContentTransferEncoding, "binary")
	ctx.Response.Header().Set(HeaderExpires, "0")
	ctx.Response.Header().Set(HeaderCacheControl, "must-revalidate")
	ctx.Response.Header().Set(HeaderPragma, "public")
	http.ServeFile(ctx.ResponseWriter, ctx.Request, localFilename)
}
<commit_msg>update<commit_after>// Copyright 2016 HenryLee. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unsafe"

	"github.com/ltick/tick-framework/api/acceptencoder"
	"github.com/ltick/tick-routing"
)

// Wrote returns whether the response has been submitted or not.
func (ctx *Context) Wrote() bool {
	return ctx.Response.Wrote()
}

// Status returns the HTTP status code of the response.
func (ctx *Context) Status() int {
	return ctx.Response.Status()
}

// IsCachable returns boolean of this request is cached.
// HTTP 304 means cached.
func (ctx *Context) IsCachable() bool {
	return ctx.Response.Status() >= 200 && ctx.Response.Status() < 300 || ctx.Response.Status() == 304
}

// IsEmpty returns boolean of this request is empty.
// HTTP 201，204 and 304 means empty.
func (ctx *Context) IsEmpty() bool {
	return ctx.Response.Status() == 201 || ctx.Response.Status() == 204 || ctx.Response.Status() == 304
}

// IsOk returns boolean of this request runs well.
// HTTP 200 means ok.
func (ctx *Context) IsOk() bool {
	return ctx.Response.Status() == 200
}

// IsSuccessful returns boolean of this request runs successfully.
// HTTP 2xx means ok.
func (ctx *Context) IsSuccessful() bool {
	return ctx.Response.Status() >= 200 && ctx.Response.Status() < 300
}

// IsRedirect returns boolean of this request is redirection header.
// HTTP 301,302,307 means redirection.
func (ctx *Context) IsRedirect() bool {
	return ctx.Response.Status() == 301 || ctx.Response.Status() == 302 || ctx.Response.Status() == 303 || ctx.Response.Status() == 307
}

// IsForbidden returns boolean of this request is forbidden.
// HTTP 403 means forbidden.
func (ctx *Context) IsForbidden() bool {
	return ctx.Response.Status() == 403
}

// IsNotFound returns boolean of this request is not found.
// HTTP 404 means forbidden.
func (ctx *Context) IsNotFound() bool {
	return ctx.Response.Status() == 404
}

// IsClientError returns boolean of this request client sends error data.
// HTTP 4xx means forbidden.
func (ctx *Context) IsClientError() bool {
	return ctx.Response.Status() >= 400 && ctx.Response.Status() < 500
}

// IsServerError returns boolean of this server handler errors.
// HTTP 5xx means server internal error.
func (ctx *Context) IsServerError() bool {
	return ctx.Response.Status() >= 500 && ctx.Response.Status() < 600
}

// SetHeader sets response header item string via given key.
func (ctx *Context) SetHeader(key, val string) {
	ctx.Response.Header().Set(key, val)
}

// SetCookie sets cookie value via given key.
// others are ordered as cookie's max age time, path, domain, secure and httponly.
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
	var cookie *http.Cookie = &http.Cookie{
		Name:  name,
		Value: value,
	}
	//fix cookie not work in IE
	if len(others) > 0 {
		var maxAge int
		switch v := others[0].(type) {
		case int:
			maxAge = v
		case int32:
			maxAge = int(v)
		case int64:
			maxAge = int(v)
		}
		switch {
		case maxAge > 0:
			cookie.Expires = time.Now().Add(time.Duration(maxAge) * time.Second)
			cookie.MaxAge = maxAge
		case maxAge < 0:
			cookie.MaxAge = 0
		}
	}
	// the settings below
	// Path, Domain, Secure, HttpOnly
	// can use nil skip set

	// default "/"
	if len(others) > 1 {
		if v, ok := others[1].(string); ok && len(v) > 0 {
			cookie.Path = v
		}
	} else {
		cookie.Path = "/"
	}

	// default empty
	if len(others) > 2 {
		if v, ok := others[2].(string); ok && len(v) > 0 {
			cookie.Domain = v
		}
	}

	// default empty
	if len(others) > 3 {
		var secure bool
		switch v := others[3].(type) {
		case bool:
			secure = v
		default:
			if others[3] != nil {
				secure = true
			}
		}
		cookie.Secure = secure
	}

	// default false. for session cookie default true
	httponly := false
	if len(others) > 4 {
		if v, ok := others[4].(bool); ok && v {
			// HttpOnly = true
			httponly = true
		}
	}
	cookie.HttpOnly = httponly

	ctx.Response.AddCookie(cookie)
}

// SetSecureCookie Set Secure cookie for response.
func (ctx *Context) SetSecureCookie(secret, name, value string, others ...interface{}) {
	vs := base64.URLEncoding.EncodeToString([]byte(value))
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	h := hmac.New(sha1.New, []byte(secret))
	fmt.Fprintf(h, "%s%s", vs, timestamp)
	sig := fmt.Sprintf("%02x", h.Sum(nil))
	cookie := strings.Join([]string{vs, timestamp, sig}, "|")
	ctx.SetCookie(name, cookie, others...)
}

// NoContent sends a response with no body and a status code.
func (ctx *Context) NoContent(status int) {
	ctx.Response.WriteHeader(status)
}

// Bytes writes the data bytes to the connection as part of an HTTP reply.
func (ctx *Context) ResponseBytes(status int, contentType string, content []byte) error {
	if ctx.Response.Wrote() {
		ctx.Response.wroteCallback()
		return nil
	}
	ctx.Response.Header().Set(HeaderContentType, contentType)
	if ctx.enableGzip && len(ctx.Response.Header()[HeaderContentEncoding]) == 0 {
		buf := &bytes.Buffer{}
		ok, encoding, _ := acceptencoder.WriteBody(acceptencoder.ParseEncoding(ctx.Request), buf, content)
		if ok {
			ctx.Response.Header().Set(HeaderContentEncoding, encoding)
			content = buf.Bytes()
		}
	}
	ctx.Response.Header().Set(HeaderContentLength, strconv.Itoa(len(content)))
	ctx.Response.WriteHeader(status)
	return ctx.Response.Write(content)
}

// String writes a string to the client, something like fmt.Fprintf
func (ctx *Context) ResponseString(status int, format string, s ...interface{}) error {
	if len(s) == 0 {
		return ctx.ResponseBytes(status, MIMETextPlainCharsetUTF8, []byte(format))
	}
	return ctx.ResponseBytes(status, MIMETextPlainCharsetUTF8, []byte(fmt.Sprintf(format, s...)))
}

// HTML sends an HTTP response with status code.
func (ctx *Context) ResponseHTML(status int, html string) error {
	x := (*[2]uintptr)(unsafe.Pointer(&html))
	h := [3]uintptr{x[0], x[1], x[1]}
	return ctx.ResponseBytes(status, MIMETextHTMLCharsetUTF8, *(*[]byte)(unsafe.Pointer(&h)))
}

// JSON sends a JSON response with status code.
func (ctx *Context) ResponseJSON(status int, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = json.MarshalIndent(data, "", "  ")
	} else {
		b, err = json.Marshal(data)
	}
	if err != nil {
		return err
	}
	return ctx.ResponseJSONBlob(status, b)
}

// JSONBlob sends a JSON blob response with status code.
func (ctx *Context) ResponseJSONBlob(status int, b []byte) error {
	return ctx.ResponseBytes(status, MIMEApplicationJSONCharsetUTF8, b)
}

// JSONP sends a JSONP response with status code. It uses `callback` to construct
// the JSONP payload.
func (ctx *Context) ResponseJSONP(status int, callback string, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = json.MarshalIndent(data, "", "  ")
	} else {
		b, err = json.Marshal(data)
	}
	if err != nil {
		return err
	}
	callback = template.JSEscapeString(callback)
	callbackContent := bytes.NewBufferString(" if(window." + callback + ")" + callback)
	callbackContent.WriteString("(")
	callbackContent.Write(b)
	callbackContent.WriteString(");\r\n")
	return ctx.ResponseBytes(status, MIMEApplicationJavaScriptCharsetUTF8, callbackContent.Bytes())
}

// XML sends an XML response with status code.
func (ctx *Context) ResponseXML(status int, data interface{}, isIndent ...bool) error {
	var (
		b   []byte
		err error
	)
	if len(isIndent) > 0 && isIndent[0] {
		b, err = xml.MarshalIndent(data, "", "  ")
	} else {
		b, err = xml.Marshal(data)
	}
	if err != nil {
		return err
	}
	return ctx.ResponseXMLBlob(status, b)
}

// XMLBlob sends a XML blob response with status code.
func (ctx *Context) ResponseXMLBlob(status int, b []byte) error {
	content := bytes.NewBufferString(xml.Header)
	content.Write(b)
	return ctx.ResponseBytes(status, MIMEApplicationXMLCharsetUTF8, content.Bytes())
}

// JSONOrXML serve Xml OR Json, depending on the value of the Accept header
func (ctx *Context) ResponseJSONOrXML(status int, data interface{}, isIndent ...bool) error {
	if ctx.AcceptJSON() || !ctx.AcceptXML() {
		return ctx.ResponseJSON(status, data, isIndent...)
	}
	return ctx.ResponseXML(status, data, isIndent...)
}

func (ctx *Context) ResponseDefault(code string, data interface{}, messages ...string) error {
	responseData := NewResponseData(code, data, messages...)
	err := ctx.Write(responseData)
	if err != nil {
		if ConnectionResetByPeer(err) || Timeout(err) || NetworkUnreachable(err) {
			return routing.NewHTTPError(499, "Response write error: "+err.Error())
		}
		return routing.NewHTTPError(http.StatusRequestTimeout, "Response write error: "+err.Error())
	}
	return err
}

// File forces response for download file.
// it prepares the download response header automatically.
func (ctx *Context) File(localFilename string, showFilename ...string) {
	ctx.Response.Header().Set(HeaderContentDescription, "File Transfer")
	ctx.Response.Header().Set(HeaderContentType, MIMEOctetStream)
	if len(showFilename) > 0 && showFilename[0] != "" {
		ctx.Response.Header().Set(HeaderContentDisposition, "attachment; filename="+showFilename[0])
	} else {
		ctx.Response.Header().Set(HeaderContentDisposition, "attachment; filename="+filepath.Base(localFilename))
	}
	ctx.Response.Header().Set(HeaderContentTransferEncoding, "binary")
	ctx.Response.Header().Set(HeaderExpires, "0")
	ctx.Response.Header().Set(HeaderCacheControl, "must-revalidate")
	ctx.Response.Header().Set(HeaderPragma, "public")
	http.ServeFile(ctx.ResponseWriter, ctx.Request, localFilename)
}
<|endoftext|>


<commit_before>package api

import (
	"net/url"
	"time"

	"github.com/MEDIGO/laika/models"
	"github.com/labstack/echo"
)

func GetFeature(c echo.Context) error {
	name, err := url.QueryUnescape(c.Param("name"))
	if err != nil {
		return BadRequest(c, "Bad feature name")
	}

	state := getState(c)
	for _, feature := range state.Features {
		if feature.Name == name {
			return OK(c, *getFeature(&feature, state))
		}
	}

	return NotFound(c)
}

func ListFeatures(c echo.Context) error {
	state := getState(c)
	status := []featureResource{}
	for _, feature := range state.Features {
		status = append(status, *getFeature(&feature, state))
	}
	return OK(c, status)
}

func getFeature(feature *models.Feature, s *models.State) *featureResource {
	f := featureResource{
		Feature:         *feature,
		Status:          map[string]bool{},
		FeatureStatuses: []featureStatus{},
	}
	for _, env := range s.Environments {
		status, ok := s.Enabled[models.EnvFeature{
			Env:     env.Name,
			Feature: feature.Name,
		}]
		toggled := ok && status.Enabled
		f.Status[env.Name] = toggled
		f.FeatureStatuses = append(f.FeatureStatuses, featureStatus{
			Name:      env.Name,
			Status:    toggled,
			ToggledAt: status.ToggledAt,
		})
	}

	return &f
}

func GetFeatureStatus(c echo.Context) error {
	name_param, err := url.QueryUnescape(c.Param("name"))
	if err != nil {
		return BadRequest(c, "Bad feature name")
	}

	env_param, err := url.QueryUnescape(c.Param("env"))
	if err != nil {
		return BadRequest(c, "Bad env name")
	}

	state := getState(c)
	for _, environment := range s.Environments {
		status, ok := s.Enabled[models.EnvFeature{
			Env:     environment.Name,
			Feature: feature.Name,
		}]
		toggled := ok && status.Enabled
		if(env_param == environment.Name && name_param == feature.Name) {
			return OK(c, toggled)
		}
	}
    // Too many errors can help in detecting bad requests either from client or malicious user
	return NotFound(c)
}

type featureResource struct {
	models.Feature
	Status          map[string]bool `json:"status"`
	FeatureStatuses []featureStatus `json:"feature_status"`
}

type featureStatus struct {
	Name      string     `json:"name"`
	Status    bool       `json:"status"`
	ToggledAt *time.Time `json:"toggled_at,omitempty"`
}
<commit_msg>Changed default response from error to ok(flase)<commit_after>package api

import (
	"net/url"
	"time"

	"github.com/MEDIGO/laika/models"
	"github.com/labstack/echo"
)

func GetFeature(c echo.Context) error {
	name, err := url.QueryUnescape(c.Param("name"))
	if err != nil {
		return BadRequest(c, "Bad feature name")
	}

	state := getState(c)
	for _, feature := range state.Features {
		if feature.Name == name {
			return OK(c, *getFeature(&feature, state))
		}
	}

	return NotFound(c)
}

func ListFeatures(c echo.Context) error {
	state := getState(c)
	status := []featureResource{}
	for _, feature := range state.Features {
		status = append(status, *getFeature(&feature, state))
	}
	return OK(c, status)
}

func getFeature(feature *models.Feature, s *models.State) *featureResource {
	f := featureResource{
		Feature:         *feature,
		Status:          map[string]bool{},
		FeatureStatuses: []featureStatus{},
	}
	for _, env := range s.Environments {
		status, ok := s.Enabled[models.EnvFeature{
			Env:     env.Name,
			Feature: feature.Name,
		}]
		toggled := ok && status.Enabled
		f.Status[env.Name] = toggled
		f.FeatureStatuses = append(f.FeatureStatuses, featureStatus{
			Name:      env.Name,
			Status:    toggled,
			ToggledAt: status.ToggledAt,
		})
	}

	return &f
}

func GetFeatureStatus(c echo.Context) error {
	name_param, err := url.QueryUnescape(c.Param("name"))
	if err != nil {
		return BadRequest(c, "Bad feature name")
	}

	env_param, err := url.QueryUnescape(c.Param("env"))
	if err != nil {
		return BadRequest(c, "Bad env name")
	}

	state := getState(c)
	for _, environment := range s.Environments {
		status, ok := s.Enabled[models.EnvFeature{
			Env:     environment.Name,
			Feature: feature.Name,
		}]
		toggled := ok && status.Enabled
		if(env_param == environment.Name && name_param == feature.Name) {
			return OK(c, toggled)
		}
	}
	return OK(c, false)
}

type featureResource struct {
	models.Feature
	Status          map[string]bool `json:"status"`
	FeatureStatuses []featureStatus `json:"feature_status"`
}

type featureStatus struct {
	Name      string     `json:"name"`
	Status    bool       `json:"status"`
	ToggledAt *time.Time `json:"toggled_at,omitempty"`
}
<|endoftext|>


<commit_before>package dynamodb_test

import (
	"fmt"
	"os"
	"strings"
	"testing"

	"github.com/kyani-inc/storage/providers/dynamodb"
	"github.com/subosito/gotenv"
)

var (
	ddb      dynamodb.DynamoDB
	region   = ""
	dbtable  = ""
	endpoint = ""
)

func TestMain(m *testing.M) {
	gotenv.Load(".env")

	region = os.Getenv("AWS_REGION") //"us-west-2"
	dbtable = os.Getenv("DYNAMO_DB_TABLE")
	endpoint = os.Getenv("DYNAMO_DB_ENDPOINT")
	os.Exit(m.Run())
}

func TestConnect(t *testing.T) {
	if region == "" || dbtable == "" || endpoint == "" {
		t.Fatal("Missing required env vars!")
	}

	var err error
	ddb, err = dynamodb.New(region, endpoint, "test_table")

	if err != nil {
		t.Fatal("Failed to establish connection with DynamoDB!")
	} else {
		fmt.Println("Connected to local DynamoDB server")
	}
}

func TestPut(t *testing.T) {
	blah := []byte("hello, world!!")
	_ = ddb.Put("test1", blah)

	blah = []byte(`{"hello":"world"}`)
	_ = ddb.Put("test2", blah)

	blah = []byte{}
	_ = ddb.Put("nodata", blah)
}

func TestGet(t *testing.T) {
	data := ddb.Get("test1")
	fmt.Println(string(data))

	data = ddb.Get("test2")
	fmt.Println(string(data))

	data = ddb.Get("nodata")
	fmt.Println(string(data))
}

func TestDelete(t *testing.T) {
	ddb.Delete("test2")

	data := ddb.Get("test2")

	if strings.Contains(string(data), "world") == true {
		t.Error("key test2 was not deleted!")
	}
}

func TestFlush(t *testing.T) {
	ddb.Flush()

	exists := ddb.TableExists()

	if exists {
		t.Error("DB Table was not 'flushed'. Failed to remove table.")
	}
}
<commit_msg>softly failing if env vars are not defined<commit_after>package dynamodb_test

import (
	"fmt"
	"os"
	"strings"
	"testing"

	"github.com/kyani-inc/storage/providers/dynamodb"
	"github.com/subosito/gotenv"
)

var (
	ddb      dynamodb.DynamoDB
	region   = ""
	dbtable  = ""
	endpoint = ""
)

func TestMain(m *testing.M) {
	gotenv.Load(".env")

	region = os.Getenv("AWS_REGION") //"us-west-2"
	dbtable = os.Getenv("DYNAMO_DB_TABLE")
	endpoint = os.Getenv("DYNAMO_DB_ENDPOINT")

	if region == "" || dbtable == "" || endpoint == "" {
		fmt.Println("Env vars not set")
		os.Exit(0)
		return
	}

	os.Exit(m.Run())
}

func TestConnect(t *testing.T) {
	var err error
	ddb, err = dynamodb.New(region, endpoint, "test_table")

	if err != nil {
		t.Fatal("Failed to establish connection with DynamoDB!")
	} else {
		fmt.Println("Connected to local DynamoDB server")
	}
}

func TestPut(t *testing.T) {
	blah := []byte("hello, world!!")
	_ = ddb.Put("test1", blah)

	blah = []byte(`{"hello":"world"}`)
	_ = ddb.Put("test2", blah)

	blah = []byte{}
	_ = ddb.Put("nodata", blah)
}

func TestGet(t *testing.T) {
	data := ddb.Get("test1")
	fmt.Println(string(data))

	data = ddb.Get("test2")
	fmt.Println(string(data))

	data = ddb.Get("nodata")
	fmt.Println(string(data))
}

func TestDelete(t *testing.T) {
	ddb.Delete("test2")

	data := ddb.Get("test2")

	if strings.Contains(string(data), "world") == true {
		t.Error("key test2 was not deleted!")
	}
}

func TestFlush(t *testing.T) {
	ddb.Flush()

	exists := ddb.TableExists()

	if exists {
		t.Error("DB Table was not 'flushed'. Failed to remove table.")
	}
}
<|endoftext|>


<commit_before>// This package implements a provisioner for Packer that executes
// Converge to provision a remote machine

package converge

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"net/http"

	"strings"

	"encoding/json"

	"regexp"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

var versionRegex = regexp.MustCompile(`^[\.\-\da-zA-Z]*$`)

// Config for Converge provisioner
type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// Bootstrapping
	Bootstrap bool   `mapstructure:"bootstrap"`
	Version   string `mapstructure:"version"`

	// Modules
	ModuleDirs []ModuleDir `mapstructure:"module_dirs"`
	Modules    []Module    `mapstructure:"modules"`

	ctx interpolate.Context
}

// ModuleDir is a directory to transfer to the remote system
type ModuleDir struct {
	Source      string   `mapstructure:"source"`
	Destination string   `mapstructure:"destination"`
	Exclude     []string `mapstructure:"exclude"`
}

// Module contains information needed to run a module
type Module struct {
	Module    string            `mapstructure:"module"`
	Directory string            `mapstructure:"directory"`
	Params    map[string]string `mapstucture:"params"`
}

// Provisioner for Converge
type Provisioner struct {
	config Config
}

// Prepare provisioner somehow. TODO: actual docs
func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(
		&p.config,
		&config.DecodeOpts{
			Interpolate:        true,
			InterpolateContext: &p.config.ctx,
		},
		raws...,
	)
	if err != nil {
		return err
	}

	// validate version
	if !versionRegex.Match([]byte(p.config.Version)) {
		return fmt.Errorf("Invalid Converge version %q specified. Valid versions include only letters, numbers, dots, and dashes", p.config.Version)
	}

	// validate sources and destinations
	for i, dir := range p.config.ModuleDirs {
		if dir.Source == "" {
			return fmt.Errorf("Source (\"source\" key) is required in Converge module dir #%d", i)
		}
		if dir.Destination == "" {
			return fmt.Errorf("Destination (\"destination\" key) is required in Converge module dir #%d", i)
		}
	}

	// validate modules
	if len(p.config.Modules) == 0 {
		return errors.New("Converge requires at least one module (\"modules\" key) to provision the system")
	}
	for i, module := range p.config.Modules {
		if module.Module == "" {
			return fmt.Errorf("Module (\"module\" key) is required in Converge module #%d", i)
		}
		if module.Directory == "" {
			p.config.Modules[i].Directory = "/tmp"
		}
	}

	return err
}

// Provision node somehow. TODO: actual docs
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Provisioning with Converge")

	// bootstrapping
	if err := p.maybeBootstrap(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	// check version (really, this make sure that Converge is installed before we try to run it)
	if err := p.checkVersion(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	// send module directories to the remote host
	if err := p.sendModuleDirectories(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	// apply all the modules
	if err := p.applyModules(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	return nil
}

func (p *Provisioner) maybeBootstrap(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.Bootstrap {
		return nil
	}
	ui.Message("bootstrapping converge")

	bootstrap, err := http.Get("https://get.converge.sh")
	if err != nil {
		return fmt.Errorf("Error downloading bootstrap script: %s", err) // TODO: is github.com/pkg/error allowed?
	}
	if err := comm.Upload("/tmp/install-converge.sh", bootstrap.Body, nil); err != nil {
		return fmt.Errorf("Error uploading script: %s", err)
	}
	if err := bootstrap.Body.Close(); err != nil {
		return fmt.Errorf("Error getting bootstrap script: %s", err)
	}

	// construct command
	command := "/bin/sh /tmp/install-converge.sh"
	if p.config.Version != "" {
		command += " -v " + p.config.Version
	}

	var out bytes.Buffer
	cmd := &packer.RemoteCmd{
		Command: command,
		Stdin:   nil,
		Stdout:  &out,
		Stderr:  &out,
	}

	if err = comm.Start(cmd); err != nil {
		return fmt.Errorf("Error bootstrapping converge: %s", err)
	}

	cmd.Wait()
	if cmd.ExitStatus != 0 {
		ui.Error(out.String())
		return errors.New("Error bootstrapping converge")
	}

	ui.Message(strings.TrimSpace(out.String()))
	return nil
}

func (p *Provisioner) checkVersion(ui packer.Ui, comm packer.Communicator) error {
	var versionOut bytes.Buffer
	cmd := &packer.RemoteCmd{
		Command: "converge version",
		Stdin:   nil,
		Stdout:  &versionOut,
		Stderr:  &versionOut,
	}
	if err := comm.Start(cmd); err != nil {
		return fmt.Errorf("Error running `converge version`: %s", err)
	}

	cmd.Wait()
	if cmd.ExitStatus == 127 {
		ui.Error("Could not determine Converge version. Is it installed and in PATH?")
		if !p.config.Bootstrap {
			ui.Error("Bootstrapping was disabled for this run. That might be why Converge isn't present.")
		}

		return errors.New("could not determine Converge version")

	} else if cmd.ExitStatus != 0 {
		ui.Error(versionOut.String())
		ui.Error(fmt.Sprintf("exited with error code %d", cmd.ExitStatus))
		return errors.New("Error running `converge version`")
	}

	ui.Say(fmt.Sprintf("Provisioning with %s", strings.TrimSpace(versionOut.String())))

	return nil
}

func (p *Provisioner) sendModuleDirectories(ui packer.Ui, comm packer.Communicator) error {
	for _, dir := range p.config.ModuleDirs {
		if err := comm.UploadDir(dir.Destination, dir.Source, dir.Exclude); err != nil {
			return fmt.Errorf("Could not upload %q: %s", dir.Source, err)
		}
		ui.Message(fmt.Sprintf("transferred %q to %q", dir.Source, dir.Destination))
	}

	return nil
}

func (p *Provisioner) applyModules(ui packer.Ui, comm packer.Communicator) error {
	for _, module := range p.config.Modules {
		// create params JSON file
		params, err := json.Marshal(module.Params)
		if err != nil {
			return fmt.Errorf("Could not marshal parameters as JSON: %s", err)
		}

		// run Converge in the specified directory
		var runOut bytes.Buffer
		cmd := &packer.RemoteCmd{
			Command: fmt.Sprintf(
				"cd %s && converge apply --local --log-level=WARNING --paramsJSON '%s' %s",
				module.Directory,
				string(params),
				module.Module,
			),
			Stdin:  nil,
			Stdout: &runOut,
			Stderr: &runOut,
		}
		if err := comm.Start(cmd); err != nil {
			return fmt.Errorf("Error applying %q: %s", module.Module, err)
		}

		cmd.Wait()
		if cmd.ExitStatus != 0 {
			ui.Error(strings.TrimSpace(runOut.String()))
			ui.Error(fmt.Sprintf("exited with error code %d", cmd.ExitStatus))
			return fmt.Errorf("Error applying %q", module.Module)
		}

		ui.Message(strings.TrimSpace(runOut.String()))
	}

	return nil
}

// Cancel the provisioning process
func (p *Provisioner) Cancel() {
	log.Println("cancel called in Converge provisioner")
}
<commit_msg>provisioner(converge): remove version check<commit_after>// This package implements a provisioner for Packer that executes
// Converge to provision a remote machine

package converge

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"net/http"

	"strings"

	"encoding/json"

	"regexp"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

var versionRegex = regexp.MustCompile(`^[\.\-\da-zA-Z]*$`)

// Config for Converge provisioner
type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// Bootstrapping
	Bootstrap bool   `mapstructure:"bootstrap"`
	Version   string `mapstructure:"version"`

	// Modules
	ModuleDirs []ModuleDir `mapstructure:"module_dirs"`
	Modules    []Module    `mapstructure:"modules"`

	ctx interpolate.Context
}

// ModuleDir is a directory to transfer to the remote system
type ModuleDir struct {
	Source      string   `mapstructure:"source"`
	Destination string   `mapstructure:"destination"`
	Exclude     []string `mapstructure:"exclude"`
}

// Module contains information needed to run a module
type Module struct {
	Module    string            `mapstructure:"module"`
	Directory string            `mapstructure:"directory"`
	Params    map[string]string `mapstucture:"params"`
}

// Provisioner for Converge
type Provisioner struct {
	config Config
}

// Prepare provisioner somehow. TODO: actual docs
func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(
		&p.config,
		&config.DecodeOpts{
			Interpolate:        true,
			InterpolateContext: &p.config.ctx,
		},
		raws...,
	)
	if err != nil {
		return err
	}

	// validate version
	if !versionRegex.Match([]byte(p.config.Version)) {
		return fmt.Errorf("Invalid Converge version %q specified. Valid versions include only letters, numbers, dots, and dashes", p.config.Version)
	}

	// validate sources and destinations
	for i, dir := range p.config.ModuleDirs {
		if dir.Source == "" {
			return fmt.Errorf("Source (\"source\" key) is required in Converge module dir #%d", i)
		}
		if dir.Destination == "" {
			return fmt.Errorf("Destination (\"destination\" key) is required in Converge module dir #%d", i)
		}
	}

	// validate modules
	if len(p.config.Modules) == 0 {
		return errors.New("Converge requires at least one module (\"modules\" key) to provision the system")
	}
	for i, module := range p.config.Modules {
		if module.Module == "" {
			return fmt.Errorf("Module (\"module\" key) is required in Converge module #%d", i)
		}
		if module.Directory == "" {
			p.config.Modules[i].Directory = "/tmp"
		}
	}

	return err
}

// Provision node somehow. TODO: actual docs
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Provisioning with Converge")

	// bootstrapping
	if err := p.maybeBootstrap(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	// send module directories to the remote host
	if err := p.sendModuleDirectories(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	// apply all the modules
	if err := p.applyModules(ui, comm); err != nil {
		return err // error messages are already user-friendly
	}

	return nil
}

func (p *Provisioner) maybeBootstrap(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.Bootstrap {
		return nil
	}
	ui.Message("bootstrapping converge")

	bootstrap, err := http.Get("https://get.converge.sh")
	if err != nil {
		return fmt.Errorf("Error downloading bootstrap script: %s", err) // TODO: is github.com/pkg/error allowed?
	}
	if err := comm.Upload("/tmp/install-converge.sh", bootstrap.Body, nil); err != nil {
		return fmt.Errorf("Error uploading script: %s", err)
	}
	if err := bootstrap.Body.Close(); err != nil {
		return fmt.Errorf("Error getting bootstrap script: %s", err)
	}

	// construct command
	command := "/bin/sh /tmp/install-converge.sh"
	if p.config.Version != "" {
		command += " -v " + p.config.Version
	}

	var out bytes.Buffer
	cmd := &packer.RemoteCmd{
		Command: command,
		Stdin:   nil,
		Stdout:  &out,
		Stderr:  &out,
	}

	if err = comm.Start(cmd); err != nil {
		return fmt.Errorf("Error bootstrapping converge: %s", err)
	}

	cmd.Wait()
	if cmd.ExitStatus != 0 {
		ui.Error(out.String())
		return errors.New("Error bootstrapping converge")
	}

	ui.Message(strings.TrimSpace(out.String()))
	return nil
}

func (p *Provisioner) sendModuleDirectories(ui packer.Ui, comm packer.Communicator) error {
	for _, dir := range p.config.ModuleDirs {
		if err := comm.UploadDir(dir.Destination, dir.Source, dir.Exclude); err != nil {
			return fmt.Errorf("Could not upload %q: %s", dir.Source, err)
		}
		ui.Message(fmt.Sprintf("transferred %q to %q", dir.Source, dir.Destination))
	}

	return nil
}

func (p *Provisioner) applyModules(ui packer.Ui, comm packer.Communicator) error {
	for _, module := range p.config.Modules {
		// create params JSON file
		params, err := json.Marshal(module.Params)
		if err != nil {
			return fmt.Errorf("Could not marshal parameters as JSON: %s", err)
		}

		// run Converge in the specified directory
		var runOut bytes.Buffer
		cmd := &packer.RemoteCmd{
			Command: fmt.Sprintf(
				"cd %s && converge apply --local --log-level=WARNING --paramsJSON '%s' %s",
				module.Directory,
				string(params),
				module.Module,
			),
			Stdin:  nil,
			Stdout: &runOut,
			Stderr: &runOut,
		}
		if err := comm.Start(cmd); err != nil {
			return fmt.Errorf("Error applying %q: %s", module.Module, err)
		}

		cmd.Wait()
		if cmd.ExitStatus == 127 {
			ui.Error("Could not find Converge. Is it installed and in PATH?")
			if !p.config.Bootstrap {
				ui.Error("Bootstrapping was disabled for this run. That might be why Converge isn't present.")
			}

			return errors.New("Could not find Converge")

		} else if cmd.ExitStatus != 0 {
			ui.Error(strings.TrimSpace(runOut.String()))
			ui.Error(fmt.Sprintf("exited with error code %d", cmd.ExitStatus))
			return fmt.Errorf("Error applying %q", module.Module)
		}

		ui.Message(strings.TrimSpace(runOut.String()))
	}

	return nil
}

// Cancel the provisioning process
func (p *Provisioner) Cancel() {
	log.Println("cancel called in Converge provisioner")
}
<|endoftext|>


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

package main

import (
	"github.com/globocom/tsuru/juju"
	"net/http"
)

// FilteredWriter is a custom writer
// that filter deprecation warnings and juju log output.
type FilteredWriter struct {
	writer http.ResponseWriter
}

// WriteHeader calls the w.Header
func (w *FilteredWriter) Header() http.Header {
	return w.writer.Header()
}

// Write writes and flushes the data, filtering the juju warnings.
func (w *FilteredWriter) Write(data []byte) (int, error) {
	if w.Header().Get("Content-Type") == "text" {
		data = juju.FilterOutput(data)
	}
	_, err := w.writer.Write(data)
	if f, ok := w.writer.(http.Flusher); ok {
		f.Flush()
	}
	// returning the len(data) to skip the 'short write' error
	return len(data), err
}

// WriteHeader calls the w.WriteHeader
func (w *FilteredWriter) WriteHeader(code int) {
	w.writer.WriteHeader(code)
}
<commit_msg>webserver: simplify FilteredWriter<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/globocom/tsuru/juju"
	"net/http"
)

// FilteredWriter is a custom writer
// that filter deprecation warnings and juju log output.
type FilteredWriter struct {
	http.ResponseWriter
}

// Write writes and flushes the data, filtering the juju warnings.
func (w *FilteredWriter) Write(data []byte) (int, error) {
	if w.Header().Get("Content-Type") == "text" {
		data = juju.FilterOutput(data)
	}
	_, err := w.ResponseWriter.Write(data)
	if f, ok := w.ResponseWriter.(http.Flusher); ok {
		f.Flush()
	}
	// returning the len(data) to skip the "short write" error
	return len(data), err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	"hermes/ratings/controller"
	"hermes/ratings/handler"

	"github.com/alecthomas/kingpin"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/labstack/echo"
)

var (
	app            = kingpin.New("hermes", "GCBA product ratings APIs.")
	startCommand   = kingpin.Command("start", "Start an Hermes API.")
	ratingsCommand = startCommand.Command("ratings", "Start the ratings API.")
	statsCommand   = startCommand.Command("stats", "Start the statistics API.")
	ratingsPort    = getRatingsPort()
	noCursor       = "\n\n\033[?25l"
	banner         = `
 _  _ ____ ____ _  _ ____ ____
 |__| |___ |__/ |\/| |___ [__
 |  | |___ |  \ |  | |___ ___] `
)

func main() {
	kingpin.Version("0.0.1")
	fmt.Println("\n", banner, "\n\n")

	switch kingpin.Parse() {
	case "start ratings":
		startRatingsAPI()
	case "start stats":
		startStatsAPI()
	}
}

func startRatingsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    controller.OptionsRoot,
		"OptionsRatings": controller.OptionsRatings,
		"PostRatings":    controller.PostRatings}

	handler, castOk := handler.Handler(ratingsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Server started on port", strconv.Itoa(ratingsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func startStatsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    controller.OptionsRoot,
		"OptionsRatings": controller.OptionsRatings,
		"PostRatings":    controller.PostRatings}

	handler, castOk := handler.Handler(ratingsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Server started on port", strconv.Itoa(ratingsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func getRatingsPort() int {
	port, portErr := strconv.Atoi(os.Getenv("HERMES_RATINGS_PORT"))

	if portErr != nil {
		return 5000
	}

	return port
}

func getStatsPort() int {
	port, portErr := strconv.Atoi(os.Getenv("HERMES_STATS_PORT"))

	if portErr != nil {
		return 5000
	}

	return port
}
<commit_msg>Used the right port<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	"hermes/ratings/controller"
	"hermes/ratings/handler"

	"github.com/alecthomas/kingpin"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/labstack/echo"
)

var (
	app            = kingpin.New("hermes", "GCBA product ratings APIs.")
	startCommand   = kingpin.Command("start", "Start an Hermes API.")
	ratingsCommand = startCommand.Command("ratings", "Start the ratings API.")
	statsCommand   = startCommand.Command("stats", "Start the statistics API.")
	ratingsPort    = getRatingsPort()
	statsPort      = getStatsPort()
	noCursor       = "\n\n\033[?25l"
	banner         = `
 _  _ ____ ____ _  _ ____ ____
 |__| |___ |__/ |\/| |___ [__
 |  | |___ |  \ |  | |___ ___] `
)

func main() {
	kingpin.Version("0.0.1")
	fmt.Println("\n", banner)

	switch kingpin.Parse() {
	case "start ratings":
		fmt.Print("	               ratings", "\n\n\n")
		startRatingsAPI()
	case "start stats":
		fmt.Print("	                 stats", "\n\n\n")
		startStatsAPI()
	}
}

func startRatingsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    controller.OptionsRoot,
		"OptionsRatings": controller.OptionsRatings,
		"PostRatings":    controller.PostRatings}

	handler, castOk := handler.Handler(ratingsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Ratings server started on port", strconv.Itoa(ratingsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func startStatsAPI() {
	routes := map[string]echo.HandlerFunc{
		"OptionsRoot":    controller.OptionsRoot,
		"OptionsRatings": controller.OptionsRatings,
		"PostRatings":    controller.PostRatings}

	handler, castOk := handler.Handler(statsPort, routes).(*echo.Echo)

	if !castOk {
		handler.Logger.Fatal("Could not start server")
	}

	fmt.Println("✅  Stats server started on port", strconv.Itoa(statsPort))
	fmt.Print(noCursor)

	handler.Logger.Fatal(gracehttp.Serve(handler.Server))
}

func getRatingsPort() int {
	port, portErr := strconv.Atoi(os.Getenv("HERMES_RATINGS_PORT"))

	if portErr != nil {
		return 5000
	}

	return port
}

func getStatsPort() int {
	port, portErr := strconv.Atoi(os.Getenv("HERMES_STATS_PORT"))

	if portErr != nil {
		return 7000
	}

	return port
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package unversioned

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

// TODO: We need to remove the GroupVersion in types.go. We use the name GroupVersion here temporarily.
// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
type GroupVersion struct {
	Group   string
	Version string
}

// String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1".
func (gv *GroupVersion) String() string {
	// special case of "v1" for backward compatibility
	if gv.Group == "" && gv.Version == "v1" {
		return gv.Version
	} else {
		return gv.Group + "/" + gv.Version
	}
}

// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) {
	s := strings.Split(gv, "/")
	// "v1" is the only special case. Otherwise GroupVersion is expected to contain
	// one "/" dividing the string into two parts.
	switch {
	case len(s) == 1 && gv == "v1":
		return GroupVersion{"", "v1"}, nil
	case len(s) == 2:
		return GroupVersion{s[0], s[1]}, nil
	default:
		return GroupVersion{}, fmt.Errorf("Unexpected GroupVersion string: %v", gv)
	}
}

// MarshalJSON implements the json.Marshaller interface.
func (gv GroupVersion) MarshalJSON() ([]byte, error) {
	s := gv.String()
	if strings.Count(s, "/") > 1 {
		return []byte{}, fmt.Errorf("illegal GroupVersion %v: contains more than one /", s)
	}
	return json.Marshal(s)
}

func (gv *GroupVersion) unmarshal(value []byte) error {
	var s string
	if err := json.Unmarshal(value, &s); err != nil {
		return err
	}
	parsed, err := ParseGroupVersion(s)
	if err != nil {
		return err
	}
	*gv = parsed
	return nil
}

// UnmarshalJSON implements the json.Unmarshaller interface.
func (gv *GroupVersion) UnmarshalJSON(value []byte) error {
	return gv.unmarshal(value)
}

// UnmarshalTEXT implements the Ugorji's encoding.TextUnmarshaler interface.
func (gv *GroupVersion) UnmarshalText(value []byte) error {
	return gv.unmarshal(value)
}
<commit_msg>use GroupVersion in APIGroupVersion for api installer<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package unversioned

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

// TODO: We need to remove the GroupVersion in types.go. We use the name GroupVersion here temporarily.
// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
type GroupVersion struct {
	Group   string
	Version string
}

// String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1".
func (gv *GroupVersion) String() string {
	// special case of "v1" for backward compatibility
	if gv.Group == "" && gv.Version == "v1" {
		return gv.Version
	} else {
		return gv.Group + "/" + gv.Version
	}
}

// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) {
	s := strings.Split(gv, "/")
	// "v1" is the only special case. Otherwise GroupVersion is expected to contain
	// one "/" dividing the string into two parts.
	switch {
	case len(s) == 1 && gv == "v1":
		return GroupVersion{"", "v1"}, nil
	case len(s) == 2:
		return GroupVersion{s[0], s[1]}, nil
	default:
		return GroupVersion{}, fmt.Errorf("Unexpected GroupVersion string: %v", gv)
	}
}

func ParseGroupVersionOrDie(gv string) GroupVersion {
	ret, err := ParseGroupVersion(gv)
	if err != nil {
		panic(err)
	}

	return ret
}

// MarshalJSON implements the json.Marshaller interface.
func (gv GroupVersion) MarshalJSON() ([]byte, error) {
	s := gv.String()
	if strings.Count(s, "/") > 1 {
		return []byte{}, fmt.Errorf("illegal GroupVersion %v: contains more than one /", s)
	}
	return json.Marshal(s)
}

func (gv *GroupVersion) unmarshal(value []byte) error {
	var s string
	if err := json.Unmarshal(value, &s); err != nil {
		return err
	}
	parsed, err := ParseGroupVersion(s)
	if err != nil {
		return err
	}
	*gv = parsed
	return nil
}

// UnmarshalJSON implements the json.Unmarshaller interface.
func (gv *GroupVersion) UnmarshalJSON(value []byte) error {
	return gv.unmarshal(value)
}

// UnmarshalTEXT implements the Ugorji's encoding.TextUnmarshaler interface.
func (gv *GroupVersion) UnmarshalText(value []byte) error {
	return gv.unmarshal(value)
}
<|endoftext|>


<commit_before>package gitserver

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/url"
	"os"

	"github.com/openshift/origin/pkg/cmd/templates"
	"github.com/spf13/cobra"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"

	"github.com/openshift/origin/pkg/gitserver"
	"github.com/openshift/origin/pkg/gitserver/autobuild"
)

const LogLevelEnv = "LOGLEVEL"

var (
	longCommandDesc = templates.LongDesc(`
		Start a Git server

		This command launches a Git HTTP/HTTPS server that supports push and pull, mirroring,
		and automatic creation of applications on push.

		%[1]s`)

	repositoryBuildConfigsDesc = templates.LongDesc(`
		Retrieve build configs for a gitserver repository

		This command lists build configurations in the current namespace that correspond to a given git repository.`)
)

// CommandFor returns the appropriate command for this base name,
// or the global OpenShift command
func CommandFor(basename string) *cobra.Command {
	var cmd *cobra.Command

	out := os.Stdout

	setLogLevel()

	switch basename {
	case "gitrepo-buildconfigs":
		cmd = NewCommandRepositoryBuildConfigs(basename, out)
	default:
		cmd = NewCommandGitServer("gitserver")
	}
	return cmd
}

// NewCommandGitServer launches a Git server
func NewCommandGitServer(name string) *cobra.Command {
	cmd := &cobra.Command{
		Use:   name,
		Short: "Start a Git server",
		Long:  fmt.Sprintf(longCommandDesc, gitserver.EnvironmentHelp),
		Run: func(c *cobra.Command, args []string) {
			err := RunGitServer()
			cmdutil.CheckErr(err)
		},
	}

	return cmd
}

func RunGitServer() error {
	config, err := gitserver.NewEnvironmentConfig()
	if err != nil {
		return err
	}
	link, err := autobuild.NewAutoLinkBuildsFromEnvironment()
	switch {
	case err == autobuild.ErrNotEnabled:
	case err != nil:
		log.Fatal(err)
	default:
		link.LinkFn = func(name string) *url.URL { return gitserver.RepositoryURL(config, name, nil) }
		clones, err := link.Link()
		if err != nil {
			log.Printf("error: %v", err)
			break
		}
		for name, v := range clones {
			config.InitialClones[name] = v
		}
	}
	return gitserver.Start(config)
}

func NewCommandRepositoryBuildConfigs(name string, out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   fmt.Sprintf("%s REPOSITORY_NAME", name),
		Short: "Retrieve build configs for a gitserver repository",
		Long:  repositoryBuildConfigsDesc,
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				err := cmdutil.UsageError(c, "This command takes a single argument - the name of the repository")
				cmdutil.CheckErr(err)
			}
			repoName := args[0]
			client, err := gitserver.GetClient()
			cmdutil.CheckErr(err)
			err = gitserver.GetRepositoryBuildConfigs(client, repoName, out)
			cmdutil.CheckErr(err)
		},
	}
	return cmd
}

func setLogLevel() {
	logLevel := os.Getenv(LogLevelEnv)
	if len(logLevel) > 0 {
		if flag.CommandLine.Lookup("v") != nil {
			flag.CommandLine.Set("v", logLevel)
		}
	}
}
<commit_msg>modify comment for CommandFor<commit_after>package gitserver

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/url"
	"os"

	"github.com/openshift/origin/pkg/cmd/templates"
	"github.com/spf13/cobra"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"

	"github.com/openshift/origin/pkg/gitserver"
	"github.com/openshift/origin/pkg/gitserver/autobuild"
)

const LogLevelEnv = "LOGLEVEL"

var (
	longCommandDesc = templates.LongDesc(`
		Start a Git server

		This command launches a Git HTTP/HTTPS server that supports push and pull, mirroring,
		and automatic creation of applications on push.

		%[1]s`)

	repositoryBuildConfigsDesc = templates.LongDesc(`
		Retrieve build configs for a gitserver repository

		This command lists build configurations in the current namespace that correspond to a given git repository.`)
)

// CommandFor returns gitrepo-buildconfigs command or gitserver command
func CommandFor(basename string) *cobra.Command {
	var cmd *cobra.Command

	out := os.Stdout

	setLogLevel()

	switch basename {
	case "gitrepo-buildconfigs":
		cmd = NewCommandRepositoryBuildConfigs(basename, out)
	default:
		cmd = NewCommandGitServer("gitserver")
	}
	return cmd
}

// NewCommandGitServer launches a Git server
func NewCommandGitServer(name string) *cobra.Command {
	cmd := &cobra.Command{
		Use:   name,
		Short: "Start a Git server",
		Long:  fmt.Sprintf(longCommandDesc, gitserver.EnvironmentHelp),
		Run: func(c *cobra.Command, args []string) {
			err := RunGitServer()
			cmdutil.CheckErr(err)
		},
	}

	return cmd
}

func RunGitServer() error {
	config, err := gitserver.NewEnvironmentConfig()
	if err != nil {
		return err
	}
	link, err := autobuild.NewAutoLinkBuildsFromEnvironment()
	switch {
	case err == autobuild.ErrNotEnabled:
	case err != nil:
		log.Fatal(err)
	default:
		link.LinkFn = func(name string) *url.URL { return gitserver.RepositoryURL(config, name, nil) }
		clones, err := link.Link()
		if err != nil {
			log.Printf("error: %v", err)
			break
		}
		for name, v := range clones {
			config.InitialClones[name] = v
		}
	}
	return gitserver.Start(config)
}

func NewCommandRepositoryBuildConfigs(name string, out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   fmt.Sprintf("%s REPOSITORY_NAME", name),
		Short: "Retrieve build configs for a gitserver repository",
		Long:  repositoryBuildConfigsDesc,
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				err := cmdutil.UsageError(c, "This command takes a single argument - the name of the repository")
				cmdutil.CheckErr(err)
			}
			repoName := args[0]
			client, err := gitserver.GetClient()
			cmdutil.CheckErr(err)
			err = gitserver.GetRepositoryBuildConfigs(client, repoName, out)
			cmdutil.CheckErr(err)
		},
	}
	return cmd
}

func setLogLevel() {
	logLevel := os.Getenv(LogLevelEnv)
	if len(logLevel) > 0 {
		if flag.CommandLine.Lookup("v") != nil {
			flag.CommandLine.Set("v", logLevel)
		}
	}
}
<|endoftext|>