<commit_before>package core

import (
	"context"
	"sync"

	"v2ray.com/core/common"
	"v2ray.com/core/common/serial"
	"v2ray.com/core/features"
	"v2ray.com/core/features/dns"
	"v2ray.com/core/features/inbound"
	"v2ray.com/core/features/outbound"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/features/routing"
)

// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
type Server interface {
	common.Runnable
}

// ServerType returns the type of the server.
func ServerType() interface{} {
	return (*Instance)(nil)
}

type resolution struct {
	deps     []interface{}
	callback func([]features.Feature)
}

func getFeature(allFeatures []features.Feature, t interface{}) features.Feature {
	for _, f := range allFeatures {
		if f.Type() == t {
			return f
		}
	}
	return nil
}

func (r *resolution) resolve(allFeatures []features.Feature) bool {
	var fs []features.Feature
	for _, d := range r.deps {
		f := getFeature(allFeatures, d)
		if f == nil {
			return false
		}
		fs = append(fs, f)
	}

	r.callback(fs)
	return true
}

// Instance combines all functionalities in V2Ray.
type Instance struct {
	access             sync.Mutex
	features           []features.Feature
	featureResolutions []resolution
	running            bool
}

// New returns a new V2Ray instance based on given configuration.
// The instance is not started at this point.
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
func New(config *Config) (*Instance, error) {
	var server = &Instance{}

	if config.Transport != nil {
		features.PrintDeprecatedFeatureWarning("global transport settings")
	}
	if err := config.Transport.Apply(); err != nil {
		return nil, err
	}

	for _, appSettings := range config.App {
		settings, err := appSettings.GetInstance()
		if err != nil {
			return nil, err
		}
		obj, err := CreateObject(server, settings)
		if err != nil {
			return nil, err
		}
		if feature, ok := obj.(features.Feature); ok {
			server.AddFeature(feature)
		}
	}

	if server.GetFeature(dns.ClientType()) == nil {
		server.AddFeature(dns.LocalClient{})
	}

	if server.GetFeature(policy.ManagerType()) == nil {
		server.AddFeature(policy.DefaultManager{})
	}

	if server.GetFeature(routing.RouterType()) == nil {
		server.AddFeature(routing.DefaultRouter{})
	}

	// Add an empty instance at the end, for optional feature requirement.
	server.AddFeature(&Instance{})

	if server.featureResolutions != nil {
		return nil, newError("not all dependency are resolved.")
	}

	if len(config.Inbound) > 0 {
		inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
		for _, inboundConfig := range config.Inbound {
			rawHandler, err := CreateObject(server, inboundConfig)
			if err != nil {
				return nil, err
			}
			handler, ok := rawHandler.(inbound.Handler)
			if !ok {
				return nil, newError("not an InboundHandler")
			}
			if err := inboundManager.AddHandler(context.Background(), handler); err != nil {
				return nil, err
			}
		}
	}

	if len(config.Outbound) > 0 {
		outboundManager := server.GetFeature(outbound.ManagerType()).(outbound.Manager)
		for _, outboundConfig := range config.Outbound {
			rawHandler, err := CreateObject(server, outboundConfig)
			if err != nil {
				return nil, err
			}
			handler, ok := rawHandler.(outbound.Handler)
			if !ok {
				return nil, newError("not an OutboundHandler")
			}
			if err := outboundManager.AddHandler(context.Background(), handler); err != nil {
				return nil, err
			}
		}
	}

	return server, nil
}

// Type implements common.HasType.
func (s *Instance) Type() interface{} {
	return ServerType()
}

// Close shutdown the V2Ray instance.
func (s *Instance) Close() error {
	s.access.Lock()
	defer s.access.Unlock()

	s.running = false

	var errors []interface{}
	for _, f := range s.features {
		if err := f.Close(); err != nil {
			errors = append(errors, err)
		}
	}
	if len(errors) > 0 {
		return newError("failed to close all features").Base(newError(serial.Concat(errors...)))
	}

	return nil
}

// RequireFeatures registers a callback, which will be called when all dependent features are registered.
func (s *Instance) RequireFeatures(featureTypes []interface{}, callback func([]features.Feature)) {
	r := resolution{
		deps:     featureTypes,
		callback: callback,
	}
	if r.resolve(s.features) {
		return
	}
	s.featureResolutions = append(s.featureResolutions, r)
}

// AddFeature registers a feature into current Instance.
func (s *Instance) AddFeature(feature features.Feature) {
	s.features = append(s.features, feature)

	if s.running {
		if err := feature.Start(); err != nil {
			newError("failed to start feature").Base(err).WriteToLog()
		}
		return
	}

	if s.featureResolutions == nil {
		return
	}

	var pendingResolutions []resolution
	for _, r := range s.featureResolutions {
		if !r.resolve(s.features) {
			pendingResolutions = append(pendingResolutions, r)
		}
	}
	if len(pendingResolutions) == 0 {
		s.featureResolutions = nil
	} else if len(pendingResolutions) < len(s.featureResolutions) {
		s.featureResolutions = pendingResolutions
	}
}

// GetFeature returns a feature of the given type, or nil if such feature is not registered.
func (s *Instance) GetFeature(featureType interface{}) features.Feature {
	return getFeature(s.features, featureType)
}

// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
func (s *Instance) Start() error {
	s.access.Lock()
	defer s.access.Unlock()

	s.running = true
	for _, f := range s.features {
		if err := f.Start(); err != nil {
			return err
		}
	}

	newError("V2Ray ", Version(), " started").AtWarning().WriteToLog()

	return nil
}
<commit_msg>refactor new instance function<commit_after>package core

import (
	"context"
	"sync"

	"v2ray.com/core/common"
	"v2ray.com/core/common/serial"
	"v2ray.com/core/features"
	"v2ray.com/core/features/dns"
	"v2ray.com/core/features/inbound"
	"v2ray.com/core/features/outbound"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/features/routing"
)

// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
type Server interface {
	common.Runnable
}

// ServerType returns the type of the server.
func ServerType() interface{} {
	return (*Instance)(nil)
}

type resolution struct {
	deps     []interface{}
	callback func([]features.Feature)
}

func getFeature(allFeatures []features.Feature, t interface{}) features.Feature {
	for _, f := range allFeatures {
		if f.Type() == t {
			return f
		}
	}
	return nil
}

func (r *resolution) resolve(allFeatures []features.Feature) bool {
	var fs []features.Feature
	for _, d := range r.deps {
		f := getFeature(allFeatures, d)
		if f == nil {
			return false
		}
		fs = append(fs, f)
	}

	r.callback(fs)
	return true
}

// Instance combines all functionalities in V2Ray.
type Instance struct {
	access             sync.Mutex
	features           []features.Feature
	featureResolutions []resolution
	running            bool
}

func addInboundHandlers(server *Instance, configs []*InboundHandlerConfig) error {
	if len(configs) == 0 {
		return nil
	}

	inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
	for _, inboundConfig := range configs {
		rawHandler, err := CreateObject(server, inboundConfig)
		if err != nil {
			return err
		}
		handler, ok := rawHandler.(inbound.Handler)
		if !ok {
			return newError("not an InboundHandler")
		}
		if err := inboundManager.AddHandler(context.Background(), handler); err != nil {
			return err
		}
	}

	return nil
}

func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) error {
	if len(configs) == 0 {
		return nil
	}

	outboundManager := server.GetFeature(outbound.ManagerType()).(outbound.Manager)
	for _, outboundConfig := range configs {
		rawHandler, err := CreateObject(server, outboundConfig)
		if err != nil {
			return err
		}
		handler, ok := rawHandler.(outbound.Handler)
		if !ok {
			return newError("not an OutboundHandler")
		}
		if err := outboundManager.AddHandler(context.Background(), handler); err != nil {
			return err
		}
	}

	return nil
}

// New returns a new V2Ray instance based on given configuration.
// The instance is not started at this point.
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
func New(config *Config) (*Instance, error) {
	var server = &Instance{}

	if config.Transport != nil {
		features.PrintDeprecatedFeatureWarning("global transport settings")
	}
	if err := config.Transport.Apply(); err != nil {
		return nil, err
	}

	for _, appSettings := range config.App {
		settings, err := appSettings.GetInstance()
		if err != nil {
			return nil, err
		}
		obj, err := CreateObject(server, settings)
		if err != nil {
			return nil, err
		}
		if feature, ok := obj.(features.Feature); ok {
			server.AddFeature(feature)
		}
	}

	if server.GetFeature(dns.ClientType()) == nil {
		server.AddFeature(dns.LocalClient{})
	}

	if server.GetFeature(policy.ManagerType()) == nil {
		server.AddFeature(policy.DefaultManager{})
	}

	if server.GetFeature(routing.RouterType()) == nil {
		server.AddFeature(routing.DefaultRouter{})
	}

	// Add an empty instance at the end, for optional feature requirement.
	server.AddFeature(&Instance{})

	if server.featureResolutions != nil {
		return nil, newError("not all dependency are resolved.")
	}

	if err := addInboundHandlers(server, config.Inbound); err != nil {
		return nil, err
	}

	if err := addOutboundHandlers(server, config.Outbound); err != nil {
		return nil, err
	}

	return server, nil
}

// Type implements common.HasType.
func (s *Instance) Type() interface{} {
	return ServerType()
}

// Close shutdown the V2Ray instance.
func (s *Instance) Close() error {
	s.access.Lock()
	defer s.access.Unlock()

	s.running = false

	var errors []interface{}
	for _, f := range s.features {
		if err := f.Close(); err != nil {
			errors = append(errors, err)
		}
	}
	if len(errors) > 0 {
		return newError("failed to close all features").Base(newError(serial.Concat(errors...)))
	}

	return nil
}

// RequireFeatures registers a callback, which will be called when all dependent features are registered.
func (s *Instance) RequireFeatures(featureTypes []interface{}, callback func([]features.Feature)) {
	r := resolution{
		deps:     featureTypes,
		callback: callback,
	}
	if r.resolve(s.features) {
		return
	}
	s.featureResolutions = append(s.featureResolutions, r)
}

// AddFeature registers a feature into current Instance.
func (s *Instance) AddFeature(feature features.Feature) {
	s.features = append(s.features, feature)

	if s.running {
		if err := feature.Start(); err != nil {
			newError("failed to start feature").Base(err).WriteToLog()
		}
		return
	}

	if s.featureResolutions == nil {
		return
	}

	var pendingResolutions []resolution
	for _, r := range s.featureResolutions {
		if !r.resolve(s.features) {
			pendingResolutions = append(pendingResolutions, r)
		}
	}
	if len(pendingResolutions) == 0 {
		s.featureResolutions = nil
	} else if len(pendingResolutions) < len(s.featureResolutions) {
		s.featureResolutions = pendingResolutions
	}
}

// GetFeature returns a feature of the given type, or nil if such feature is not registered.
func (s *Instance) GetFeature(featureType interface{}) features.Feature {
	return getFeature(s.features, featureType)
}

// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
func (s *Instance) Start() error {
	s.access.Lock()
	defer s.access.Unlock()

	s.running = true
	for _, f := range s.features {
		if err := f.Start(); err != nil {
			return err
		}
	}

	newError("V2Ray ", Version(), " started").AtWarning().WriteToLog()

	return nil
}
<|endoftext|>


<commit_before>package pongo2

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type Value struct {
	v reflect.Value
}

// Converts any given value to a pongo2.Value
// Usually being used within own functions passed to a template
// through a Context or within filter functions.
//
// Example:
//     AsValue("my string")
func AsValue(i interface{}) *Value {
	return &Value{
		v: reflect.ValueOf(i),
	}
}

func (v *Value) getResolvedValue() reflect.Value {
	if v.v.IsValid() && v.v.Kind() == reflect.Ptr {
		return v.v.Elem()
	}
	return v.v
}

// Checks whether the underlying value is a string
func (v *Value) IsString() bool {
	return v.getResolvedValue().Kind() == reflect.String
}

// Checks whether the underlying value is a float
func (v *Value) IsFloat() bool {
	return v.getResolvedValue().Kind() == reflect.Float32 ||
		v.getResolvedValue().Kind() == reflect.Float64
}

// Checks whether the underlying value is an integer
func (v *Value) IsInteger() bool {
	return v.getResolvedValue().Kind() == reflect.Int ||
		v.getResolvedValue().Kind() == reflect.Int8 ||
		v.getResolvedValue().Kind() == reflect.Int16 ||
		v.getResolvedValue().Kind() == reflect.Int32 ||
		v.getResolvedValue().Kind() == reflect.Int64 ||
		v.getResolvedValue().Kind() == reflect.Uint ||
		v.getResolvedValue().Kind() == reflect.Uint8 ||
		v.getResolvedValue().Kind() == reflect.Uint16 ||
		v.getResolvedValue().Kind() == reflect.Uint32 ||
		v.getResolvedValue().Kind() == reflect.Uint64
}

// Checks whether the underlying value is either an integer
// or a float.
func (v *Value) IsNumber() bool {
	return v.IsInteger() || v.IsFloat()
}

// Checks whether the underlying value is NIL
func (v *Value) IsNil() bool {
	//fmt.Printf("%+v\n", v.getResolvedValue().Type().String())
	return !v.getResolvedValue().IsValid()
}

// Returns a string for the underlying value. If this value is not
// of type string, pongo2 tries to convert it. Currently the following
// types for underlying values are supported:
//
//     1. string
//     2. int/uint (any size)
//     3. float (any precision)
//     4. bool
//     5. time.Time
//
// NIL values will lead to an empty string. Unsupported types are leading
// to their respective type name.
func (v *Value) String() string {
	if v.IsNil() {
		return ""
	}

	switch v.getResolvedValue().Kind() {
	case reflect.String:
		return v.getResolvedValue().String()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(v.getResolvedValue().Int(), 10)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.FormatUint(v.getResolvedValue().Uint(), 10)
	case reflect.Float32, reflect.Float64:
		return fmt.Sprintf("%f", v.getResolvedValue().Float())
	case reflect.Bool:
		if v.Bool() {
			return "True"
		} else {
			return "False"
		}
	case reflect.Struct:
		if v.getResolvedValue().Type() == reflect.TypeOf(time.Time{}) {
			return v.getResolvedValue().Interface().(time.Time).String()
		}
	}

	logf("Value.String() not implemented for type: %s\n", v.getResolvedValue().Kind().String())
	return v.getResolvedValue().String()
}

// Returns the underlying value as an integer (converts the underlying
// value, if necessary). If it's not possible to convert the underlying value,
// it will return 0.
func (v *Value) Integer() int {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int(v.getResolvedValue().Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int(v.getResolvedValue().Uint())
	case reflect.Float32, reflect.Float64:
		return int(v.getResolvedValue().Float())
	case reflect.String:
		// Try to convert from string to int (base 10)
		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
		if err != nil {
			return 0
		}
		return int(f)
	default:
		logf("Value.Integer() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0
	}
}

// Returns the underlying value as a float (converts the underlying
// value, if necessary). If it's not possible to convert the underlying value,
// it will return 0.0.
func (v *Value) Float() float64 {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return float64(v.getResolvedValue().Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return float64(v.getResolvedValue().Uint())
	case reflect.Float32, reflect.Float64:
		return v.getResolvedValue().Float()
	case reflect.String:
		// Try to convert from string to float64 (base 10)
		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
		if err != nil {
			return 0.0
		}
		return f
	default:
		logf("Value.Float() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0.0
	}
}

// Returns the underlying value as bool. If the value is not bool, false
// will always be returned. If you're looking for true/false-evaluation of the
// underlying value, have a look on the IsTrue()-function.
func (v *Value) Bool() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Bool:
		return v.getResolvedValue().Bool()
	default:
		logf("Value.Bool() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Tried to evaluate the underlying value the Pythonic-way:
//
// Returns TRUE in one the following cases:
//
//     * int != 0
//     * uint != 0
//     * float != 0.0
//     * len(array/chan/map/slice/string) > 0
//     * bool == true
//
// Otherwise returns always FALSE.
func (v *Value) IsTrue() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.getResolvedValue().Int() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return v.getResolvedValue().Uint() != 0
	case reflect.Float32, reflect.Float64:
		return v.getResolvedValue().Float() != 0
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return v.getResolvedValue().Len() > 0
	case reflect.Bool:
		return v.getResolvedValue().Bool()
	default:
		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Tries to negate the underlying value. It's mainly used for
// the NOT-operator and in conjunction with a call to
// return_value.IsTrue() afterwards.
//
// Example:
//     AsValue(1).Negate().IsTrue() == false
func (v *Value) Negate() *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if v.Integer() != 0 {
			return AsValue(0)
		} else {
			return AsValue(1)
		}
	case reflect.Float32, reflect.Float64:
		if v.Float() != 0.0 {
			return AsValue(float64(0.0))
		} else {
			return AsValue(float64(1.1))
		}
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return AsValue(v.getResolvedValue().Len() == 0)
	case reflect.Bool:
		return AsValue(!v.getResolvedValue().Bool())
	default:
		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue(true)
	}
}

// Returns the length for an array, chan, map, slice or string.
// Otherwise it will return 0.
func (v *Value) Len() int {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return v.getResolvedValue().Len()
	default:
		logf("Value.Len() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0
	}
}

// Slices an array, slice or string. Otherwise it will
// return an empty []int.
func (v *Value) Slice(i, j int) *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		return AsValue(v.getResolvedValue().Slice(i, j).Interface())
	default:
		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue([]int{})
	}
}

// Get the i-th item of an array, slice or string. Otherwise
// it will return NIL.
func (v *Value) Index(i int) *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice:
		if i >= v.Len() {
			return AsValue(nil)
		}
		return AsValue(v.getResolvedValue().Index(i).Interface())
	case reflect.String:
		return AsValue(v.getResolvedValue().Slice(i, i+1).Interface())
	default:
		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue([]int{})
	}
}

// Checks whether the underlying value (which must be of type struct, map,
// string, array or slice) contains of another Value (e. g. used to check
// whether a struct contains of a specific field or a map contains a specific key).
//
// Example:
//     AsValue("Hello, World!").Contains(AsValue("World")) == true
func (v *Value) Contains(other *Value) bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Struct:
		field_value := v.getResolvedValue().FieldByName(other.String())
		return field_value.IsValid()
	case reflect.Map:
		var map_value reflect.Value
		switch other.Interface().(type) {
		case int:
			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
		case string:
			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
		default:
			logf("Value.Contains() does not support lookup type '%s'\n", other.getResolvedValue().Kind().String())
			return false
		}

		return map_value.IsValid()
	case reflect.String:
		return strings.Contains(v.getResolvedValue().String(), other.String())

	// TODO: reflect.Array, reflect.Slice

	default:
		logf("Value.Contains() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Checks whether the underlying value is of type array, slice or string.
// You normally would use CanSlice() before using the Slice() operation.
func (v *Value) CanSlice() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		return true
	}
	return false
}

// Iterates over a map, array, slice or a string. It calls the
// function's first argument for every value with the following arguments:
//
//     idx      current 0-index
//     count    total amount of items
//     key      *Value for the key or item
//     value    *Value (only for maps, the respective value for a specific key)
//
// If the underlying value has no items or is not one of the types above,
// the empty function (function's second argument) will be called.
func (v *Value) Iterate(fn func(idx, count int, key, value *Value) bool, empty func()) {
	switch v.getResolvedValue().Kind() {
	case reflect.Map:
		keys := v.getResolvedValue().MapKeys()
		keyLen := len(keys)
		for idx, key := range keys {
			value := v.getResolvedValue().MapIndex(key)
			if !fn(idx, keyLen, &Value{key}, &Value{value}) {
				return
			}
		}
		if keyLen == 0 {
			empty()
		}
		return // done
	case reflect.Array, reflect.Slice:
		itemCount := v.getResolvedValue().Len()
		if itemCount > 0 {
			for i := 0; i < itemCount; i++ {
				if !fn(i, itemCount, &Value{v.getResolvedValue().Index(i)}, nil) {
					return
				}
			}
		} else {
			empty()
		}
		return // done
	case reflect.String:
		runeCount := v.getResolvedValue().Len()
		if runeCount > 0 {
			for i := 0; i < runeCount; i++ {
				if !fn(i, runeCount, &Value{v.getResolvedValue().Slice(i, i+1)}, nil) {
					return
				}
			}
		} else {
			empty()
		}
		return // done
	default:
		logf("Value.Iterate() not available for type: %s\n", v.getResolvedValue().Kind().String())
	}
	empty()
}

// Gives you access to the underlying value.
func (v *Value) Interface() interface{} {
	if v.v.IsValid() {
		return v.v.Interface()
	}
	return nil
}

// Checks whether two values are containing the same value or object.
func (v *Value) EqualValueTo(other *Value) bool {
	return v.Interface() == other.Interface()
}
<commit_msg>Value.IsBool() added<commit_after>package pongo2

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type Value struct {
	v reflect.Value
}

// Converts any given value to a pongo2.Value
// Usually being used within own functions passed to a template
// through a Context or within filter functions.
//
// Example:
//     AsValue("my string")
func AsValue(i interface{}) *Value {
	return &Value{
		v: reflect.ValueOf(i),
	}
}

func (v *Value) getResolvedValue() reflect.Value {
	if v.v.IsValid() && v.v.Kind() == reflect.Ptr {
		return v.v.Elem()
	}
	return v.v
}

// Checks whether the underlying value is a string
func (v *Value) IsString() bool {
	return v.getResolvedValue().Kind() == reflect.String
}

// Checks whether the underlying value is a bool
func (v *Value) IsBool() bool {
	return v.getResolvedValue().Kind() == reflect.Bool
}

// Checks whether the underlying value is a float
func (v *Value) IsFloat() bool {
	return v.getResolvedValue().Kind() == reflect.Float32 ||
		v.getResolvedValue().Kind() == reflect.Float64
}

// Checks whether the underlying value is an integer
func (v *Value) IsInteger() bool {
	return v.getResolvedValue().Kind() == reflect.Int ||
		v.getResolvedValue().Kind() == reflect.Int8 ||
		v.getResolvedValue().Kind() == reflect.Int16 ||
		v.getResolvedValue().Kind() == reflect.Int32 ||
		v.getResolvedValue().Kind() == reflect.Int64 ||
		v.getResolvedValue().Kind() == reflect.Uint ||
		v.getResolvedValue().Kind() == reflect.Uint8 ||
		v.getResolvedValue().Kind() == reflect.Uint16 ||
		v.getResolvedValue().Kind() == reflect.Uint32 ||
		v.getResolvedValue().Kind() == reflect.Uint64
}

// Checks whether the underlying value is either an integer
// or a float.
func (v *Value) IsNumber() bool {
	return v.IsInteger() || v.IsFloat()
}

// Checks whether the underlying value is NIL
func (v *Value) IsNil() bool {
	//fmt.Printf("%+v\n", v.getResolvedValue().Type().String())
	return !v.getResolvedValue().IsValid()
}

// Returns a string for the underlying value. If this value is not
// of type string, pongo2 tries to convert it. Currently the following
// types for underlying values are supported:
//
//     1. string
//     2. int/uint (any size)
//     3. float (any precision)
//     4. bool
//     5. time.Time
//
// NIL values will lead to an empty string. Unsupported types are leading
// to their respective type name.
func (v *Value) String() string {
	if v.IsNil() {
		return ""
	}

	switch v.getResolvedValue().Kind() {
	case reflect.String:
		return v.getResolvedValue().String()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(v.getResolvedValue().Int(), 10)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.FormatUint(v.getResolvedValue().Uint(), 10)
	case reflect.Float32, reflect.Float64:
		return fmt.Sprintf("%f", v.getResolvedValue().Float())
	case reflect.Bool:
		if v.Bool() {
			return "True"
		} else {
			return "False"
		}
	case reflect.Struct:
		if v.getResolvedValue().Type() == reflect.TypeOf(time.Time{}) {
			return v.getResolvedValue().Interface().(time.Time).String()
		}
	}

	logf("Value.String() not implemented for type: %s\n", v.getResolvedValue().Kind().String())
	return v.getResolvedValue().String()
}

// Returns the underlying value as an integer (converts the underlying
// value, if necessary). If it's not possible to convert the underlying value,
// it will return 0.
func (v *Value) Integer() int {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int(v.getResolvedValue().Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int(v.getResolvedValue().Uint())
	case reflect.Float32, reflect.Float64:
		return int(v.getResolvedValue().Float())
	case reflect.String:
		// Try to convert from string to int (base 10)
		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
		if err != nil {
			return 0
		}
		return int(f)
	default:
		logf("Value.Integer() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0
	}
}

// Returns the underlying value as a float (converts the underlying
// value, if necessary). If it's not possible to convert the underlying value,
// it will return 0.0.
func (v *Value) Float() float64 {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return float64(v.getResolvedValue().Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return float64(v.getResolvedValue().Uint())
	case reflect.Float32, reflect.Float64:
		return v.getResolvedValue().Float()
	case reflect.String:
		// Try to convert from string to float64 (base 10)
		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
		if err != nil {
			return 0.0
		}
		return f
	default:
		logf("Value.Float() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0.0
	}
}

// Returns the underlying value as bool. If the value is not bool, false
// will always be returned. If you're looking for true/false-evaluation of the
// underlying value, have a look on the IsTrue()-function.
func (v *Value) Bool() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Bool:
		return v.getResolvedValue().Bool()
	default:
		logf("Value.Bool() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Tried to evaluate the underlying value the Pythonic-way:
//
// Returns TRUE in one the following cases:
//
//     * int != 0
//     * uint != 0
//     * float != 0.0
//     * len(array/chan/map/slice/string) > 0
//     * bool == true
//
// Otherwise returns always FALSE.
func (v *Value) IsTrue() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.getResolvedValue().Int() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return v.getResolvedValue().Uint() != 0
	case reflect.Float32, reflect.Float64:
		return v.getResolvedValue().Float() != 0
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return v.getResolvedValue().Len() > 0
	case reflect.Bool:
		return v.getResolvedValue().Bool()
	default:
		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Tries to negate the underlying value. It's mainly used for
// the NOT-operator and in conjunction with a call to
// return_value.IsTrue() afterwards.
//
// Example:
//     AsValue(1).Negate().IsTrue() == false
func (v *Value) Negate() *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if v.Integer() != 0 {
			return AsValue(0)
		} else {
			return AsValue(1)
		}
	case reflect.Float32, reflect.Float64:
		if v.Float() != 0.0 {
			return AsValue(float64(0.0))
		} else {
			return AsValue(float64(1.1))
		}
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return AsValue(v.getResolvedValue().Len() == 0)
	case reflect.Bool:
		return AsValue(!v.getResolvedValue().Bool())
	default:
		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue(true)
	}
}

// Returns the length for an array, chan, map, slice or string.
// Otherwise it will return 0.
func (v *Value) Len() int {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
		return v.getResolvedValue().Len()
	default:
		logf("Value.Len() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return 0
	}
}

// Slices an array, slice or string. Otherwise it will
// return an empty []int.
func (v *Value) Slice(i, j int) *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		return AsValue(v.getResolvedValue().Slice(i, j).Interface())
	default:
		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue([]int{})
	}
}

// Get the i-th item of an array, slice or string. Otherwise
// it will return NIL.
func (v *Value) Index(i int) *Value {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice:
		if i >= v.Len() {
			return AsValue(nil)
		}
		return AsValue(v.getResolvedValue().Index(i).Interface())
	case reflect.String:
		return AsValue(v.getResolvedValue().Slice(i, i+1).Interface())
	default:
		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return AsValue([]int{})
	}
}

// Checks whether the underlying value (which must be of type struct, map,
// string, array or slice) contains of another Value (e. g. used to check
// whether a struct contains of a specific field or a map contains a specific key).
//
// Example:
//     AsValue("Hello, World!").Contains(AsValue("World")) == true
func (v *Value) Contains(other *Value) bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Struct:
		field_value := v.getResolvedValue().FieldByName(other.String())
		return field_value.IsValid()
	case reflect.Map:
		var map_value reflect.Value
		switch other.Interface().(type) {
		case int:
			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
		case string:
			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
		default:
			logf("Value.Contains() does not support lookup type '%s'\n", other.getResolvedValue().Kind().String())
			return false
		}

		return map_value.IsValid()
	case reflect.String:
		return strings.Contains(v.getResolvedValue().String(), other.String())

	// TODO: reflect.Array, reflect.Slice

	default:
		logf("Value.Contains() not available for type: %s\n", v.getResolvedValue().Kind().String())
		return false
	}
}

// Checks whether the underlying value is of type array, slice or string.
// You normally would use CanSlice() before using the Slice() operation.
func (v *Value) CanSlice() bool {
	switch v.getResolvedValue().Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		return true
	}
	return false
}

// Iterates over a map, array, slice or a string. It calls the
// function's first argument for every value with the following arguments:
//
//     idx      current 0-index
//     count    total amount of items
//     key      *Value for the key or item
//     value    *Value (only for maps, the respective value for a specific key)
//
// If the underlying value has no items or is not one of the types above,
// the empty function (function's second argument) will be called.
func (v *Value) Iterate(fn func(idx, count int, key, value *Value) bool, empty func()) {
	switch v.getResolvedValue().Kind() {
	case reflect.Map:
		keys := v.getResolvedValue().MapKeys()
		keyLen := len(keys)
		for idx, key := range keys {
			value := v.getResolvedValue().MapIndex(key)
			if !fn(idx, keyLen, &Value{key}, &Value{value}) {
				return
			}
		}
		if keyLen == 0 {
			empty()
		}
		return // done
	case reflect.Array, reflect.Slice:
		itemCount := v.getResolvedValue().Len()
		if itemCount > 0 {
			for i := 0; i < itemCount; i++ {
				if !fn(i, itemCount, &Value{v.getResolvedValue().Index(i)}, nil) {
					return
				}
			}
		} else {
			empty()
		}
		return // done
	case reflect.String:
		runeCount := v.getResolvedValue().Len()
		if runeCount > 0 {
			for i := 0; i < runeCount; i++ {
				if !fn(i, runeCount, &Value{v.getResolvedValue().Slice(i, i+1)}, nil) {
					return
				}
			}
		} else {
			empty()
		}
		return // done
	default:
		logf("Value.Iterate() not available for type: %s\n", v.getResolvedValue().Kind().String())
	}
	empty()
}

// Gives you access to the underlying value.
func (v *Value) Interface() interface{} {
	if v.v.IsValid() {
		return v.v.Interface()
	}
	return nil
}

// Checks whether two values are containing the same value or object.
func (v *Value) EqualValueTo(other *Value) bool {
	return v.Interface() == other.Interface()
}
<|endoftext|>


<commit_before>// Copyright 2015 The draw2d Authors. All rights reserved.
// created: 26/06/2015 by Stani Michiels
// TODO: fonts, dpi

package pdf2d

import (
	"bytes"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"strconv"

	"code.google.com/p/freetype-go/freetype/truetype"

	"github.com/stanim/draw2d"
	"github.com/stanim/gofpdf"
)

var (
	caps = map[draw2d.Cap]string{
		draw2d.RoundCap:  "round",
		draw2d.ButtCap:   "butt",
		draw2d.SquareCap: "square"}
)

const c255 = 255.0 / 65535.0

var (
	imageCount uint32
	white      color.Color = color.RGBA{255, 255, 255, 255}
)

// NewPdf creates a new pdf document with the draw2d fontfolder, adds
// a page and set fill color to white.
func NewPdf(orientationStr, unitStr, sizeStr string) *gofpdf.Fpdf {
	pdf := gofpdf.New(orientationStr, unitStr, sizeStr, draw2d.GetFontFolder())
	pdf.AddPage()
	pdf.SetFillColor(255, 255, 255) // to be compatible with draw2d
	return pdf
}

// rgb converts a color (used by draw2d) into 3 int (used by gofpdf)
func rgb(c color.Color) (int, int, int) {
	r, g, b, _ := c.RGBA()
	return int(float64(r) * c255), int(float64(g) * c255), int(float64(b) * c255)
}

// clearRect draws a white rectangle
func clearRect(gc *GraphicContext, x1, y1, x2, y2 float64) {
	// save state
	f := gc.Current.FillColor
	x, y := gc.pdf.GetXY()
	// cover page with white rectangle
	gc.SetFillColor(white)
	draw2d.Rect(gc, x1, y1, x2, y2)
	gc.Fill()
	// restore state
	gc.SetFillColor(f)
	gc.pdf.MoveTo(x, y)
}

// GraphicContext implements the draw2d.GraphicContext interface
// It provides draw2d with a pdf backend (based on gofpdf)
type GraphicContext struct {
	*draw2d.StackGraphicContext
	pdf *gofpdf.Fpdf
	DPI int
}

// NewGraphicContext creates a new pdf GraphicContext
func NewGraphicContext(pdf *gofpdf.Fpdf) *GraphicContext {
	dpi := 92
	return &GraphicContext{draw2d.NewStackGraphicContext(), pdf, dpi}
}

// DrawImage draws an image as PNG
// TODO: add type (tp) as parameter to argument list?
func (gc *GraphicContext) DrawImage(image image.Image) {
	name := strconv.Itoa(int(imageCount))
	tp := "PNG" // "JPG", "JPEG", "PNG" and "GIF"
	b := &bytes.Buffer{}
	png.Encode(b, image)
	gc.pdf.RegisterImageReader(name, tp, b)
	bounds := image.Bounds()
	//x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Dx()), float64(bounds.Dy())
	x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
	tr := gc.Current.Tr
	tr.TransformRectangle(&x0, &y0, &x1, &y1)
	gc.pdf.Image(name, x0, y0, x1-x0, y1-y0, false, tp, 0, "")
}

// Clear draws a white rectangle over the whole page
func (gc *GraphicContext) Clear() {
	width, height := gc.pdf.GetPageSize()
	clearRect(gc, 0, 0, width, height)
}

// ClearRect draws a white rectangle over the specified area
func (gc *GraphicContext) ClearRect(x1, y1, x2, y2 int) {
	clearRect(gc, float64(x1), float64(y1), float64(x2), float64(y2))
}

// SetDPI is a dummy method to implement the GraphicContext interface
func (gc *GraphicContext) SetDPI(dpi int) {
	gc.DPI = dpi
	// gc.recalc()
}

// GetDPI is a dummy method to implement the GraphicContext interface
func (gc *GraphicContext) GetDPI() int {
	return gc.DPI
}

// GetStringBounds returns the approximate pixel bounds of the string s at x, y.
func (gc *GraphicContext) GetStringBounds(s string) (left, top, right, bottom float64) {
	_, h := gc.pdf.GetFontSize()
	return 0, 0, gc.pdf.GetStringWidth(s), h
}

// CreateStringPath creates a path from the string s at x, y, and returns the string width.
func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
	gc.pdf.MoveTo(x, y)
	_, _, w, h := gc.GetStringBounds(text)
	gc.pdf.Cell(w, h, text)
	return w
}

// FillString draws a string at 0, 0
func (gc *GraphicContext) FillString(text string) (cursor float64) {
	return gc.FillStringAt(text, 0, 0)
}

// FillStringAt draws a string at x, y
func (gc *GraphicContext) FillStringAt(text string, x, y float64) (cursor float64) {
	return gc.CreateStringPath(text, x, y)
}

// StrokeString draws a string at 0, 0
func (gc *GraphicContext) StrokeString(text string) (cursor float64) {
	return gc.StrokeStringAt(text, 0, 0)
}

// StrokeStringAt draws a string at x, y
func (gc *GraphicContext) StrokeStringAt(text string, x, y float64) (cursor float64) {
	return gc.CreateStringPath(text, x, y)
}

// Stroke strokes the paths
func (gc *GraphicContext) Stroke(paths ...*draw2d.PathStorage) {
	gc.draw("D", paths...)
}

// Fill strokes the paths
func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) {
	gc.draw("F", paths...)
}

// FillStroke first fills the paths and than strokes them
func (gc *GraphicContext) FillStroke(paths ...*draw2d.PathStorage) {
	gc.draw("FD", paths...)
}

var logger = log.New(os.Stdout, "", log.Lshortfile)

// draw fills and/or strokes paths
func (gc *GraphicContext) draw(style string, paths ...*draw2d.PathStorage) {
	paths = append(paths, gc.Current.Path)
	pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr, gc.pdf))
	// pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr,NewPathLogger(logger, gc.pdf)))
	pathConverter.Convert(paths...)
	if gc.Current.FillRule.UseNonZeroWinding() {
		style += "*"
	}
	gc.pdf.DrawPath(style)
}

// overwrite StackGraphicContext methods

// SetStrokeColor sets the stroke color
func (gc *GraphicContext) SetStrokeColor(c color.Color) {
	gc.StackGraphicContext.SetStrokeColor(c)
	gc.pdf.SetDrawColor(rgb(c))
}

// SetFillColor sets the fill color
func (gc *GraphicContext) SetFillColor(c color.Color) {
	gc.StackGraphicContext.SetFillColor(c)
	gc.pdf.SetFillColor(rgb(c))
}

// SetFont is unsupported by the pdf graphic context, use SetFontData
// instead.
func (gc *GraphicContext) SetFont(font *truetype.Font) {
	// TODO: what to do with this api conflict between draw2d and gofpdf?!
}

// SetFontData sets the current font used to draw text. Always use
// this method, as SetFont is unsupported by the pdf graphic context.
// It is mandatory to call this method at least once before printing
// text or the resulting document will not be valid.
// It is necessary to generate a font definition file first with the
// makefont utility. It is not necessary to call this function for the
// core PDF fonts (courier, helvetica, times, zapfdingbats).
// go get github.com/jung-kurt/gofpdf/makefont
// http://godoc.org/github.com/jung-kurt/gofpdf#Fpdf.AddFont
func (gc *GraphicContext) SetFontData(fontData draw2d.FontData) {
	gc.StackGraphicContext.SetFontData(fontData)
	var style string
	if fontData.Style&draw2d.FontStyleBold != 0 {
		style += "B"
	}
	if fontData.Style&draw2d.FontStyleItalic != 0 {
		style += "I"
	}
	fn := draw2d.FontFileName(fontData)
	fn = fn[:len(fn)-4]
	gc.pdf.AddFont(fn, style, fn+".json")
}

// SetFontSize sets the font size in points (as in ``a 12 point font'').
func (gc *GraphicContext) SetFontSize(fontSize float64) {
	gc.StackGraphicContext.SetFontSize(fontSize)
	gc.pdf.SetFontSize(fontSize)
	//gc.recalc()
}

// SetLineWidth sets the line width
func (gc *GraphicContext) SetLineWidth(LineWidth float64) {
	gc.StackGraphicContext.SetLineWidth(LineWidth)
	gc.pdf.SetLineWidth(LineWidth)
}

// SetLineCap sets the line cap (round, but or square)
func (gc *GraphicContext) SetLineCap(Cap draw2d.Cap) {
	gc.StackGraphicContext.SetLineCap(Cap)
	gc.pdf.SetLineCapStyle(caps[Cap])
}
<commit_msg>add transformation to text and images<commit_after>// Copyright 2015 The draw2d Authors. All rights reserved.
// created: 26/06/2015 by Stani Michiels
// TODO: fonts, dpi

package pdf2d

import (
	"bytes"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"strconv"

	"code.google.com/p/freetype-go/freetype/truetype"

	"github.com/stanim/draw2d"
	"github.com/stanim/gofpdf"
)

var (
	caps = map[draw2d.Cap]string{
		draw2d.RoundCap:  "round",
		draw2d.ButtCap:   "butt",
		draw2d.SquareCap: "square"}
)

const c255 = 255.0 / 65535.0

var (
	imageCount uint32
	white      color.Color = color.RGBA{255, 255, 255, 255}
)

// NewPdf creates a new pdf document with the draw2d fontfolder, adds
// a page and set fill color to white.
func NewPdf(orientationStr, unitStr, sizeStr string) *gofpdf.Fpdf {
	pdf := gofpdf.New(orientationStr, unitStr, sizeStr, draw2d.GetFontFolder())
	pdf.AddPage()
	pdf.SetFillColor(255, 255, 255) // to be compatible with draw2d
	return pdf
}

// rgb converts a color (used by draw2d) into 3 int (used by gofpdf)
func rgb(c color.Color) (int, int, int) {
	r, g, b, _ := c.RGBA()
	return int(float64(r) * c255), int(float64(g) * c255), int(float64(b) * c255)
}

// clearRect draws a white rectangle
func clearRect(gc *GraphicContext, x1, y1, x2, y2 float64) {
	// save state
	f := gc.Current.FillColor
	x, y := gc.pdf.GetXY()
	// cover page with white rectangle
	gc.SetFillColor(white)
	draw2d.Rect(gc, x1, y1, x2, y2)
	gc.Fill()
	// restore state
	gc.SetFillColor(f)
	gc.pdf.MoveTo(x, y)
}

// GraphicContext implements the draw2d.GraphicContext interface
// It provides draw2d with a pdf backend (based on gofpdf)
type GraphicContext struct {
	*draw2d.StackGraphicContext
	pdf *gofpdf.Fpdf
	DPI int
}

// NewGraphicContext creates a new pdf GraphicContext
func NewGraphicContext(pdf *gofpdf.Fpdf) *GraphicContext {
	dpi := 92
	return &GraphicContext{draw2d.NewStackGraphicContext(), pdf, dpi}
}

// DrawImage draws an image as PNG
// TODO: add type (tp) as parameter to argument list?
func (gc *GraphicContext) DrawImage(image image.Image) {
	// TODO: fix rotation gc.Current.Tr
	name := strconv.Itoa(int(imageCount))
	tp := "PNG" // "JPG", "JPEG", "PNG" and "GIF"
	b := &bytes.Buffer{}
	png.Encode(b, image)
	gc.pdf.RegisterImageReader(name, tp, b)
	bounds := image.Bounds()
	//x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Dx()), float64(bounds.Dy())
	x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
	tr := gc.Current.Tr
	tr.TransformRectangle(&x0, &y0, &x1, &y1)
	gc.pdf.Image(name, x0, y0, x1-x0, y1-y0, false, tp, 0, "")
}

// Clear draws a white rectangle over the whole page
func (gc *GraphicContext) Clear() {
	width, height := gc.pdf.GetPageSize()
	clearRect(gc, 0, 0, width, height)
}

// ClearRect draws a white rectangle over the specified area
func (gc *GraphicContext) ClearRect(x1, y1, x2, y2 int) {
	clearRect(gc, float64(x1), float64(y1), float64(x2), float64(y2))
}

// SetDPI is a dummy method to implement the GraphicContext interface
func (gc *GraphicContext) SetDPI(dpi int) {
	gc.DPI = dpi
	// gc.recalc()
}

// GetDPI is a dummy method to implement the GraphicContext interface
func (gc *GraphicContext) GetDPI() int {
	return gc.DPI
}

// GetStringBounds returns the approximate pixel bounds of the string s at x, y.
func (gc *GraphicContext) GetStringBounds(s string) (left, top, right, bottom float64) {
	_, h := gc.pdf.GetFontSize()
	return 0, 0, gc.pdf.GetStringWidth(s), h
}

// CreateStringPath creates a path from the string s at x, y, and returns the string width.
func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
	// TODO: fix rotation of gc.Current.Tr
	_, _, w, h := gc.GetStringBounds(text)
	x1, y1 := x+w, y+h
	tr := gc.Current.Tr
	tr.TransformRectangle(&x, &y, &x1, &y1)
	gc.pdf.MoveTo(x, y)
	gc.pdf.Cell(x1-x, y1-y, text)
	return w
}

// FillString draws a string at 0, 0
func (gc *GraphicContext) FillString(text string) (cursor float64) {
	return gc.FillStringAt(text, 0, 0)
}

// FillStringAt draws a string at x, y
func (gc *GraphicContext) FillStringAt(text string, x, y float64) (cursor float64) {
	return gc.CreateStringPath(text, x, y)
}

// StrokeString draws a string at 0, 0 (stroking is unsupported,
// string will be filled)
func (gc *GraphicContext) StrokeString(text string) (cursor float64) {
	return gc.StrokeStringAt(text, 0, 0)
}

// StrokeStringAt draws a string at x, y (stroking is unsupported,
// string will be filled)
func (gc *GraphicContext) StrokeStringAt(text string, x, y float64) (cursor float64) {
	return gc.CreateStringPath(text, x, y)
}

// Stroke strokes the paths
func (gc *GraphicContext) Stroke(paths ...*draw2d.PathStorage) {
	gc.draw("D", paths...)
}

// Fill strokes the paths
func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) {
	gc.draw("F", paths...)
}

// FillStroke first fills the paths and than strokes them
func (gc *GraphicContext) FillStroke(paths ...*draw2d.PathStorage) {
	gc.draw("FD", paths...)
}

var logger = log.New(os.Stdout, "", log.Lshortfile)

// draw fills and/or strokes paths
func (gc *GraphicContext) draw(style string, paths ...*draw2d.PathStorage) {
	paths = append(paths, gc.Current.Path)
	pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr, gc.pdf))
	// pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr,NewPathLogger(logger, gc.pdf)))
	pathConverter.Convert(paths...)
	if gc.Current.FillRule.UseNonZeroWinding() {
		style += "*"
	}
	gc.pdf.DrawPath(style)
}

// overwrite StackGraphicContext methods

// SetStrokeColor sets the stroke color
func (gc *GraphicContext) SetStrokeColor(c color.Color) {
	gc.StackGraphicContext.SetStrokeColor(c)
	gc.pdf.SetDrawColor(rgb(c))
}

// SetFillColor sets the fill color
func (gc *GraphicContext) SetFillColor(c color.Color) {
	gc.StackGraphicContext.SetFillColor(c)
	gc.pdf.SetFillColor(rgb(c))
}

// SetFont is unsupported by the pdf graphic context, use SetFontData
// instead.
func (gc *GraphicContext) SetFont(font *truetype.Font) {
	// TODO: what to do with this api conflict between draw2d and gofpdf?!
}

// SetFontData sets the current font used to draw text. Always use
// this method, as SetFont is unsupported by the pdf graphic context.
// It is mandatory to call this method at least once before printing
// text or the resulting document will not be valid.
// It is necessary to generate a font definition file first with the
// makefont utility. It is not necessary to call this function for the
// core PDF fonts (courier, helvetica, times, zapfdingbats).
// go get github.com/jung-kurt/gofpdf/makefont
// http://godoc.org/github.com/jung-kurt/gofpdf#Fpdf.AddFont
func (gc *GraphicContext) SetFontData(fontData draw2d.FontData) {
	gc.StackGraphicContext.SetFontData(fontData)
	var style string
	if fontData.Style&draw2d.FontStyleBold != 0 {
		style += "B"
	}
	if fontData.Style&draw2d.FontStyleItalic != 0 {
		style += "I"
	}
	fn := draw2d.FontFileName(fontData)
	fn = fn[:len(fn)-4]
	gc.pdf.AddFont(fn, style, fn+".json")
}

// SetFontSize sets the font size in points (as in ``a 12 point font'').
func (gc *GraphicContext) SetFontSize(fontSize float64) {
	gc.StackGraphicContext.SetFontSize(fontSize)
	gc.pdf.SetFontSize(fontSize)
	//gc.recalc()
}

// SetLineWidth sets the line width
func (gc *GraphicContext) SetLineWidth(LineWidth float64) {
	gc.StackGraphicContext.SetLineWidth(LineWidth)
	gc.pdf.SetLineWidth(LineWidth)
}

// SetLineCap sets the line cap (round, but or square)
func (gc *GraphicContext) SetLineCap(Cap draw2d.Cap) {
	gc.StackGraphicContext.SetLineCap(Cap)
	gc.pdf.SetLineCapStyle(caps[Cap])
}
<|endoftext|>


<commit_before>package ioutilmore

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"sort"
	"strings"
)

func Copy(src string, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	return err
}

func ReadDirSplit(dirname string, skipDotDirs bool) ([]os.FileInfo, []os.FileInfo, error) {
	all, err := ioutil.ReadDir(dirname)
	if err != nil {
		return []os.FileInfo{}, []os.FileInfo{}, err
	}
	subdirs, regular := FileInfosSplit(all, skipDotDirs)
	return subdirs, regular, nil
}

func FileInfosSplit(all []os.FileInfo, skipDotDirs bool) ([]os.FileInfo, []os.FileInfo) {
	subdirs := []os.FileInfo{}
	regular := []os.FileInfo{}
	for _, f := range all {
		if f.Mode().IsDir() {
			if !skipDotDirs || (f.Name() != "." && f.Name() != "..") {
				subdirs = append(subdirs, f)
			}
		} else {
			regular = append(regular, f)
		}
	}
	return subdirs, regular
}

func DirEntriesReSizeGt0(dir string, rx1 *regexp.Regexp) ([]os.FileInfo, error) {
	filesMatch := []os.FileInfo{}
	filesAll, e := ioutil.ReadDir(dir)
	if e != nil {
		return filesMatch, e
	}
	for _, f := range filesAll {
		if f.Name() == "." || f.Name() == ".." {
			continue
		}
		if f.Size() > int64(0) {
			rs1 := rx1.FindStringSubmatch(f.Name())
			if len(rs1) > 0 {
				filesMatch = append(filesMatch, f)
			}
		}
	}
	return filesMatch, nil
}

// DirFilesSubmatchGreatest takes a directory, regular expression and boolean to indicate
// whether to include zero size files and returns the greatest of a single match in the
// regular expression.
func DirFilesSubmatchGreatest(dir string, rx1 *regexp.Regexp, nonZeroFilesOnly bool) (string, error) {
	filesAll, err := ioutil.ReadDir(dir)
	if err != nil {
		return "", err
	}
	strs := []string{}
	for _, f := range filesAll {
		if nonZeroFilesOnly && f.Size() <= int64(0) {
			continue
		}
		rs1 := rx1.FindStringSubmatch(f.Name())
		if len(rs1) > 1 {
			strs = append(strs, rs1[1])
		}
	}
	sort.Strings(strs)
	if len(strs) == 0 {
		return "", fmt.Errorf("No matches found")
	}
	return strs[len(strs)-1], nil
}

func DirFromPath(path string) (string, error) {
	path = strings.TrimRight(path, "/\\")
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	fi, err := f.Stat()
	if err != nil {
		return "", err
	}
	isFile := false
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return path, nil
	case mode.IsRegular():
		isFile = true
	}
	if isFile == false {
		return "", nil
	}
	rx1 := regexp.MustCompile(`^(.+)[/\\][^/\\]+`)
	rs1 := rx1.FindStringSubmatch(path)
	dir := ""
	if len(rs1) > 1 {
		dir = rs1[1]
	}
	return dir, nil
}

func GetFileInfo(path string) (os.FileInfo, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return f.Stat()
}

func IsDir(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return true, nil
	case mode.IsRegular():
		return false, nil
	}
	return false, nil
}

func IsFile(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return false, nil
	case mode.IsRegular():
		return true, nil
	}
	return false, nil
}

func IsFileWithSizeGtZero(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	if fi.Mode().IsRegular() == false {
		err = errors.New("400: file path is not a file")
		return false, err
	} else if fi.Size() <= 0 {
		return false, nil
	}
	return true, nil
}

func FilterFilenamesSizeGtZero(filepaths ...string) []string {
	filepathsExist := []string{}

	for _, envPathVal := range filepaths {
		envPathVals := strings.Split(envPathVal, ",")
		for _, envPath := range envPathVals {
			envPath = strings.TrimSpace(envPath)

			good, err := IsFileWithSizeGtZero(envPath)
			if err == nil && good {
				filepathsExist = append(filepathsExist, envPath)
			}
		}
	}
	return filepathsExist
}

func RemoveAllChildren(dir string) error {
	isDir, err := IsDir(dir)
	if err != nil {
		return err
	}
	if isDir == false {
		err = errors.New("400: Path Is Not Directory")
		return err
	}
	filesAll, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, fi := range filesAll {
		if fi.Name() == "." || fi.Name() == ".." {
			continue
		}
		filepath := path.Join(dir, fi.Name())
		if fi.IsDir() {
			err = os.RemoveAll(filepath)
			if err != nil {
				return err
			}
		} else {
			err = os.Remove(filepath)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// ReaderToBytes reads from an io.Reader, e.g. io.ReadCloser
func ReaderToBytes(ior io.Reader) []byte {
	buf := new(bytes.Buffer)
	buf.ReadFrom(ior)
	return buf.Bytes()
}

func WriteJSON(filepath string, data interface{}, perm os.FileMode, wantPretty bool) error {
	var bytes []byte
	if wantPretty {
		bytesTry, err := json.MarshalIndent(data, "", "  ")
		if err != nil {
			return err
		}
		bytes = bytesTry
	} else {
		bytesTry, err := json.Marshal(data)
		if err != nil {
			return err
		}
		bytes = bytesTry
	}
	return ioutil.WriteFile(filepath, bytes, perm)
}

type FileWriter struct {
	File   *os.File
	Writer *bufio.Writer
}

func NewFileWriter(path string) (FileWriter, error) {
	fw := FileWriter{}
	file, err := os.Create(path)
	if err != nil {
		return fw, err
	}

	fw.File = file
	fw.Writer = bufio.NewWriter(file)

	return fw, nil
}

func (f *FileWriter) Close() {
	f.Writer.Flush()
	f.File.Close()
}
<commit_msg>add iom.DirFilesRegexpSubmatchGreatest<commit_after>package ioutilmore

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"sort"
	"strings"

	"github.com/grokify/gotilla/type/maputil"
)

func Copy(src string, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	return err
}

func ReadDirSplit(dirname string, skipDotDirs bool) ([]os.FileInfo, []os.FileInfo, error) {
	all, err := ioutil.ReadDir(dirname)
	if err != nil {
		return []os.FileInfo{}, []os.FileInfo{}, err
	}
	subdirs, regular := FileInfosSplit(all, skipDotDirs)
	return subdirs, regular, nil
}

func FileInfosSplit(all []os.FileInfo, skipDotDirs bool) ([]os.FileInfo, []os.FileInfo) {
	subdirs := []os.FileInfo{}
	regular := []os.FileInfo{}
	for _, f := range all {
		if f.Mode().IsDir() {
			if !skipDotDirs || (f.Name() != "." && f.Name() != "..") {
				subdirs = append(subdirs, f)
			}
		} else {
			regular = append(regular, f)
		}
	}
	return subdirs, regular
}

func DirEntriesReSizeGt0(dir string, rx1 *regexp.Regexp) ([]os.FileInfo, error) {
	filesMatch := []os.FileInfo{}
	filesAll, e := ioutil.ReadDir(dir)
	if e != nil {
		return filesMatch, e
	}
	for _, f := range filesAll {
		if f.Name() == "." || f.Name() == ".." {
			continue
		}
		if f.Size() > int64(0) {
			rs1 := rx1.FindStringSubmatch(f.Name())
			if len(rs1) > 0 {
				filesMatch = append(filesMatch, f)
			}
		}
	}
	return filesMatch, nil
}

// DirEntriesRegexpGreatest takes a directory, regular expression and boolean to indicate
// whether to include zero size files and returns the greatest of a single match in the
// regular expression.
func DirFilesRegexpSubmatchGreatest(dir string, rx1 *regexp.Regexp, nonZeroFilesOnly bool) ([]os.FileInfo, error) {
	files := map[string][]os.FileInfo{}

	filesAll, e := ioutil.ReadDir(dir)
	if e != nil {
		return []os.FileInfo{}, e
	}
	for _, f := range filesAll {
		if f.Name() == "." || f.Name() == ".." ||
			(nonZeroFilesOnly && f.Size() <= int64(0)) {
			continue
		}

		rs1 := rx1.FindStringSubmatch(f.Name())
		if len(rs1) > 1 {
			extract := rs1[1]
			if _, ok := files[extract]; !ok {
				files[extract] = []os.FileInfo{}
			}
			files[extract] = append(files[extract], f)
			//strs = append(strs, rs1[1])
			//filesMatch = append(filesMatch, f)
		}
	}
	keysSorted := maputil.StringKeysSorted(files)
	greatest := keysSorted[len(keysSorted)-1]
	return files[greatest], nil
}

// DirFilesRegexpSubmatchGreatestSubmatch takes a directory, regular expression and boolean to indicate
// whether to include zero size files and returns the greatest of a single match in the
// regular expression.
func DirFilesRegexpSubmatchGreatestSubmatch(dir string, rx1 *regexp.Regexp, nonZeroFilesOnly bool) (string, error) {
	filesAll, err := ioutil.ReadDir(dir)
	if err != nil {
		return "", err
	}
	strs := []string{}
	for _, f := range filesAll {
		if nonZeroFilesOnly && f.Size() <= int64(0) {
			continue
		}
		rs1 := rx1.FindStringSubmatch(f.Name())
		if len(rs1) > 1 {
			strs = append(strs, rs1[1])
		}
	}
	sort.Strings(strs)
	if len(strs) == 0 {
		return "", fmt.Errorf("No matches found")
	}
	return strs[len(strs)-1], nil
}

func DirFromPath(path string) (string, error) {
	path = strings.TrimRight(path, "/\\")
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	fi, err := f.Stat()
	if err != nil {
		return "", err
	}
	isFile := false
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return path, nil
	case mode.IsRegular():
		isFile = true
	}
	if isFile == false {
		return "", nil
	}
	rx1 := regexp.MustCompile(`^(.+)[/\\][^/\\]+`)
	rs1 := rx1.FindStringSubmatch(path)
	dir := ""
	if len(rs1) > 1 {
		dir = rs1[1]
	}
	return dir, nil
}

func GetFileInfo(path string) (os.FileInfo, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return f.Stat()
}

func IsDir(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return true, nil
	case mode.IsRegular():
		return false, nil
	}
	return false, nil
}

func IsFile(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return false, nil
	case mode.IsRegular():
		return true, nil
	}
	return false, nil
}

func IsFileWithSizeGtZero(path string) (bool, error) {
	fi, err := GetFileInfo(path)
	if err != nil {
		return false, err
	}
	if fi.Mode().IsRegular() == false {
		err = errors.New("400: file path is not a file")
		return false, err
	} else if fi.Size() <= 0 {
		return false, nil
	}
	return true, nil
}

func FilterFilenamesSizeGtZero(filepaths ...string) []string {
	filepathsExist := []string{}

	for _, envPathVal := range filepaths {
		envPathVals := strings.Split(envPathVal, ",")
		for _, envPath := range envPathVals {
			envPath = strings.TrimSpace(envPath)

			good, err := IsFileWithSizeGtZero(envPath)
			if err == nil && good {
				filepathsExist = append(filepathsExist, envPath)
			}
		}
	}
	return filepathsExist
}

func RemoveAllChildren(dir string) error {
	isDir, err := IsDir(dir)
	if err != nil {
		return err
	}
	if isDir == false {
		err = errors.New("400: Path Is Not Directory")
		return err
	}
	filesAll, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, fi := range filesAll {
		if fi.Name() == "." || fi.Name() == ".." {
			continue
		}
		filepath := path.Join(dir, fi.Name())
		if fi.IsDir() {
			err = os.RemoveAll(filepath)
			if err != nil {
				return err
			}
		} else {
			err = os.Remove(filepath)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// ReaderToBytes reads from an io.Reader, e.g. io.ReadCloser
func ReaderToBytes(ior io.Reader) []byte {
	buf := new(bytes.Buffer)
	buf.ReadFrom(ior)
	return buf.Bytes()
}

func WriteJSON(filepath string, data interface{}, perm os.FileMode, wantPretty bool) error {
	var bytes []byte
	if wantPretty {
		bytesTry, err := json.MarshalIndent(data, "", "  ")
		if err != nil {
			return err
		}
		bytes = bytesTry
	} else {
		bytesTry, err := json.Marshal(data)
		if err != nil {
			return err
		}
		bytes = bytesTry
	}
	return ioutil.WriteFile(filepath, bytes, perm)
}

type FileWriter struct {
	File   *os.File
	Writer *bufio.Writer
}

func NewFileWriter(path string) (FileWriter, error) {
	fw := FileWriter{}
	file, err := os.Create(path)
	if err != nil {
		return fw, err
	}

	fw.File = file
	fw.Writer = bufio.NewWriter(file)

	return fw, nil
}

func (f *FileWriter) Close() {
	f.Writer.Flush()
	f.File.Close()
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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 ratelimit

import (
	"errors"
	"io"

	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

// Create a bucket that limits the rate at which it calls the wrapped bucket
// using opThrottle, and limits the bandwidth with which it reads from the
// wrapped bucket using egressThrottle.
func NewThrottledBucket(
	opThrottle Throttle,
	egressThrottle Throttle,
	wrapped gcs.Bucket) (b gcs.Bucket) {
	b = &throttledBucket{
		opThrottle:     opThrottle,
		egressThrottle: egressThrottle,
		wrapped:        wrapped,
	}

	return
}

type throttledBucket struct {
	opThrottle     Throttle
	egressThrottle Throttle
	wrapped        gcs.Bucket
}

func (b *throttledBucket) Name() string {
	return b.wrapped.Name()
}

func (b *throttledBucket) NewReader(
	ctx context.Context,
	req *gcs.ReadObjectRequest) (rc io.ReadCloser, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) CreateObject(
	ctx context.Context,
	req *gcs.CreateObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) CopyObject(
	ctx context.Context,
	req *gcs.CopyObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) StatObject(
	ctx context.Context,
	req *gcs.StatObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) ListObjects(
	ctx context.Context,
	req *gcs.ListObjectsRequest) (listing *gcs.Listing, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) UpdateObject(
	ctx context.Context,
	req *gcs.UpdateObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) DeleteObject(
	ctx context.Context,
	name string) (err error) {
	err = errors.New("TODO")
	return
}
<commit_msg>throttledBucket.NewReader<commit_after>// Copyright 2015 Google Inc. 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 ratelimit

import (
	"errors"
	"io"

	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

// Create a bucket that limits the rate at which it calls the wrapped bucket
// using opThrottle, and limits the bandwidth with which it reads from the
// wrapped bucket using egressThrottle.
func NewThrottledBucket(
	opThrottle Throttle,
	egressThrottle Throttle,
	wrapped gcs.Bucket) (b gcs.Bucket) {
	b = &throttledBucket{
		opThrottle:     opThrottle,
		egressThrottle: egressThrottle,
		wrapped:        wrapped,
	}

	return
}

type throttledBucket struct {
	opThrottle     Throttle
	egressThrottle Throttle
	wrapped        gcs.Bucket
}

func (b *throttledBucket) Name() string {
	return b.wrapped.Name()
}

func (b *throttledBucket) NewReader(
	ctx context.Context,
	req *gcs.ReadObjectRequest) (rc io.ReadCloser, err error) {
	// Wait for permission to call through.
	err = b.opThrottle.Wait(ctx, 1)
	if err != nil {
		return
	}

	// Call through.
	rc, err = b.wrapped.NewReader(ctx, req)
	if err != nil {
		return
	}

	// Wrap the result in a throttled layer.
	rc = &readerCloser{
		Reader: ThrottledReader(rc, b.egressThrottle),
		Closer: rc,
	}

	return
}

func (b *throttledBucket) CreateObject(
	ctx context.Context,
	req *gcs.CreateObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) CopyObject(
	ctx context.Context,
	req *gcs.CopyObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) StatObject(
	ctx context.Context,
	req *gcs.StatObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) ListObjects(
	ctx context.Context,
	req *gcs.ListObjectsRequest) (listing *gcs.Listing, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) UpdateObject(
	ctx context.Context,
	req *gcs.UpdateObjectRequest) (o *gcs.Object, err error) {
	err = errors.New("TODO")
	return
}

func (b *throttledBucket) DeleteObject(
	ctx context.Context,
	name string) (err error) {
	err = errors.New("TODO")
	return
}
<|endoftext|>


<commit_before>package bundle

import(
  "github.com/TykTechnologies/goverify"
  "github.com/TykTechnologies/tykcommon"
  "io"
  "io/ioutil"
  "encoding/json"
  "encoding/base64"
  "archive/zip"
  "crypto/md5"
  "bufio"
  "errors"
  "bytes"
  "fmt"
  "os"
)

var bundleOutput, privKey string
var forceInsecure *bool

const (
	defaultBundleOutput = "bundle.zip"
)

func init() {
}

// Bundle will handle the bundle command calls.
func Bundle(command string, thisBundleOutput string, thisPrivKey string, thisForceInsecure *bool) (err error) {
  bundleOutput = thisBundleOutput
  privKey = thisPrivKey
  forceInsecure = thisForceInsecure
	switch command {
	case "build":
		var manifestPath = "./manifest.json"
		if _, err := os.Stat(manifestPath); err == nil {
			var manifestData []byte
			manifestData, err = ioutil.ReadFile(manifestPath)

			var manifest tykcommon.BundleManifest
			err = json.Unmarshal(manifestData, &manifest)

			if err != nil {
				fmt.Println("Couldn't parse manifest file!")
				break
			}

			err = bundleValidateManifest(&manifest)

			if err != nil {
				fmt.Println("Bundle validation error:")
				fmt.Println(err)
				break
			}

			// The manifest is valid, we should do the checksum and sign step at this point.
			bundleBuild(&manifest)

		} else {
			err = errors.New("Manifest file doesn't exist.")
		}
	default:
		err = errors.New("Invalid command.")
	}
	return err
}

// bundleValidateManifest will validate the manifest file before building a bundle.
func bundleValidateManifest(manifest *tykcommon.BundleManifest) (err error) {
	// Validate manifest file list:
	for _, file := range manifest.FileList {
		if _, statErr := os.Stat(file); statErr != nil {
			err = errors.New("Referencing a nonexistent file: " + file)
			break
		}
	}

	// The custom middleware block must specify at least one hook:
	var definedHooks int
	definedHooks = len(manifest.CustomMiddleware.Pre) + len(manifest.CustomMiddleware.Post) + len(manifest.CustomMiddleware.PostKeyAuth)

	// We should count the auth check middleware (single), if it's present:
	if manifest.CustomMiddleware.AuthCheck.Name != "" {
		definedHooks++
	}

	if definedHooks == 0 {
		err = errors.New("No hooks defined!")
		return err
	}

	// The custom middleware block must specify a driver:
	if manifest.CustomMiddleware.Driver == "" {
		err = errors.New("No driver specified!")
		return err
	}

	return err
}

// bundleBuild will build and generate a bundle file.
func bundleBuild(manifest *tykcommon.BundleManifest) (err error) {
	var useSignature bool

	if bundleOutput == "" {
		fmt.Println("No output specified, using bundle.zip")
		bundleOutput = defaultBundleOutput
	}

	if privKey != "" {
		fmt.Println("The bundle will be signed.")
		useSignature = true
	}

	var bundleData bytes.Buffer

	for _, file := range manifest.FileList {
		var data []byte
		data, err = ioutil.ReadFile(file)

		if err != nil {
			fmt.Println("*** Error: ", err)
			return err
		}

		bundleData.Write(data)
	}

	// Update the manifest file:
	manifest.Checksum = fmt.Sprintf("%x", md5.Sum(bundleData.Bytes()))

	// If a private key is specified, sign the data:
	if useSignature {
		var signer goverify.Signer
		signer, err = goverify.LoadPrivateKeyFromFile(privKey)

		if err != nil {
			// Error: Couldn't read the private key
			return err
		}
		var signed []byte
		signed, err = signer.Sign(bundleData.Bytes())

		if err != nil {
			// Error: Couldn't sign the data.
			return err
		}

		manifest.Signature = base64.StdEncoding.EncodeToString(signed)
	} else {
		if *forceInsecure == false {
			fmt.Print("The bundle will be unsigned, type \"y\" to confirm: ")
			reader := bufio.NewReader(os.Stdin)
			text, _ := reader.ReadString('\n')
			if text != "y\n" {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}
	}

	var newManifestData []byte
	newManifestData, err = json.Marshal(&manifest)

	// Write the bundle file:
	buf := new(bytes.Buffer)
	bundleWriter := zip.NewWriter(buf)

	for _, file := range manifest.FileList {
		var outputFile io.Writer
		outputFile, err = bundleWriter.Create(file)
		if err != nil {
			return err
		}
		var data []byte
		data, err = ioutil.ReadFile(file)

		_, err = outputFile.Write(data)

		if err != nil {
			return err
		}
	}

	// Write manifest file:
	var newManifest io.Writer
	newManifest, err = bundleWriter.Create("manifest.json")
	_, err = newManifest.Write(newManifestData)

	err = bundleWriter.Close()
	err = ioutil.WriteFile(bundleOutput, buf.Bytes(), 0755)

	return err
}
<commit_msg>Exposing bundle functions.<commit_after>package bundle

import(
  "github.com/TykTechnologies/goverify"
  "github.com/TykTechnologies/tykcommon"
  "io"
  "io/ioutil"
  "encoding/json"
  "encoding/base64"
  "archive/zip"
  "crypto/md5"
  "bufio"
  "errors"
  "bytes"
  "fmt"
  "os"
)

var bundleOutput, privKey string
var forceInsecure *bool

const (
	defaultBundleOutput = "bundle.zip"
)

func init() {
}

// Bundle will handle the bundle command calls.
func Bundle(command string, thisBundleOutput string, thisPrivKey string, thisForceInsecure *bool) (err error) {
  bundleOutput = thisBundleOutput
  privKey = thisPrivKey
  forceInsecure = thisForceInsecure

	switch command {
	case "build":
		var manifestPath = "./manifest.json"
		if _, err = os.Stat(manifestPath); err == nil {
			var manifestData []byte
			manifestData, err = ioutil.ReadFile(manifestPath)

			var manifest tykcommon.BundleManifest
			err = json.Unmarshal(manifestData, &manifest)

			if err != nil {
				fmt.Println("Couldn't parse manifest file!")
				break
			}

			err = BundleValidateManifest(&manifest)

			if err != nil {
				fmt.Println("Bundle validation error:")
				fmt.Println(err)
				break
			}

			// The manifest is valid, we should do the checksum and sign step at this point.
			bundleBuild(&manifest)

		} else {
			err = errors.New("Manifest file doesn't exist.")
		}
	default:
		err = errors.New("Invalid command.")
	}
	return err
}

// BundleValidateManifest will validate the manifest file before building a bundle.
func BundleValidateManifest(manifest *tykcommon.BundleManifest) (err error) {
	// Validate manifest file list:
	for _, file := range manifest.FileList {
		if _, statErr := os.Stat(file); statErr != nil {
			err = errors.New("Referencing a nonexistent file: " + file)
			break
		}
	}

  // The file list references a nonexistent file:
  if err != nil {
    return err
  }

	// The custom middleware block must specify at least one hook:
	var definedHooks int
	definedHooks = len(manifest.CustomMiddleware.Pre) + len(manifest.CustomMiddleware.Post) + len(manifest.CustomMiddleware.PostKeyAuth)

	// We should count the auth check middleware (single), if it's present:
	if manifest.CustomMiddleware.AuthCheck.Name != "" {
		definedHooks++
	}

	if definedHooks == 0 {
		err = errors.New("No hooks defined!")
		return err
	}

	// The custom middleware block must specify a driver:
	if manifest.CustomMiddleware.Driver == "" {
		err = errors.New("No driver specified!")
		return err
	}

	return err
}

// bundleBuild will build and generate a bundle file.
func bundleBuild(manifest *tykcommon.BundleManifest) (err error) {
	var useSignature bool

	if bundleOutput == "" {
		fmt.Println("No output specified, using bundle.zip")
		bundleOutput = defaultBundleOutput
	}

	if privKey != "" {
		fmt.Println("The bundle will be signed.")
		useSignature = true
	}

	var bundleData bytes.Buffer

	for _, file := range manifest.FileList {
		var data []byte
		data, err = ioutil.ReadFile(file)

		if err != nil {
			fmt.Println("*** Error: ", err)
			return err
		}

		bundleData.Write(data)
	}

	// Update the manifest file:
	manifest.Checksum = fmt.Sprintf("%x", md5.Sum(bundleData.Bytes()))

	// If a private key is specified, sign the data:
	if useSignature {
		var signer goverify.Signer
		signer, err = goverify.LoadPrivateKeyFromFile(privKey)

		if err != nil {
			// Error: Couldn't read the private key
			return err
		}
		var signed []byte
		signed, err = signer.Sign(bundleData.Bytes())

		if err != nil {
			// Error: Couldn't sign the data.
			return err
		}

		manifest.Signature = base64.StdEncoding.EncodeToString(signed)
	} else {
		if *forceInsecure == false {
			fmt.Print("The bundle will be unsigned, type \"y\" to confirm: ")
			reader := bufio.NewReader(os.Stdin)
			text, _ := reader.ReadString('\n')
			if text != "y\n" {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}
	}

	var newManifestData []byte
	newManifestData, err = json.Marshal(&manifest)

	// Write the bundle file:
	buf := new(bytes.Buffer)
	bundleWriter := zip.NewWriter(buf)

	for _, file := range manifest.FileList {
		var outputFile io.Writer
		outputFile, err = bundleWriter.Create(file)
		if err != nil {
			return err
		}
		var data []byte
		data, err = ioutil.ReadFile(file)

		_, err = outputFile.Write(data)

		if err != nil {
			return err
		}
	}

	// Write manifest file:
	var newManifest io.Writer
	newManifest, err = bundleWriter.Create("manifest.json")
	_, err = newManifest.Write(newManifestData)

	err = bundleWriter.Close()
	err = ioutil.WriteFile(bundleOutput, buf.Bytes(), 0755)

	return err
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package gitlab

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/mvdan/gibot/site"

	client "github.com/xanzy/go-gitlab"
)

const (
	titleLength = 50
	shaLength   = 6
)

type Repo struct {
	Name     string
	Prefix   string
	Path     string
	IssueRe  *regexp.Regexp
	PullRe   *regexp.Regexp
	CommitRe *regexp.Regexp
	Client   client.Client
}

func NewRepo(r *site.Repo) *Repo {
	issueRe := regexp.MustCompile(`(` + strings.Join(r.Aliases, "|") + `)#([1-9][0-9]*)`)
	issueRe.Longest()
	pullRe := regexp.MustCompile(`(` + strings.Join(r.Aliases, "|") + `)!([1-9][0-9]*)`)
	pullRe.Longest()
	commitRe := regexp.MustCompile(`\b[0-9a-f]{6,20}\b`)
	commitRe.Longest()
	return &Repo{
		Name:     r.Name,
		Prefix:   r.Prefix,
		Path:     r.Path,
		IssueRe:  issueRe,
		PullRe:   pullRe,
		CommitRe: commitRe,
		Client:   *client.NewClient(nil, r.Token),
	}
}

func firstLine(s string) string {
	i := strings.IndexAny(s, "\n\r")
	if i == -1 {
		return s
	}
	return s[:i]
}

func ShortTitle(message string) string {
	title := firstLine(message)
	title = strings.TrimSpace(title)
	if len(title) > titleLength {
		return fmt.Sprintf("%s…", title[:titleLength-1])
	}
	return title
}

func (r *Repo) GetUser(id int) (*client.User, error) {
	user, _, err := r.Client.Users.GetUser(id)
	return user, err
}

func (r *Repo) IssueURL(id int) string {
	return fmt.Sprintf("%s/%s/issues/%d", r.Prefix, r.Path, id)
}

func (r *Repo) GetIssue(id int) (*client.Issue, error) {
	issues, _, err := r.Client.Issues.ListProjectIssues(r.Path,
		&client.ListProjectIssuesOptions{IID: id})
	if err != nil {
		return nil, err
	}
	if len(issues) < 1 {
		return nil, fmt.Errorf("Not found")
	}
	return issues[0], nil
}

func (r *Repo) IssueInfo(id int) (string, error) {
	issue, err := r.GetIssue(id)
	if err != nil {
		return "", err
	}
	title := ShortTitle(issue.Title)
	return fmt.Sprintf("#%d: %s - %s", id, title, r.IssueURL(id)), nil
}

func (r *Repo) GetMergeRequest(id int) (*client.MergeRequest, error) {
	merges, _, err := r.Client.MergeRequests.ListMergeRequests(r.Path,
		&client.ListMergeRequestsOptions{IID: id})
	if err != nil {
		return nil, err
	}
	if len(merges) < 1 {
		return nil, fmt.Errorf("Not found")
	}
	return merges[0], nil
}

func (r *Repo) MergeURL(id int) string {
	return fmt.Sprintf("%s/%s/merge_requests/%d", r.Prefix, r.Path, id)
}

func (r *Repo) PullInfo(id int) (string, error) {
	merge, err := r.GetMergeRequest(id)
	if err != nil {
		return "", err
	}
	title := ShortTitle(merge.Title)
	return fmt.Sprintf("#%d: %s - %s", id, title, r.MergeURL(id)), nil
}

func (r *Repo) GetCommit(sha string) (*client.Commit, error) {
	commit, _, err := r.Client.Commits.GetCommit(r.Path, sha)
	return commit, err
}

func ShortCommit(sha string) string {
	if len(sha) > shaLength {
		return sha[:shaLength]
	}
	return sha
}

func (r *Repo) CommitURL(sha string) string {
	sha = ShortCommit(sha)
	return fmt.Sprintf("%s/%s/commit/%s", r.Prefix, r.Path, sha)
}

func (r *Repo) CommitInfo(sha string) (string, error) {
	commit, err := r.GetCommit(sha)
	if err != nil {
		return "", err
	}
	short := ShortCommit(sha)
	title := ShortTitle(commit.Title)
	return fmt.Sprintf("%s: %s - %s", short, title, r.CommitURL(short)), nil
}

func (r *Repo) CompareURL(before, after string) string {
	before = ShortCommit(before)
	after = ShortCommit(after)
	return fmt.Sprintf("%s/%s/compare/%s...%s", r.Prefix, r.Path, before, after)
}
<commit_msg>Bump gitlab commit sha length to 8<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package gitlab

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/mvdan/gibot/site"

	client "github.com/xanzy/go-gitlab"
)

const (
	titleLength = 50
	shaLength   = 8
)

type Repo struct {
	Name     string
	Prefix   string
	Path     string
	IssueRe  *regexp.Regexp
	PullRe   *regexp.Regexp
	CommitRe *regexp.Regexp
	Client   client.Client
}

func NewRepo(r *site.Repo) *Repo {
	issueRe := regexp.MustCompile(`(` + strings.Join(r.Aliases, "|") + `)#([1-9][0-9]*)`)
	issueRe.Longest()
	pullRe := regexp.MustCompile(`(` + strings.Join(r.Aliases, "|") + `)!([1-9][0-9]*)`)
	pullRe.Longest()
	commitRe := regexp.MustCompile(`\b[0-9a-f]{8,20}\b`)
	commitRe.Longest()
	return &Repo{
		Name:     r.Name,
		Prefix:   r.Prefix,
		Path:     r.Path,
		IssueRe:  issueRe,
		PullRe:   pullRe,
		CommitRe: commitRe,
		Client:   *client.NewClient(nil, r.Token),
	}
}

func firstLine(s string) string {
	i := strings.IndexAny(s, "\n\r")
	if i == -1 {
		return s
	}
	return s[:i]
}

func ShortTitle(message string) string {
	title := firstLine(message)
	title = strings.TrimSpace(title)
	if len(title) > titleLength {
		return fmt.Sprintf("%s…", title[:titleLength-1])
	}
	return title
}

func (r *Repo) GetUser(id int) (*client.User, error) {
	user, _, err := r.Client.Users.GetUser(id)
	return user, err
}

func (r *Repo) IssueURL(id int) string {
	return fmt.Sprintf("%s/%s/issues/%d", r.Prefix, r.Path, id)
}

func (r *Repo) GetIssue(id int) (*client.Issue, error) {
	issues, _, err := r.Client.Issues.ListProjectIssues(r.Path,
		&client.ListProjectIssuesOptions{IID: id})
	if err != nil {
		return nil, err
	}
	if len(issues) < 1 {
		return nil, fmt.Errorf("Not found")
	}
	return issues[0], nil
}

func (r *Repo) IssueInfo(id int) (string, error) {
	issue, err := r.GetIssue(id)
	if err != nil {
		return "", err
	}
	title := ShortTitle(issue.Title)
	return fmt.Sprintf("#%d: %s - %s", id, title, r.IssueURL(id)), nil
}

func (r *Repo) GetMergeRequest(id int) (*client.MergeRequest, error) {
	merges, _, err := r.Client.MergeRequests.ListMergeRequests(r.Path,
		&client.ListMergeRequestsOptions{IID: id})
	if err != nil {
		return nil, err
	}
	if len(merges) < 1 {
		return nil, fmt.Errorf("Not found")
	}
	return merges[0], nil
}

func (r *Repo) MergeURL(id int) string {
	return fmt.Sprintf("%s/%s/merge_requests/%d", r.Prefix, r.Path, id)
}

func (r *Repo) PullInfo(id int) (string, error) {
	merge, err := r.GetMergeRequest(id)
	if err != nil {
		return "", err
	}
	title := ShortTitle(merge.Title)
	return fmt.Sprintf("#%d: %s - %s", id, title, r.MergeURL(id)), nil
}

func (r *Repo) GetCommit(sha string) (*client.Commit, error) {
	commit, _, err := r.Client.Commits.GetCommit(r.Path, sha)
	return commit, err
}

func ShortCommit(sha string) string {
	if len(sha) > shaLength {
		return sha[:shaLength]
	}
	return sha
}

func (r *Repo) CommitURL(sha string) string {
	sha = ShortCommit(sha)
	return fmt.Sprintf("%s/%s/commit/%s", r.Prefix, r.Path, sha)
}

func (r *Repo) CommitInfo(sha string) (string, error) {
	commit, err := r.GetCommit(sha)
	if err != nil {
		return "", err
	}
	short := ShortCommit(sha)
	title := ShortTitle(commit.Title)
	return fmt.Sprintf("%s: %s - %s", short, title, r.CommitURL(short)), nil
}

func (r *Repo) CompareURL(before, after string) string {
	before = ShortCommit(before)
	after = ShortCommit(after)
	return fmt.Sprintf("%s/%s/compare/%s...%s", r.Prefix, r.Path, before, after)
}
<|endoftext|>


<commit_before>package k8sTest

import (
	"fmt"
	"strings"
	"sync"

	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var _ = Describe("K8sValidatedUpdates", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string
	var demoPath string
	var l3Policy, l7Policy string
	var apps []string

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Delete(ciliumPath)

		apps = []string{helpers.App1, helpers.App2, helpers.App3}

		demoPath = kubectl.ManifestGet("demo.yaml")
		l3Policy = kubectl.ManifestGet("l3_l4_policy.yaml")
		l7Policy = kubectl.ManifestGet("l7_policy.yaml")

		// Sometimes PolicyGen has a lot of pods running around without delete
		// it. Using this we are sure that we delete before this test start
		kubectl.Exec(fmt.Sprintf(
			"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))

		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")

	}

	AfterEach(func() {

		//This policies maybe are not loaded, (Test failed before) so no assert here.
		kubectl.Delete(l7Policy)
		kubectl.Delete(l3Policy)
		kubectl.Delete(demoPath)

		res := kubectl.DeleteResource(
			"ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		res.ExpectSuccess("Cilium DS cannot be deleted")

	})

	BeforeEach(func() {
		once.Do(initialize)
		kubectl.Exec("sudo docker rmi cilium/cilium")
		// Making sure that we deleted the  cilium ds. No assert message
		// because maybe is not present
		kubectl.DeleteResource("ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		helpers.InstallExampleCilium(kubectl)
	})

	validatedImage := func(image string) {
		By(fmt.Sprintf("Checking that installed image is %q", image))

		filter := `{.items[*].status.containerStatuses[0].image}`
		data, err := kubectl.GetPods(
			helpers.KubeSystemNamespace, "-l k8s-app=cilium").Filter(filter)
		ExpectWithOffset(1, err).To(BeNil(), "Cannot get cilium pods")

		for _, val := range strings.Split(data.String(), " ") {
			ExpectWithOffset(1, val).To(Equal(image), "Cilium image didn't update correctly")
		}
	}

	waitEndpointReady := func() {
		ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
		Expect(err).To(BeNil(), "cannot retrieve cilium pods")
		for _, pod := range ciliumPods {
			ExpectWithOffset(1, kubectl.CiliumEndpointWait(pod)).To(BeTrue(),
				"Pod %v is not ready", pod)
		}
	}

	It("Updating Cilium stable to master", func() {
		By("Creating some endpoints and L7 policy")
		kubectl.Apply(demoPath).ExpectSuccess()

		kubectl.Exec(fmt.Sprintf("%s scale deployment %s --replicas=5",
			helpers.KubectlCmd, helpers.App1)).ExpectSuccess(
			"Cannot scale %v deployment", helpers.App1)

		_, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", timeout)
		Expect(err).Should(BeNil())

		_, err = kubectl.CiliumPolicyAction(
			helpers.KubeSystemNamespace, l7Policy, helpers.KubectlApply, timeout)
		Expect(err).Should(BeNil(), "cannot import l7 policy: %v", l7Policy)

		waitEndpointReady()

		appPods := helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "id")

		res := kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
		res.ExpectSuccess("Cannot curl app1-service")

		By("Updating cilium to master image")

		localImage := "k8s1:5000/cilium/cilium-dev:latest"
		resource := "daemonset/cilium"

		kubectl.Exec(fmt.Sprintf("%s -n %s set image %s cilium-agent=%s",
			helpers.KubectlCmd, helpers.KubeSystemNamespace,
			resource, localImage)).ExpectSuccess(
			"Cannot update image")

		kubectl.Exec(fmt.Sprintf("%s rollout status %s -n %s",
			helpers.KubectlCmd, resource,
			helpers.KubeSystemNamespace)).ExpectSuccess("Cannot rollout the change")

		waitForUpdateImage := func() bool {
			pods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
			if err != nil {
				return false
			}

			filter := `{.items[*].status.containerStatuses[0].image}`
			data, err := kubectl.GetPods(
				helpers.KubeSystemNamespace, "-l k8s-app=cilium").Filter(filter)
			if err != nil {
				return false
			}
			number := strings.Count(data.String(), localImage)
			if number == len(pods) {
				return true
			}
			logger.Infof("Only '%v' of '%v' cilium pods updated to the new image",
				number, len(pods))
			return false
		}

		err = helpers.WithTimeout(
			waitForUpdateImage,
			"Cilium Pods are not updating correctly",
			&helpers.TimeoutConfig{Timeout: timeout})
		Expect(err).To(BeNil(), "Pods are not updating")

		status, err := kubectl.WaitforPods(
			helpers.KubeSystemNamespace, "-l k8s-app=cilium", timeout)
		Expect(status).Should(BeTrue(), "Cilium is not ready after timeout")
		Expect(err).Should(BeNil(), "Cilium is not ready after timeout")

		validatedImage(localImage)
		res = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
		res.ExpectSuccess("Cannot curl service after update")
	})
})
<commit_msg>Test: Disable cilium update from stable<commit_after>package k8sTest

import (
	"fmt"
	"strings"
	"sync"

	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var _ = Describe("DisabledK8sValidatedUpdates", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string
	var demoPath string
	var l3Policy, l7Policy string
	var apps []string

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Delete(ciliumPath)

		apps = []string{helpers.App1, helpers.App2, helpers.App3}

		demoPath = kubectl.ManifestGet("demo.yaml")
		l3Policy = kubectl.ManifestGet("l3_l4_policy.yaml")
		l7Policy = kubectl.ManifestGet("l7_policy.yaml")

		// Sometimes PolicyGen has a lot of pods running around without delete
		// it. Using this we are sure that we delete before this test start
		kubectl.Exec(fmt.Sprintf(
			"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))

		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")

	}

	AfterEach(func() {

		//This policies maybe are not loaded, (Test failed before) so no assert here.
		kubectl.Delete(l7Policy)
		kubectl.Delete(l3Policy)
		kubectl.Delete(demoPath)

		res := kubectl.DeleteResource(
			"ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		res.ExpectSuccess("Cilium DS cannot be deleted")

	})

	BeforeEach(func() {
		once.Do(initialize)
		kubectl.Exec("sudo docker rmi cilium/cilium")
		// Making sure that we deleted the  cilium ds. No assert message
		// because maybe is not present
		kubectl.DeleteResource("ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		helpers.InstallExampleCilium(kubectl)
	})

	validatedImage := func(image string) {
		By(fmt.Sprintf("Checking that installed image is %q", image))

		filter := `{.items[*].status.containerStatuses[0].image}`
		data, err := kubectl.GetPods(
			helpers.KubeSystemNamespace, "-l k8s-app=cilium").Filter(filter)
		ExpectWithOffset(1, err).To(BeNil(), "Cannot get cilium pods")

		for _, val := range strings.Split(data.String(), " ") {
			ExpectWithOffset(1, val).To(Equal(image), "Cilium image didn't update correctly")
		}
	}

	waitEndpointReady := func() {
		ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
		Expect(err).To(BeNil(), "cannot retrieve cilium pods")
		for _, pod := range ciliumPods {
			ExpectWithOffset(1, kubectl.CiliumEndpointWait(pod)).To(BeTrue(),
				"Pod %v is not ready", pod)
		}
	}

	It("Updating Cilium stable to master", func() {
		By("Creating some endpoints and L7 policy")
		kubectl.Apply(demoPath).ExpectSuccess()

		kubectl.Exec(fmt.Sprintf("%s scale deployment %s --replicas=5",
			helpers.KubectlCmd, helpers.App1)).ExpectSuccess(
			"Cannot scale %v deployment", helpers.App1)

		_, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", timeout)
		Expect(err).Should(BeNil())

		_, err = kubectl.CiliumPolicyAction(
			helpers.KubeSystemNamespace, l7Policy, helpers.KubectlApply, timeout)
		Expect(err).Should(BeNil(), "cannot import l7 policy: %v", l7Policy)

		waitEndpointReady()

		appPods := helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "id")

		res := kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
		res.ExpectSuccess("Cannot curl app1-service")

		By("Updating cilium to master image")

		localImage := "k8s1:5000/cilium/cilium-dev:latest"
		resource := "daemonset/cilium"

		kubectl.Exec(fmt.Sprintf("%s -n %s set image %s cilium-agent=%s",
			helpers.KubectlCmd, helpers.KubeSystemNamespace,
			resource, localImage)).ExpectSuccess(
			"Cannot update image")

		kubectl.Exec(fmt.Sprintf("%s rollout status %s -n %s",
			helpers.KubectlCmd, resource,
			helpers.KubeSystemNamespace)).ExpectSuccess("Cannot rollout the change")

		waitForUpdateImage := func() bool {
			pods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
			if err != nil {
				return false
			}

			filter := `{.items[*].status.containerStatuses[0].image}`
			data, err := kubectl.GetPods(
				helpers.KubeSystemNamespace, "-l k8s-app=cilium").Filter(filter)
			if err != nil {
				return false
			}
			number := strings.Count(data.String(), localImage)
			if number == len(pods) {
				return true
			}
			logger.Infof("Only '%v' of '%v' cilium pods updated to the new image",
				number, len(pods))
			return false
		}

		err = helpers.WithTimeout(
			waitForUpdateImage,
			"Cilium Pods are not updating correctly",
			&helpers.TimeoutConfig{Timeout: timeout})
		Expect(err).To(BeNil(), "Pods are not updating")

		status, err := kubectl.WaitforPods(
			helpers.KubeSystemNamespace, "-l k8s-app=cilium", timeout)
		Expect(status).Should(BeTrue(), "Cilium is not ready after timeout")
		Expect(err).Should(BeNil(), "Cilium is not ready after timeout")

		validatedImage(localImage)
		res = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
		res.ExpectSuccess("Cannot curl service after update")
	})
})
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/binary"
	"io/ioutil"

	"github.com/privacybydesign/irmago/internal/keysharecore"
	"github.com/sietseringers/cobra"
)

var keyshareKeygen = &cobra.Command{
	Use:   "keygen",
	Short: "Generate storage key for keyshare server",
	RunE: func(command *cobra.Command, args []string) error {
		filename, err := command.Flags().GetString("key-file")
		if err != nil {
			return err
		}

		counter, err := command.Flags().GetUint32("counter")
		if err != nil {
			return err
		}

		key, err := keysharecore.GenerateAESKey()
		if err != nil {
			return err
		}

		keydata := make([]byte, 4+len(key[:]))
		binary.LittleEndian.PutUint32(keydata, counter)
		copy(keydata[4:], key[:])

		return ioutil.WriteFile(filename, keydata, 0600)
	},
}

func init() {
	keyshareRoot.AddCommand(keyshareKeygen)

	flags := keyshareKeygen.Flags()
	flags.SortFlags = false

	flags.StringP("key-file", "k", "storagekey.aes", "File to write key to")
	flags.Uint32P("counter", "c", 0, "Set counter for number of generated storage keys")
}
<commit_msg>feat: improve error messages of irma keyshare keygen<commit_after>package cmd

import (
	"encoding/binary"
	"io/ioutil"

	"github.com/privacybydesign/irmago/internal/keysharecore"
	"github.com/sietseringers/cobra"
)

var keyshareKeygen = &cobra.Command{
	Use:   "keygen",
	Short: "Generate storage key for keyshare server",
	Run: func(command *cobra.Command, args []string) {
		filename, err := command.Flags().GetString("key-file")
		if err != nil {
			die("", err)
		}

		counter, err := command.Flags().GetUint32("counter")
		if err != nil {
			die("", err)
		}

		key, err := keysharecore.GenerateAESKey()
		if err != nil {
			die("", err)
		}

		keydata := make([]byte, 4+len(key[:]))
		binary.LittleEndian.PutUint32(keydata, counter)
		copy(keydata[4:], key[:])

		err = ioutil.WriteFile(filename, keydata, 0600)
		if err != nil {
			die("", err)
		}
	},
}

func init() {
	keyshareRoot.AddCommand(keyshareKeygen)

	flags := keyshareKeygen.Flags()
	flags.SortFlags = false

	flags.StringP("key-file", "k", "storagekey.aes", "File to write key to")
	flags.Uint32P("counter", "c", 0, "Set counter for number of generated storage keys")
}
<|endoftext|>