<commit_before>/*
xslate is an extremely powerful template engine, based on Perl5's Text::Xslate
module. Xslate uses a virtual machine to execute pre-compiled template bytecode,
which gives its flexibility while maitaining a very fast execution speed.

Note that RenderString() DOES NOT CACHE THE GENERATED BYTECODE. This has
significant effect on performance if you repeatedly call the same template

*/
package xslate

import (
  "errors"
  "fmt"
  "io/ioutil"
  "os"
  "reflect"

  "github.com/lestrrat/go-xslate/compiler"
  "github.com/lestrrat/go-xslate/loader"
  "github.com/lestrrat/go-xslate/parser"
  "github.com/lestrrat/go-xslate/parser/tterse"
  "github.com/lestrrat/go-xslate/vm"
)

type Vars vm.Vars
type Xslate struct {
  Flags    int32
  Vm       *vm.VM
  Compiler compiler.Compiler
  Parser   parser.Parser
  Loader   loader.ByteCodeLoader
  // XXX Need to make syntax pluggable
}

type ConfigureArgs interface {
  Get(string) (interface {}, bool)
}

type Args map[string]interface {}

// Given an unconfigured Xslate instance and arguments, sets up
// the compiler of said Xslate instance. Current implementation
// just uses compiler.New()
func DefaultCompiler(tx *Xslate, args Args) error {
  tx.Compiler = compiler.New()
  return nil
}

func DefaultParser(tx *Xslate, args Args) error {
  syntax, ok := args.Get("Syntax")
  if ! ok {
    syntax = "TTerse"
  }

  switch syntax {
  case "TTerse":
    tx.Parser = tterse.New()
  default:
    return errors.New(fmt.Sprintf("Syntax '%s' not available", syntax))
  }
  return nil
}

func DefaultLoader(tx *Xslate, args Args) error {
  var tmp interface {}

  tmp, ok := args.Get("CacheDir")
  if !ok {
    tmp, _ = ioutil.TempDir("", "go-xslate-cache-")
  }
  cacheDir := tmp.(string)

  tmp, ok = args.Get("LoadPaths")
  if !ok {
    cwd, _ := os.Getwd()
    tmp = []string { cwd }
  }
  paths := tmp.([]string)

  cache, err := loader.NewFileCache(cacheDir)
  if err != nil {
    return err
  }
  fetcher, err := loader.NewFileTemplateFetcher(paths)
  if err != nil {
    return err
  }
  tx.Loader = loader.NewCachedByteCodeLoader(cache, fetcher, tx.Parser, tx.Compiler)
  return nil
}

func DefaultVm(tx *Xslate, args Args) error {
  tx.Vm = vm.NewVM()
  tx.Vm.Loader = tx.Loader
  return nil
}

func (args Args) Get(key string) (interface {}, bool) {
  ret, ok := args[key]
  return ret, ok
}

func (tx *Xslate) configureGeneric(configuror interface {}, args Args) error {
  ref := reflect.ValueOf(configuror)
  switch ref.Type().Kind() {
  case reflect.Func:
    // If this is a function, it better take our Xslate instance as the
    // sole argument, and initialize it as it pleases
    if ref.Type().NumIn() != 2 && (ref.Type().In(0).Name() != "Xslate" || ref.Type().In(1).Name() != "Args") {
      panic(fmt.Sprintf(`Expected function initializer "func (tx *Xslate ", but instead of %s`, ref.Type))
    }
    cb := configuror.(func(*Xslate, Args) error)
    err := cb(tx, args)
    return err
  }
  return errors.New("Bad configurator")
}

func (tx *Xslate) Configure(args ConfigureArgs) error {
  // The compiler currently does not have any configurable options, but
  // one may want to replace the entire compiler struct
  defaults := map[string]func(*Xslate, Args) error {
    "Compiler": DefaultCompiler,
    "Parser":   DefaultParser,
    "Loader":   DefaultLoader,
    "Vm":       DefaultVm,
  }

  for _, key := range []string { "Parser", "Compiler", "Loader", "Vm" } {
    configKey := "Configure" + key
    configuror, ok := args.Get(configKey);
    if !ok {
      configuror = defaults[key]
    }

    args, ok := args.Get(key)
    if !ok {
      args = Args {}
    }

    err := tx.configureGeneric(configuror, args.(Args))
    if err != nil {
      return err
    }
  }

  return nil
}

func New(args ...Args) (*Xslate, error) {
  tx := &Xslate {}

  // We jump through hoops because there are A LOT of configuration options
  // but most of them only need to use the default values
  if len(args) <= 0 {
    args = []Args { Args {} }
  }
  err := tx.Configure(args[0])
  if err != nil {
    return nil, err
  }
  return tx, nil
}

func (tx *Xslate) DumpAST(b bool) {
  tx.Loader.DumpAST(b)
}

func (tx *Xslate) DumpByteCode(b bool) {
  tx.Loader.DumpByteCode(b)
}

func (x *Xslate) Render(name string, vars Vars) (string, error) {
  bc, err := x.Loader.Load(name)
  if err != nil {
    return "", err
  }
  x.Vm.Run(bc, vm.Vars(vars))
  return x.Vm.OutputString()
}

func (x *Xslate) RenderString(template string, vars Vars) (string, error) {
  bc, err := x.Loader.LoadString(template)
  if err != nil {
    return "", err
  }

  x.Vm.Run(bc, vm.Vars(vars))
  return x.Vm.OutputString()
}
<commit_msg>Respect go vet<commit_after>/*
xslate is an extremely powerful template engine, based on Perl5's Text::Xslate
module. Xslate uses a virtual machine to execute pre-compiled template bytecode,
which gives its flexibility while maitaining a very fast execution speed.

Note that RenderString() DOES NOT CACHE THE GENERATED BYTECODE. This has
significant effect on performance if you repeatedly call the same template

*/
package xslate

import (
  "errors"
  "fmt"
  "io/ioutil"
  "os"
  "reflect"

  "github.com/lestrrat/go-xslate/compiler"
  "github.com/lestrrat/go-xslate/loader"
  "github.com/lestrrat/go-xslate/parser"
  "github.com/lestrrat/go-xslate/parser/tterse"
  "github.com/lestrrat/go-xslate/vm"
)

type Vars vm.Vars
type Xslate struct {
  Flags    int32
  Vm       *vm.VM
  Compiler compiler.Compiler
  Parser   parser.Parser
  Loader   loader.ByteCodeLoader
  // XXX Need to make syntax pluggable
}

type ConfigureArgs interface {
  Get(string) (interface {}, bool)
}

type Args map[string]interface {}

// Given an unconfigured Xslate instance and arguments, sets up
// the compiler of said Xslate instance. Current implementation
// just uses compiler.New()
func DefaultCompiler(tx *Xslate, args Args) error {
  tx.Compiler = compiler.New()
  return nil
}

func DefaultParser(tx *Xslate, args Args) error {
  syntax, ok := args.Get("Syntax")
  if ! ok {
    syntax = "TTerse"
  }

  switch syntax {
  case "TTerse":
    tx.Parser = tterse.New()
  default:
    return errors.New(fmt.Sprintf("Syntax '%s' not available", syntax))
  }
  return nil
}

func DefaultLoader(tx *Xslate, args Args) error {
  var tmp interface {}

  tmp, ok := args.Get("CacheDir")
  if !ok {
    tmp, _ = ioutil.TempDir("", "go-xslate-cache-")
  }
  cacheDir := tmp.(string)

  tmp, ok = args.Get("LoadPaths")
  if !ok {
    cwd, _ := os.Getwd()
    tmp = []string { cwd }
  }
  paths := tmp.([]string)

  cache, err := loader.NewFileCache(cacheDir)
  if err != nil {
    return err
  }
  fetcher, err := loader.NewFileTemplateFetcher(paths)
  if err != nil {
    return err
  }
  tx.Loader = loader.NewCachedByteCodeLoader(cache, fetcher, tx.Parser, tx.Compiler)
  return nil
}

func DefaultVm(tx *Xslate, args Args) error {
  tx.Vm = vm.NewVM()
  tx.Vm.Loader = tx.Loader
  return nil
}

func (args Args) Get(key string) (interface {}, bool) {
  ret, ok := args[key]
  return ret, ok
}

func (tx *Xslate) configureGeneric(configuror interface {}, args Args) error {
  ref := reflect.ValueOf(configuror)
  switch ref.Type().Kind() {
  case reflect.Func:
    // If this is a function, it better take our Xslate instance as the
    // sole argument, and initialize it as it pleases
    if ref.Type().NumIn() != 2 && (ref.Type().In(0).Name() != "Xslate" || ref.Type().In(1).Name() != "Args") {
      panic(fmt.Sprintf(`Expected function initializer "func (tx *Xslate ", but instead of %s`, ref.Type.String()))
    }
    cb := configuror.(func(*Xslate, Args) error)
    err := cb(tx, args)
    return err
  }
  return errors.New("Bad configurator")
}

func (tx *Xslate) Configure(args ConfigureArgs) error {
  // The compiler currently does not have any configurable options, but
  // one may want to replace the entire compiler struct
  defaults := map[string]func(*Xslate, Args) error {
    "Compiler": DefaultCompiler,
    "Parser":   DefaultParser,
    "Loader":   DefaultLoader,
    "Vm":       DefaultVm,
  }

  for _, key := range []string { "Parser", "Compiler", "Loader", "Vm" } {
    configKey := "Configure" + key
    configuror, ok := args.Get(configKey);
    if !ok {
      configuror = defaults[key]
    }

    args, ok := args.Get(key)
    if !ok {
      args = Args {}
    }

    err := tx.configureGeneric(configuror, args.(Args))
    if err != nil {
      return err
    }
  }

  return nil
}

func New(args ...Args) (*Xslate, error) {
  tx := &Xslate {}

  // We jump through hoops because there are A LOT of configuration options
  // but most of them only need to use the default values
  if len(args) <= 0 {
    args = []Args { Args {} }
  }
  err := tx.Configure(args[0])
  if err != nil {
    return nil, err
  }
  return tx, nil
}

func (tx *Xslate) DumpAST(b bool) {
  tx.Loader.DumpAST(b)
}

func (tx *Xslate) DumpByteCode(b bool) {
  tx.Loader.DumpByteCode(b)
}

func (x *Xslate) Render(name string, vars Vars) (string, error) {
  bc, err := x.Loader.Load(name)
  if err != nil {
    return "", err
  }
  x.Vm.Run(bc, vm.Vars(vars))
  return x.Vm.OutputString()
}

func (x *Xslate) RenderString(template string, vars Vars) (string, error) {
  bc, err := x.Loader.LoadString(template)
  if err != nil {
    return "", err
  }

  x.Vm.Run(bc, vm.Vars(vars))
  return x.Vm.OutputString()
}
<|endoftext|>


<commit_before>// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
// at http://cyan4973.github.io/xxHash/.
package xxhash

import (
	"encoding/binary"
	"hash"
	"reflect"
	"unsafe"
)

const (
	prime1 uint64 = 11400714785074694791
	prime2 uint64 = 14029467366897019727
	prime3 uint64 = 1609587929392839161
	prime4 uint64 = 9650029242287828579
	prime5 uint64 = 2870177450012600261
)

// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
// possible in the Go code is worth a small (but measurable) performance boost
// by avoiding some MOVQs. Vars are needed for the asm and also are useful for
// convenience in the Go code in a few places where we need to intentionally
// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
// result overflows a uint64).
var (
	prime1v = prime1
	prime2v = prime2
	prime3v = prime3
	prime4v = prime4
	prime5v = prime5
)

// Sum64String computes the 64-bit xxHash digest of s.
// It may be faster than Sum64([]byte(s)) by avoiding a copy.
//
// TODO(caleb): Consider removing this if an optimization is ever added to make
// it unnecessary: https://golang.org/issue//2205.
//
// TODO(caleb): We still have a function call; we could instead write Go/asm
// copies of Sum64 for strings to squeeze out a bit more speed.
func Sum64String(s string) uint64 {
	var b []byte
	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
	bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	bh.Data = uintptr(unsafe.Pointer(sh.Data))
	bh.Len = sh.Len
	bh.Cap = sh.Len
	return Sum64(b)
}

type xxh struct {
	v1    uint64
	v2    uint64
	v3    uint64
	v4    uint64
	total int
	mem   [32]byte
	n     int // how much of mem is used
}

// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm.
func New() hash.Hash64 {
	var x xxh
	x.Reset()
	return &x
}

func (x *xxh) Reset() {
	x.n = 0
	x.total = 0
	x.v1 = prime1v + prime2
	x.v2 = prime2
	x.v3 = 0
	x.v4 = -prime1v
}

func (x *xxh) Size() int      { return 8 }
func (x *xxh) BlockSize() int { return 32 }

// Write adds more data to x. It always returns len(b), nil.
func (x *xxh) Write(b []byte) (n int, err error) {
	n = len(b)
	x.total += len(b)

	if x.n+len(b) < 32 {
		// This new data doesn't even fill the current block.
		copy(x.mem[x.n:], b)
		x.n += len(b)
		return
	}

	if x.n > 0 {
		// Finish off the partial block.
		copy(x.mem[x.n:], b)
		x.v1 = round(x.v1, u64(x.mem[0:8]))
		x.v2 = round(x.v2, u64(x.mem[8:16]))
		x.v3 = round(x.v3, u64(x.mem[16:24]))
		x.v4 = round(x.v4, u64(x.mem[24:32]))
		b = b[32-x.n:]
		x.n = 0
	}

	if len(b) >= 32 {
		// One or more full blocks left.
		b = writeBlocks(x, b)
	}

	// Store any remaining partial block.
	copy(x.mem[:], b)
	x.n = len(b)

	return
}

func (x *xxh) Sum(b []byte) []byte {
	s := x.Sum64()
	return append(
		b,
		byte(s>>56),
		byte(s>>48),
		byte(s>>40),
		byte(s>>32),
		byte(s>>24),
		byte(s>>16),
		byte(s>>8),
		byte(s),
	)
}

func (x *xxh) Sum64() uint64 {
	var h uint64

	if x.total >= 32 {
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = x.v3 + prime5
	}

	h += uint64(x.total)

	i, end := 0, x.n
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(x.mem[i:i+8]))
		h ^= k1
		h = rol27(h)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(x.mem[i:i+4])) * prime1
		h = rol23(h)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(x.mem[i]) * prime5
		h = rol11(h) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h
}

func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }

func round(acc, input uint64) uint64 {
	acc += input * prime2
	acc = rol31(acc)
	acc *= prime1
	return acc
}

func mergeRound(acc, val uint64) uint64 {
	val = round(0, val)
	acc ^= val
	acc = acc*prime1 + prime4
	return acc
}

// It's important for performance to get the rotates to actually compile to
// ROLQs. gc will do this for us but only if rotate amount is a constant.
//
// TODO(caleb): In Go 1.9 a single function
//   rol(x uint64, k uint) uint64
// should do instead. See https://golang.org/issue/18254.
//
// TODO(caleb): In Go 1.x (1.9?) consider using the new math/bits package to be more
// explicit about things. See https://golang.org/issue/18616.

func rol1(x uint64) uint64  { return (x << 1) | (x >> (64 - 1)) }
func rol7(x uint64) uint64  { return (x << 7) | (x >> (64 - 7)) }
func rol11(x uint64) uint64 { return (x << 11) | (x >> (64 - 11)) }
func rol12(x uint64) uint64 { return (x << 12) | (x >> (64 - 12)) }
func rol18(x uint64) uint64 { return (x << 18) | (x >> (64 - 18)) }
func rol23(x uint64) uint64 { return (x << 23) | (x >> (64 - 23)) }
func rol27(x uint64) uint64 { return (x << 27) | (x >> (64 - 27)) }
func rol31(x uint64) uint64 { return (x << 31) | (x >> (64 - 31)) }
<commit_msg>Remove unnecessary type conversions<commit_after>// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
// at http://cyan4973.github.io/xxHash/.
package xxhash

import (
	"encoding/binary"
	"hash"
	"reflect"
	"unsafe"
)

const (
	prime1 uint64 = 11400714785074694791
	prime2 uint64 = 14029467366897019727
	prime3 uint64 = 1609587929392839161
	prime4 uint64 = 9650029242287828579
	prime5 uint64 = 2870177450012600261
)

// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
// possible in the Go code is worth a small (but measurable) performance boost
// by avoiding some MOVQs. Vars are needed for the asm and also are useful for
// convenience in the Go code in a few places where we need to intentionally
// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
// result overflows a uint64).
var (
	prime1v = prime1
	prime2v = prime2
	prime3v = prime3
	prime4v = prime4
	prime5v = prime5
)

// Sum64String computes the 64-bit xxHash digest of s.
// It may be faster than Sum64([]byte(s)) by avoiding a copy.
//
// TODO(caleb): Consider removing this if an optimization is ever added to make
// it unnecessary: https://golang.org/issue//2205.
//
// TODO(caleb): We still have a function call; we could instead write Go/asm
// copies of Sum64 for strings to squeeze out a bit more speed.
func Sum64String(s string) uint64 {
	var b []byte
	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
	bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	bh.Data = sh.Data
	bh.Len = sh.Len
	bh.Cap = sh.Len
	return Sum64(b)
}

type xxh struct {
	v1    uint64
	v2    uint64
	v3    uint64
	v4    uint64
	total int
	mem   [32]byte
	n     int // how much of mem is used
}

// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm.
func New() hash.Hash64 {
	var x xxh
	x.Reset()
	return &x
}

func (x *xxh) Reset() {
	x.n = 0
	x.total = 0
	x.v1 = prime1v + prime2
	x.v2 = prime2
	x.v3 = 0
	x.v4 = -prime1v
}

func (x *xxh) Size() int      { return 8 }
func (x *xxh) BlockSize() int { return 32 }

// Write adds more data to x. It always returns len(b), nil.
func (x *xxh) Write(b []byte) (n int, err error) {
	n = len(b)
	x.total += len(b)

	if x.n+len(b) < 32 {
		// This new data doesn't even fill the current block.
		copy(x.mem[x.n:], b)
		x.n += len(b)
		return
	}

	if x.n > 0 {
		// Finish off the partial block.
		copy(x.mem[x.n:], b)
		x.v1 = round(x.v1, u64(x.mem[0:8]))
		x.v2 = round(x.v2, u64(x.mem[8:16]))
		x.v3 = round(x.v3, u64(x.mem[16:24]))
		x.v4 = round(x.v4, u64(x.mem[24:32]))
		b = b[32-x.n:]
		x.n = 0
	}

	if len(b) >= 32 {
		// One or more full blocks left.
		b = writeBlocks(x, b)
	}

	// Store any remaining partial block.
	copy(x.mem[:], b)
	x.n = len(b)

	return
}

func (x *xxh) Sum(b []byte) []byte {
	s := x.Sum64()
	return append(
		b,
		byte(s>>56),
		byte(s>>48),
		byte(s>>40),
		byte(s>>32),
		byte(s>>24),
		byte(s>>16),
		byte(s>>8),
		byte(s),
	)
}

func (x *xxh) Sum64() uint64 {
	var h uint64

	if x.total >= 32 {
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = x.v3 + prime5
	}

	h += uint64(x.total)

	i, end := 0, x.n
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(x.mem[i:i+8]))
		h ^= k1
		h = rol27(h)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(x.mem[i:i+4])) * prime1
		h = rol23(h)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(x.mem[i]) * prime5
		h = rol11(h) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h
}

func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }

func round(acc, input uint64) uint64 {
	acc += input * prime2
	acc = rol31(acc)
	acc *= prime1
	return acc
}

func mergeRound(acc, val uint64) uint64 {
	val = round(0, val)
	acc ^= val
	acc = acc*prime1 + prime4
	return acc
}

// It's important for performance to get the rotates to actually compile to
// ROLQs. gc will do this for us but only if rotate amount is a constant.
//
// TODO(caleb): In Go 1.9 a single function
//   rol(x uint64, k uint) uint64
// should do instead. See https://golang.org/issue/18254.
//
// TODO(caleb): In Go 1.x (1.9?) consider using the new math/bits package to be more
// explicit about things. See https://golang.org/issue/18616.

func rol1(x uint64) uint64  { return (x << 1) | (x >> (64 - 1)) }
func rol7(x uint64) uint64  { return (x << 7) | (x >> (64 - 7)) }
func rol11(x uint64) uint64 { return (x << 11) | (x >> (64 - 11)) }
func rol12(x uint64) uint64 { return (x << 12) | (x >> (64 - 12)) }
func rol18(x uint64) uint64 { return (x << 18) | (x >> (64 - 18)) }
func rol23(x uint64) uint64 { return (x << 23) | (x >> (64 - 23)) }
func rol27(x uint64) uint64 { return (x << 27) | (x >> (64 - 27)) }
func rol31(x uint64) uint64 { return (x << 31) | (x >> (64 - 31)) }
<|endoftext|>


<commit_before>// Copyright (c) 2017 Pani Networks
// 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.

// Romana CNI plugin configures kubernetes pods on Romana network.
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"runtime"
	"syscall"

	"github.com/romana/core/pkg/cni/kubernetes"

	"github.com/containernetworking/cni/pkg/ip"
	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/containernetworking/cni/pkg/version"
	util "github.com/romana/core/pkg/cni"
	log "github.com/romana/rlog"
	"github.com/vishvananda/netlink"
)

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

// cmdAdd is a callback functions that gets called by skel.PluginMain
// in response to ADD method.
func cmdAdd(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, _, _ := loadConf(args.StdinData)
	cniVersion := netConf.CNIVersion
	log.Debugf("Loaded netConf %v", netConf)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := kubernetes.K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return fmt.Errorf("Failed to types.LoadArgs, err=%(err)", err)
	}
	log.Debugf("Loaded Kubernetes args %v", k8sargs)

	// Retrieves additional information about the pod
	pod, err := kubernetes.GetPodDescription(k8sargs, netConf.KubernetesConfig)
	if err != nil {
		return err
	}

	// Deferring deallocation before allocating ip address,
	// deallocation will be called on any return unless
	// flag set to false.
	var deallocateOnExit = true
	defer func() {
		if deallocateOnExit {
			deallocator, err := util.NewRomanaAddressManager(util.DefaultProvider)

			// don't want to panic here
			if netConf != nil && err == nil {
				log.Errorf("Deallocating IP on exist, something went wrong")
				_ = deallocator.Deallocate(*netConf, pod.Name)
			}
		}
	}()

	// Allocating ip address.
	allocator, err := util.NewRomanaAddressManager(util.DefaultProvider)
	if err != nil {
		return err
	}
	podAddress, err := allocator.Allocate(*netConf, util.RomanaAllocatorPodDescription{
		Name:        pod.Name,
		Hostname:    netConf.RomanaHostName,
		Namespace:   pod.Namespace,
		Labels:      pod.Labels,
		Annotations: pod.Annotations,
	})
	if err != nil {
		return err
	}

	// Networking setup
	_, gwAddr, err := GetRomanaGwAddr()
	if err != nil {
		return fmt.Errorf("Failed to detect ipv4 address on romana-gw interface, err=(%s)", err)
	}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	// Magic variables for callback.
	contIface := &current.Interface{}
	hostIface := &current.Interface{}
	ifName := "eth0"
	mtu := 1500 //TODO for stas, make configurable
	_, defaultNet, _ := net.ParseCIDR("0.0.0.0/0")

	// And this is a callback inside the callback, it sets up networking
	// withing a pod namespace, nice thing it save us from shellouts
	// but still, callback within a callback.
	err = netns.Do(func(hostNS ns.NetNS) error {
		// Creates veth interfacces.
		hostVeth, containerVeth, err := ip.SetupVeth(ifName, mtu, hostNS)
		if err != nil {
			return err
		}

		// transportNet is a romana-gw cidr turned into romana-gw.IP/32
		transportNet := net.IPNet{IP: gwAddr.IP, Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}
		transportRoute := netlink.Route{
			LinkIndex: containerVeth.Index,
			Dst:       &transportNet,
		}

		// sets up transport route to allow installing default route
		err = netlink.RouteAdd(&transportRoute)
		if err != nil {
			return fmt.Errorf("route add error=(%s)", err)
		}

		// default route for the pod
		defaultRoute := netlink.Route{
			Dst:       defaultNet,
			LinkIndex: containerVeth.Index,
		}
		err = netlink.RouteAdd(&defaultRoute)
		if err != nil {
			return fmt.Errorf("route add default error=(%s)", err)
		}

		containerVethLink, err := netlink.LinkByIndex(containerVeth.Index)
		if err != nil {
			return fmt.Errorf("failed to discover container veth, err=(%s)", err)
		}

		podIP, err := netlink.ParseAddr(podAddress.String())
		if err != nil {
			return fmt.Errorf("netlink failed to parse address %s, err=(%s)", podAddress, err)
		}

		err = netlink.AddrAdd(containerVethLink, podIP)
		if err != nil {
			return fmt.Errorf("failed to add ip address %s to the interface %s, err=(%s)", podIP, containerVeth, err)
		}

		contIface.Name = containerVeth.Name
		contIface.Mac = containerVeth.HardwareAddr.String()
		contIface.Sandbox = netns.Path()
		hostIface.Name = hostVeth.Name
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create veth interfaces in namespace %v, err=(%s)", netns, err)
	}

	// Rename host part of veth to something convinient.
	vethExternalName := k8sargs.MakeVethName()
	err = RenameLink(hostIface.Name, vethExternalName)
	if err != nil {
		return fmt.Errorf("Failed to rename host part of veth interface from %s to %s, err=(%s)", hostIface.Name, vethExternalName, err)
	}

	// Return route.
	err = AddEndpointRoute(vethExternalName, podAddress)
	if err != nil {
		return fmt.Errorf("Failed to setup return route to %s via interface %s, err=(%s)", podAddress, hostIface.Name, err)
	}

	result := &current.Result{
		IPs: []*current.IPConfig{
			&current.IPConfig{
				Version:   "4",
				Address:   *podAddress,
				Interface: 0,
			},
		},
	}

	result.Interfaces = []*current.Interface{hostIface}

	deallocateOnExit = false
	return types.PrintResult(result, cniVersion)
}

// cmdDel is a callback functions that gets called by skel.PluginMain
// in response to DEL method.
func cmdDel(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, _, _ := loadConf(args.StdinData)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := kubernetes.K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return err
	}

	deallocator, err := util.NewRomanaAddressManager(util.DefaultProvider)
	if err != nil {
		return err
	}
	err = deallocator.Deallocate(*netConf, k8sargs.MakePodName())
	if err != nil {
		return fmt.Errorf("Failed to tear down pod network for %s, err=(%s)", k8sargs.MakePodName(), err)
	}

	return nil
}

// GetRomanaGwAddr detects ip address assigned to romana-gw interface.
func GetRomanaGwAddr() (netlink.Link, *net.IPNet, error) {
	const gwIface = "romana-gw"
	romanaGw, err := netlink.LinkByName(gwIface)
	if err != nil {
		return nil, nil, err
	}

	addr, err := netlink.AddrList(romanaGw, syscall.AF_INET)
	if err != nil {
		return nil, nil, err
	}

	if len(addr) != 1 {
		return nil, nil, fmt.Errorf("Expected exactly 1 ipv4 address on romana-gw interface, found %d", len(addr))
	}

	return romanaGw, addr[0].IPNet, nil
}

// RenameLink renames interface.
func RenameLink(curName, newName string) error {
	curVeth, err := netlink.LinkByName(curName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", curName, err)
	}

	if err = netlink.LinkSetDown(curVeth); err != nil {
		return fmt.Errorf("failed to set %q up: %v", curName, err)
	}

	err = netlink.LinkSetName(curVeth, newName)
	if err != nil {
		return fmt.Errorf("failed to rename %q: %v", curVeth, newName)
	}

	newVeth, err := netlink.LinkByName(newName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", newName, err)
	}

	err = netlink.LinkSetUp(newVeth)
	if err != nil {
		return fmt.Errorf("failed to set %q up: %v", newVeth, err)
	}

	return nil
}

// AddEndpointRoute adds return /32 route from host to pod.
func AddEndpointRoute(ifaceName string, ip *net.IPNet) error {
	veth, err := netlink.LinkByName(ifaceName)
	if err != nil {
		return err
	}

	returnRoute := netlink.Route{
		Dst:       ip,
		LinkIndex: veth.Attrs().Index,
	}

	err = netlink.RouteAdd(&returnRoute)

	return nil
}

// loadConf initializes romana config from stdin.
func loadConf(bytes []byte) (*util.NetConf, string, error) {
	n := &util.NetConf{}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, "", fmt.Errorf("failed to load netconf: %s", err)
	}

	// TODO for stas
	// verify config here
	if n.RomanaHostName == "" {
		hostname, err := os.Hostname()
		if err != nil {
			return nil, "", fmt.Errorf("failed to load netconf: %s", err)
		}

		n.RomanaHostName = hostname
	}

	return n, n.CNIVersion, nil
}

func main() {
	skel.PluginMain(cmdAdd, cmdDel, version.All)
}
<commit_msg>Formating verb fix<commit_after>// Copyright (c) 2017 Pani Networks
// 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.

// Romana CNI plugin configures kubernetes pods on Romana network.
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"runtime"
	"syscall"

	"github.com/romana/core/pkg/cni/kubernetes"

	"github.com/containernetworking/cni/pkg/ip"
	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/containernetworking/cni/pkg/version"
	util "github.com/romana/core/pkg/cni"
	log "github.com/romana/rlog"
	"github.com/vishvananda/netlink"
)

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

// cmdAdd is a callback functions that gets called by skel.PluginMain
// in response to ADD method.
func cmdAdd(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, _, _ := loadConf(args.StdinData)
	cniVersion := netConf.CNIVersion
	log.Debugf("Loaded netConf %v", netConf)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := kubernetes.K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return fmt.Errorf("Failed to types.LoadArgs, err=(%s)", err)
	}
	log.Debugf("Loaded Kubernetes args %v", k8sargs)

	// Retrieves additional information about the pod
	pod, err := kubernetes.GetPodDescription(k8sargs, netConf.KubernetesConfig)
	if err != nil {
		return err
	}

	// Deferring deallocation before allocating ip address,
	// deallocation will be called on any return unless
	// flag set to false.
	var deallocateOnExit = true
	defer func() {
		if deallocateOnExit {
			deallocator, err := util.NewRomanaAddressManager(util.DefaultProvider)

			// don't want to panic here
			if netConf != nil && err == nil {
				log.Errorf("Deallocating IP on exist, something went wrong")
				_ = deallocator.Deallocate(*netConf, pod.Name)
			}
		}
	}()

	// Allocating ip address.
	allocator, err := util.NewRomanaAddressManager(util.DefaultProvider)
	if err != nil {
		return err
	}
	podAddress, err := allocator.Allocate(*netConf, util.RomanaAllocatorPodDescription{
		Name:        pod.Name,
		Hostname:    netConf.RomanaHostName,
		Namespace:   pod.Namespace,
		Labels:      pod.Labels,
		Annotations: pod.Annotations,
	})
	if err != nil {
		return err
	}

	// Networking setup
	_, gwAddr, err := GetRomanaGwAddr()
	if err != nil {
		return fmt.Errorf("Failed to detect ipv4 address on romana-gw interface, err=(%s)", err)
	}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	// Magic variables for callback.
	contIface := &current.Interface{}
	hostIface := &current.Interface{}
	ifName := "eth0"
	mtu := 1500 //TODO for stas, make configurable
	_, defaultNet, _ := net.ParseCIDR("0.0.0.0/0")

	// And this is a callback inside the callback, it sets up networking
	// withing a pod namespace, nice thing it save us from shellouts
	// but still, callback within a callback.
	err = netns.Do(func(hostNS ns.NetNS) error {
		// Creates veth interfacces.
		hostVeth, containerVeth, err := ip.SetupVeth(ifName, mtu, hostNS)
		if err != nil {
			return err
		}

		// transportNet is a romana-gw cidr turned into romana-gw.IP/32
		transportNet := net.IPNet{IP: gwAddr.IP, Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}
		transportRoute := netlink.Route{
			LinkIndex: containerVeth.Index,
			Dst:       &transportNet,
		}

		// sets up transport route to allow installing default route
		err = netlink.RouteAdd(&transportRoute)
		if err != nil {
			return fmt.Errorf("route add error=(%s)", err)
		}

		// default route for the pod
		defaultRoute := netlink.Route{
			Dst:       defaultNet,
			LinkIndex: containerVeth.Index,
		}
		err = netlink.RouteAdd(&defaultRoute)
		if err != nil {
			return fmt.Errorf("route add default error=(%s)", err)
		}

		containerVethLink, err := netlink.LinkByIndex(containerVeth.Index)
		if err != nil {
			return fmt.Errorf("failed to discover container veth, err=(%s)", err)
		}

		podIP, err := netlink.ParseAddr(podAddress.String())
		if err != nil {
			return fmt.Errorf("netlink failed to parse address %s, err=(%s)", podAddress, err)
		}

		err = netlink.AddrAdd(containerVethLink, podIP)
		if err != nil {
			return fmt.Errorf("failed to add ip address %s to the interface %s, err=(%s)", podIP, containerVeth, err)
		}

		contIface.Name = containerVeth.Name
		contIface.Mac = containerVeth.HardwareAddr.String()
		contIface.Sandbox = netns.Path()
		hostIface.Name = hostVeth.Name
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create veth interfaces in namespace %v, err=(%s)", netns, err)
	}

	// Rename host part of veth to something convinient.
	vethExternalName := k8sargs.MakeVethName()
	err = RenameLink(hostIface.Name, vethExternalName)
	if err != nil {
		return fmt.Errorf("Failed to rename host part of veth interface from %s to %s, err=(%s)", hostIface.Name, vethExternalName, err)
	}

	// Return route.
	err = AddEndpointRoute(vethExternalName, podAddress)
	if err != nil {
		return fmt.Errorf("Failed to setup return route to %s via interface %s, err=(%s)", podAddress, hostIface.Name, err)
	}

	result := &current.Result{
		IPs: []*current.IPConfig{
			&current.IPConfig{
				Version:   "4",
				Address:   *podAddress,
				Interface: 0,
			},
		},
	}

	result.Interfaces = []*current.Interface{hostIface}

	deallocateOnExit = false
	return types.PrintResult(result, cniVersion)
}

// cmdDel is a callback functions that gets called by skel.PluginMain
// in response to DEL method.
func cmdDel(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, _, _ := loadConf(args.StdinData)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := kubernetes.K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return err
	}

	deallocator, err := util.NewRomanaAddressManager(util.DefaultProvider)
	if err != nil {
		return err
	}
	err = deallocator.Deallocate(*netConf, k8sargs.MakePodName())
	if err != nil {
		return fmt.Errorf("Failed to tear down pod network for %s, err=(%s)", k8sargs.MakePodName(), err)
	}

	return nil
}

// GetRomanaGwAddr detects ip address assigned to romana-gw interface.
func GetRomanaGwAddr() (netlink.Link, *net.IPNet, error) {
	const gwIface = "romana-gw"
	romanaGw, err := netlink.LinkByName(gwIface)
	if err != nil {
		return nil, nil, err
	}

	addr, err := netlink.AddrList(romanaGw, syscall.AF_INET)
	if err != nil {
		return nil, nil, err
	}

	if len(addr) != 1 {
		return nil, nil, fmt.Errorf("Expected exactly 1 ipv4 address on romana-gw interface, found %d", len(addr))
	}

	return romanaGw, addr[0].IPNet, nil
}

// RenameLink renames interface.
func RenameLink(curName, newName string) error {
	curVeth, err := netlink.LinkByName(curName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", curName, err)
	}

	if err = netlink.LinkSetDown(curVeth); err != nil {
		return fmt.Errorf("failed to set %q up: %v", curName, err)
	}

	err = netlink.LinkSetName(curVeth, newName)
	if err != nil {
		return fmt.Errorf("failed to rename %q: %v", curVeth, newName)
	}

	newVeth, err := netlink.LinkByName(newName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", newName, err)
	}

	err = netlink.LinkSetUp(newVeth)
	if err != nil {
		return fmt.Errorf("failed to set %q up: %v", newVeth, err)
	}

	return nil
}

// AddEndpointRoute adds return /32 route from host to pod.
func AddEndpointRoute(ifaceName string, ip *net.IPNet) error {
	veth, err := netlink.LinkByName(ifaceName)
	if err != nil {
		return err
	}

	returnRoute := netlink.Route{
		Dst:       ip,
		LinkIndex: veth.Attrs().Index,
	}

	err = netlink.RouteAdd(&returnRoute)

	return nil
}

// loadConf initializes romana config from stdin.
func loadConf(bytes []byte) (*util.NetConf, string, error) {
	n := &util.NetConf{}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, "", fmt.Errorf("failed to load netconf: %s", err)
	}

	// TODO for stas
	// verify config here
	if n.RomanaHostName == "" {
		hostname, err := os.Hostname()
		if err != nil {
			return nil, "", fmt.Errorf("failed to load netconf: %s", err)
		}

		n.RomanaHostName = hostname
	}

	return n, n.CNIVersion, nil
}

func main() {
	skel.PluginMain(cmdAdd, cmdDel, version.All)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/go-ini/ini"
	"github.com/goadapp/goad/helpers"
	"github.com/goadapp/goad/queue"
)

func main() {

	var (
		address          string
		sqsurl           string
		concurrencycount int
		maxRequestCount  int
		timeout          string
		frequency        string
		awsregion        string
		queueRegion      string
		requestMethod    string
		requestBody      string
		requestHeaders   helpers.StringsliceFlag
	)

	flag.StringVar(&address, "u", "", "URL to load test (required)")
	flag.StringVar(&requestMethod, "m", "GET", "HTTP method")
	flag.StringVar(&requestBody, "b", "", "HTTP request body")
	flag.StringVar(&awsregion, "r", "", "AWS region to run in")
	flag.StringVar(&queueRegion, "q", "", "Queue region")
	flag.StringVar(&sqsurl, "s", "", "sqsUrl")
	flag.StringVar(&timeout, "t", "15s", "request timeout in seconds")
	flag.StringVar(&frequency, "f", "15s", "Reporting frequency in seconds")

	flag.IntVar(&concurrencycount, "c", 10, "number of concurrent requests")
	flag.IntVar(&maxRequestCount, "n", 1000, "number of total requests to make")

	flag.Var(&requestHeaders, "H", "List of headers")
	flag.Parse()

	clientTimeout, _ := time.ParseDuration(timeout)
	fmt.Printf("Using a timeout of %s\n", clientTimeout)
	reportingFrequency, _ := time.ParseDuration(frequency)
	fmt.Printf("Using a reporting frequency of %s\n", reportingFrequency)

	// InsecureSkipVerify so that sites with self signed certs can be tested
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	client.Timeout = clientTimeout

	cfg, err := ini.Load([]byte("raw data"), "default.ini")
	if err == nil {
		address = cfg.Section("general").Key("url").String()
	}
	fmt.Printf("Will spawn %d workers making %d requests to %s\n", concurrencycount, maxRequestCount, address)
	runLoadTest(client, sqsurl, address, maxRequestCount, concurrencycount, awsregion, reportingFrequency, queueRegion, requestMethod, requestBody, requestHeaders)
}

type RequestResult struct {
	Time             int64  `json:"time"`
	Host             string `json:"host"`
	Type             string `json:"type"`
	Status           int    `json:"status"`
	ElapsedFirstByte int64  `json:"elapsed-first-byte"`
	ElapsedLastByte  int64  `json:"elapsed-last-byte"`
	Elapsed          int64  `json:"elapsed"`
	Bytes            int    `json:"bytes"`
	Timeout          bool   `json:"timeout"`
	ConnectionError  bool   `json:"connection-error"`
	State            string `json:"state"`
}

func runLoadTest(client *http.Client, sqsurl string, url string, totalRequests int, concurrencycount int, awsregion string, reportingFrequency time.Duration, queueRegion string, requestMethod string, requestBody string, requestHeaders []string) {
	awsConfig := aws.NewConfig().WithRegion(queueRegion)
	sqsAdaptor := queue.NewSQSAdaptor(awsConfig, sqsurl)
	//sqsAdaptor := queue.NewDummyAdaptor(sqsurl)
	jobs := make(chan struct{}, totalRequests)
	ch := make(chan RequestResult, totalRequests)
	var wg sync.WaitGroup
	loadTestStartTime := time.Now()
	var requestsSoFar int
	for i := 0; i < totalRequests; i++ {
		jobs <- struct{}{}
	}
	close(jobs)
	fmt.Print("Spawning workers…")
	for i := 0; i < concurrencycount; i++ {
		wg.Add(1)
		go fetch(loadTestStartTime, client, url, totalRequests, jobs, ch, &wg, awsregion, requestMethod, requestBody, requestHeaders)
		fmt.Print(".")
	}
	fmt.Println(" done.\nWaiting for results…")

	ticker := time.NewTicker(reportingFrequency)
	quit := make(chan struct{})
	quitting := false

	for requestsSoFar < totalRequests && !quitting {
		i := 0

		var timeToFirstTotal int64
		var requestTimeTotal int64
		totBytesRead := 0
		statuses := make(map[string]int)
		targets := make(map[string]int)
		var firstRequestTime int64
		var lastRequestTime int64
		var slowest int64
		var fastest int64
		var totalTimedOut int
		var totalConnectionError int

		resetStats := false
		for requestsSoFar < totalRequests && !quitting && !resetStats {
			aggregate := false
			select {
			case r := <-ch:
				i++
				requestsSoFar++
				if requestsSoFar%10 == 0 || requestsSoFar == totalRequests {
					fmt.Printf("\r%.2f%% done (%d requests out of %d)", (float64(requestsSoFar)/float64(totalRequests))*100.0, requestsSoFar, totalRequests)
				}
				if firstRequestTime == 0 {
					firstRequestTime = r.Time
				}

				lastRequestTime = r.Time

				if r.Timeout {
					totalTimedOut++
					continue
				}
				if r.ConnectionError {
					totalConnectionError++
					continue
				}

				if r.ElapsedLastByte > slowest {
					slowest = r.ElapsedLastByte
				}
				if fastest == 0 {
					fastest = r.ElapsedLastByte
				} else {
					if r.ElapsedLastByte < fastest {
						fastest = r.ElapsedLastByte
					}
				}

				timeToFirstTotal += r.ElapsedFirstByte
				totBytesRead += r.Bytes
				statusStr := strconv.Itoa(r.Status)
				_, ok1 := statuses[statusStr]
				if !ok1 {
					statuses[statusStr] = 1
				} else {
					statuses[statusStr]++
				}
				_, ok2 := targets[r.Host]
				if !ok2 {
					targets[r.Host] = 1
				} else {
					targets[r.Host]++
				}
				requestTimeTotal += r.Elapsed
				if requestsSoFar == totalRequests {
					quitting = true
				}
			case <-ticker.C:
				if i == 0 {
					continue
				}
				aggregate = true
			case <-quit:
				ticker.Stop()
				quitting = true
			}
			if aggregate || quitting {
				durationNanoSeconds := lastRequestTime - firstRequestTime
				durationSeconds := float32(durationNanoSeconds) / float32(1000000000)
				var reqPerSec float32
				var kbPerSec float32
				if durationSeconds > 0 {
					reqPerSec = float32(i) / durationSeconds
					kbPerSec = (float32(totBytesRead) / durationSeconds) / 1024.0
				} else {
					reqPerSec = 0
					kbPerSec = 0
				}

				fatalError := ""
				if (totalTimedOut + totalConnectionError) > i/2 {
					fatalError = "Over 50% of requests failed, aborting"
					quitting = true
				}
				aggData := queue.AggData{
					i,
					totalTimedOut,
					totalConnectionError,
					timeToFirstTotal / int64(i),
					totBytesRead,
					statuses,
					targets,
					requestTimeTotal / int64(i),
					reqPerSec,
					kbPerSec,
					slowest,
					fastest,
					awsregion,
					fatalError,
				}
				sqsAdaptor.SendResult(aggData)
				resetStats = true
			}
		}
	}
	fmt.Printf("\nYay🎈  - %d requests completed\n", requestsSoFar)

}

func fetch(loadTestStartTime time.Time, client *http.Client, address string, requestcount int, jobs <-chan struct{}, ch chan RequestResult, wg *sync.WaitGroup, awsregion string, requestMethod string, requestBody string, requestHeaders []string) {
	defer wg.Done()
	for _ = range jobs {
		start := time.Now()
		req, err := http.NewRequest(requestMethod, address, bytes.NewBufferString(requestBody))
		if err != nil {
			fmt.Println("Error creating the HTTP request:", err)
			return
		}
		req.Header.Add("Accept-Encoding", "gzip")
		for _, v := range requestHeaders {
			header := strings.Split(v, ":")
			if strings.ToLower(strings.Trim(header[0], " ")) == "host" {
				req.Host = strings.Trim(header[1], " ")
			} else {
				req.Header.Add(strings.Trim(header[0], " "), strings.Trim(header[1], " "))
			}
		}

		if req.Header.Get("User-Agent") == "" {
			req.Header.Add("User-Agent", "Mozilla/5.0 (compatible; Goad/1.0; +https://goad.io)")
		}

		response, err := client.Do(req)
		var status string
		var elapsedFirstByte time.Duration
		var elapsedLastByte time.Duration
		var elapsed time.Duration
		var statusCode int
		var bytesRead int
		buf := []byte(" ")
		timedOut := false
		connectionError := false
		isRedirect := err != nil && strings.Contains(err.Error(), "redirect")
		if err != nil && !isRedirect {
			status = fmt.Sprintf("ERROR: %s\n", err)
			switch err := err.(type) {
			case *url.Error:
				if err, ok := err.Err.(net.Error); ok && err.Timeout() {
					timedOut = true
				}
			case net.Error:
				if err.Timeout() {
					timedOut = true
				}
			}

			if !timedOut {
				connectionError = true
			}
		} else {
			statusCode = response.StatusCode
			elapsedFirstByte = time.Since(start)
			if !isRedirect {
				_, err = response.Body.Read(buf)
				firstByteRead := true
				if err != nil {
					status = fmt.Sprintf("reading first byte failed: %s\n", err)
					firstByteRead = false
				}
				body, err := ioutil.ReadAll(response.Body)
				if firstByteRead {
					bytesRead = len(body) + 1
				}
				elapsedLastByte = time.Since(start)
				if err != nil {
					// todo: detect timeout here as well
					status = fmt.Sprintf("reading response body failed: %s\n", err)
					connectionError = true
				} else {
					status = "Success"
				}
			} else {
				status = "Redirect"
			}
			response.Body.Close()

			elapsed = time.Since(start)
		}
		//fmt.Printf("Request end: %d, elapsed: %d\n", time.Now().Sub(loadTestStartTime).Nanoseconds(), elapsed.Nanoseconds())
		result := RequestResult{
			start.Sub(loadTestStartTime).Nanoseconds(),
			req.URL.Host,
			req.Method,
			statusCode,
			elapsedFirstByte.Nanoseconds(),
			elapsedLastByte.Nanoseconds(),
			elapsed.Nanoseconds(),
			bytesRead,
			timedOut,
			connectionError,
			status,
		}
		ch <- result
	}
}
<commit_msg>default.ini gets now loaded and overrides, ISSUE: goad vanilla code is not really updating itself after a new build is created<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/go-ini/ini"
	"github.com/goadapp/goad/helpers"
	"github.com/goadapp/goad/queue"
)

func main() {

	var (
		address          string
		sqsurl           string
		concurrencycount int
		maxRequestCount  int
		timeout          string
		frequency        string
		awsregion        string
		queueRegion      string
		requestMethod    string
		requestBody      string
		requestHeaders   helpers.StringsliceFlag
	)

	flag.StringVar(&address, "u", "", "URL to load test (required)")
	flag.StringVar(&requestMethod, "m", "GET", "HTTP method")
	flag.StringVar(&requestBody, "b", "", "HTTP request body")
	flag.StringVar(&awsregion, "r", "", "AWS region to run in")
	flag.StringVar(&queueRegion, "q", "", "Queue region")
	flag.StringVar(&sqsurl, "s", "", "sqsUrl")
	flag.StringVar(&timeout, "t", "15s", "request timeout in seconds")
	flag.StringVar(&frequency, "f", "15s", "Reporting frequency in seconds")

	flag.IntVar(&concurrencycount, "c", 10, "number of concurrent requests")
	flag.IntVar(&maxRequestCount, "n", 1000, "number of total requests to make")

	flag.Var(&requestHeaders, "H", "List of headers")
	flag.Parse()

	clientTimeout, _ := time.ParseDuration(timeout)
	fmt.Printf("Using a timeout of %s\n", clientTimeout)
	reportingFrequency, _ := time.ParseDuration(frequency)
	fmt.Printf("Using a reporting frequency of %s\n", reportingFrequency)

	// InsecureSkipVerify so that sites with self signed certs can be tested
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	client.Timeout = clientTimeout

	cfg, err := ini.Load("default.ini")
	if err == nil {
		address = cfg.Section("general").Key("url").String()
	} else {
		log.Print(err)
	}
	fmt.Printf("Will spawn %d workers making %d requests to %s\n", concurrencycount, maxRequestCount, address)
	runLoadTest(client, sqsurl, address, maxRequestCount, concurrencycount, awsregion, reportingFrequency, queueRegion, requestMethod, requestBody, requestHeaders)
}

// RequestResult spitted into SQS by the lambda functions
type RequestResult struct {
	Time             int64  `json:"time"`
	Host             string `json:"host"`
	Type             string `json:"type"`
	Status           int    `json:"status"`
	ElapsedFirstByte int64  `json:"elapsed-first-byte"`
	ElapsedLastByte  int64  `json:"elapsed-last-byte"`
	Elapsed          int64  `json:"elapsed"`
	Bytes            int    `json:"bytes"`
	Timeout          bool   `json:"timeout"`
	ConnectionError  bool   `json:"connection-error"`
	State            string `json:"state"`
}

func runLoadTest(client *http.Client, sqsurl string, url string, totalRequests int, concurrencycount int, awsregion string, reportingFrequency time.Duration, queueRegion string, requestMethod string, requestBody string, requestHeaders []string) {
	awsConfig := aws.NewConfig().WithRegion(queueRegion)
	sqsAdaptor := queue.NewSQSAdaptor(awsConfig, sqsurl)
	//sqsAdaptor := queue.NewDummyAdaptor(sqsurl)
	jobs := make(chan struct{}, totalRequests)
	ch := make(chan RequestResult, totalRequests)
	var wg sync.WaitGroup
	loadTestStartTime := time.Now()
	var requestsSoFar int
	for i := 0; i < totalRequests; i++ {
		jobs <- struct{}{}
	}
	close(jobs)
	fmt.Print("Spawning workers…")
	for i := 0; i < concurrencycount; i++ {
		wg.Add(1)
		go fetch(loadTestStartTime, client, url, totalRequests, jobs, ch, &wg, awsregion, requestMethod, requestBody, requestHeaders)
		fmt.Print(".")
	}
	fmt.Println(" done.\nWaiting for results…")

	ticker := time.NewTicker(reportingFrequency)
	quit := make(chan struct{})
	quitting := false

	for requestsSoFar < totalRequests && !quitting {
		i := 0

		var timeToFirstTotal int64
		var requestTimeTotal int64
		totBytesRead := 0
		statuses := make(map[string]int)
		targets := make(map[string]int)
		var firstRequestTime int64
		var lastRequestTime int64
		var slowest int64
		var fastest int64
		var totalTimedOut int
		var totalConnectionError int

		resetStats := false
		for requestsSoFar < totalRequests && !quitting && !resetStats {
			aggregate := false
			select {
			case r := <-ch:
				i++
				requestsSoFar++
				if requestsSoFar%10 == 0 || requestsSoFar == totalRequests {
					fmt.Printf("\r%.2f%% done (%d requests out of %d)", (float64(requestsSoFar)/float64(totalRequests))*100.0, requestsSoFar, totalRequests)
				}
				if firstRequestTime == 0 {
					firstRequestTime = r.Time
				}

				lastRequestTime = r.Time

				if r.Timeout {
					totalTimedOut++
					continue
				}
				if r.ConnectionError {
					totalConnectionError++
					continue
				}

				if r.ElapsedLastByte > slowest {
					slowest = r.ElapsedLastByte
				}
				if fastest == 0 {
					fastest = r.ElapsedLastByte
				} else {
					if r.ElapsedLastByte < fastest {
						fastest = r.ElapsedLastByte
					}
				}

				timeToFirstTotal += r.ElapsedFirstByte
				totBytesRead += r.Bytes
				statusStr := strconv.Itoa(r.Status)
				_, ok1 := statuses[statusStr]
				if !ok1 {
					statuses[statusStr] = 1
				} else {
					statuses[statusStr]++
				}
				_, ok2 := targets[r.Host]
				if !ok2 {
					targets[r.Host] = 1
				} else {
					targets[r.Host]++
				}
				requestTimeTotal += r.Elapsed
				if requestsSoFar == totalRequests {
					quitting = true
				}
			case <-ticker.C:
				if i == 0 {
					continue
				}
				aggregate = true
			case <-quit:
				ticker.Stop()
				quitting = true
			}
			if aggregate || quitting {
				durationNanoSeconds := lastRequestTime - firstRequestTime
				durationSeconds := float32(durationNanoSeconds) / float32(1000000000)
				var reqPerSec float32
				var kbPerSec float32
				if durationSeconds > 0 {
					reqPerSec = float32(i) / durationSeconds
					kbPerSec = (float32(totBytesRead) / durationSeconds) / 1024.0
				} else {
					reqPerSec = 0
					kbPerSec = 0
				}

				fatalError := ""
				if (totalTimedOut + totalConnectionError) > i/2 {
					fatalError = "Over 50% of requests failed, aborting"
					quitting = true
				}
				aggData := queue.AggData{
					i,
					totalTimedOut,
					totalConnectionError,
					timeToFirstTotal / int64(i),
					totBytesRead,
					statuses,
					targets,
					requestTimeTotal / int64(i),
					reqPerSec,
					kbPerSec,
					slowest,
					fastest,
					awsregion,
					fatalError,
				}
				sqsAdaptor.SendResult(aggData)
				resetStats = true
			}
		}
	}
	fmt.Printf("\nYay🎈  - %d requests completed\n", requestsSoFar)

}

func fetch(loadTestStartTime time.Time, client *http.Client, address string, requestcount int, jobs <-chan struct{}, ch chan RequestResult, wg *sync.WaitGroup, awsregion string, requestMethod string, requestBody string, requestHeaders []string) {
	defer wg.Done()
	for _ = range jobs {
		start := time.Now()
		req, err := http.NewRequest(requestMethod, address, bytes.NewBufferString(requestBody))
		if err != nil {
			fmt.Println("Error creating the HTTP request:", err)
			return
		}
		req.Header.Add("Accept-Encoding", "gzip")
		for _, v := range requestHeaders {
			header := strings.Split(v, ":")
			if strings.ToLower(strings.Trim(header[0], " ")) == "host" {
				req.Host = strings.Trim(header[1], " ")
			} else {
				req.Header.Add(strings.Trim(header[0], " "), strings.Trim(header[1], " "))
			}
		}

		if req.Header.Get("User-Agent") == "" {
			req.Header.Add("User-Agent", "Mozilla/5.0 (compatible; Goad/1.0; +https://goad.io)")
		}

		response, err := client.Do(req)
		var status string
		var elapsedFirstByte time.Duration
		var elapsedLastByte time.Duration
		var elapsed time.Duration
		var statusCode int
		var bytesRead int
		buf := []byte(" ")
		timedOut := false
		connectionError := false
		isRedirect := err != nil && strings.Contains(err.Error(), "redirect")
		if err != nil && !isRedirect {
			status = fmt.Sprintf("ERROR: %s\n", err)
			switch err := err.(type) {
			case *url.Error:
				if err, ok := err.Err.(net.Error); ok && err.Timeout() {
					timedOut = true
				}
			case net.Error:
				if err.Timeout() {
					timedOut = true
				}
			}

			if !timedOut {
				connectionError = true
			}
		} else {
			statusCode = response.StatusCode
			elapsedFirstByte = time.Since(start)
			if !isRedirect {
				_, err = response.Body.Read(buf)
				firstByteRead := true
				if err != nil {
					status = fmt.Sprintf("reading first byte failed: %s\n", err)
					firstByteRead = false
				}
				body, err := ioutil.ReadAll(response.Body)
				if firstByteRead {
					bytesRead = len(body) + 1
				}
				elapsedLastByte = time.Since(start)
				if err != nil {
					// todo: detect timeout here as well
					status = fmt.Sprintf("reading response body failed: %s\n", err)
					connectionError = true
				} else {
					status = "Success"
				}
			} else {
				status = "Redirect"
			}
			response.Body.Close()

			elapsed = time.Since(start)
		}
		//fmt.Printf("Request end: %d, elapsed: %d\n", time.Now().Sub(loadTestStartTime).Nanoseconds(), elapsed.Nanoseconds())
		result := RequestResult{
			start.Sub(loadTestStartTime).Nanoseconds(),
			req.URL.Host,
			req.Method,
			statusCode,
			elapsedFirstByte.Nanoseconds(),
			elapsedLastByte.Nanoseconds(),
			elapsed.Nanoseconds(),
			bytesRead,
			timedOut,
			connectionError,
			status,
		}
		ch <- result
	}
}
<|endoftext|>


<commit_before>//
// +build unit

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

Copyright 2015 Intel Corporation

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 movingaverage

import (
	"bytes"
	"encoding/gob"
	"math/rand"
	"testing"
	"time"

	"github.com/intelsdi-x/pulse/control/plugin"
	"github.com/intelsdi-x/pulse/control/plugin/cpolicy"
	"github.com/intelsdi-x/pulse/core/ctypes"
	. "github.com/smartystreets/goconvey/convey"
)

//Random number generator
func randInt(min int, max int) int {
	return min + rand.Intn(max-min)
}

func TestMovingAverageProcessor(t *testing.T) {
	meta := Meta()
	Convey("Meta should return metadata for the plugin", t, func() {
		Convey("So meta.Name should equal movingaverage", func() {
			So(meta.Name, ShouldEqual, "movingaverage")
		})
		Convey("So meta.Version should equal 2", func() {
			So(meta.Version, ShouldEqual, 2)
		})
		Convey("So meta.Type should be of type plugin.ProcessorPluginType", func() {
			So(meta.Type, ShouldResemble, plugin.ProcessorPluginType)
		})
	})

	proc := NewMovingaverageProcessor()
	Convey("Create Movingaverage processor", t, func() {
		Convey("So proc should not be nil", func() {
			So(proc, ShouldNotBeNil)
		})
		Convey("So proc should be of type movingAverageProcessor", func() {
			So(proc, ShouldHaveSameTypeAs, &movingAverageProcessor{})
		})
		Convey("proc.GetConfigPolicy should return a config policy", func() {
			configPolicy, _ := proc.GetConfigPolicy()
			Convey("So config policy should be a cpolicy.ConfigPolicy", func() {
				So(configPolicy, ShouldHaveSameTypeAs, &cpolicy.ConfigPolicy{})
			})
			testConfig := make(map[string]ctypes.ConfigValue)
			testConfig["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: 10}
			cfg, errs := configPolicy.Get([]string{""}).Process(testConfig)
			Convey("So config policy should process testConfig and return a config", func() {
				So(cfg, ShouldNotBeNil)
			})
			Convey("So testConfig processing should return no errors", func() {
				So(errs.HasErrors(), ShouldBeFalse)
			})
		})
	})
}

func TestMovingAverageProcessorMetrics(t *testing.T) {
	Convey("Moving Average Processor tests", t, func() {
		metrics := make([]plugin.PluginMetricType, 10)
		config := make(map[string]ctypes.ConfigValue)

		config["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: -1}

		Convey("Moving average for int data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", data)
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), config)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for float32 data", func() {
			config["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: 40}
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", float32(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), config)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})
		Convey("Moving average for float64 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", float64(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for uint32 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", uint32(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for uint64 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", uint64(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for unknown data type", func() {
			for i, _ := range metrics {

				data := "I am an unknow data Type"
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", data)
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

	})
}
<commit_msg>Update test with new version<commit_after>//
// +build unit

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

Copyright 2015 Intel Corporation

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 movingaverage

import (
	"bytes"
	"encoding/gob"
	"math/rand"
	"testing"
	"time"

	"github.com/intelsdi-x/pulse/control/plugin"
	"github.com/intelsdi-x/pulse/control/plugin/cpolicy"
	"github.com/intelsdi-x/pulse/core/ctypes"
	. "github.com/smartystreets/goconvey/convey"
)

//Random number generator
func randInt(min int, max int) int {
	return min + rand.Intn(max-min)
}

func TestMovingAverageProcessor(t *testing.T) {
	meta := Meta()
	Convey("Meta should return metadata for the plugin", t, func() {
		Convey("So meta.Name should equal movingaverage", func() {
			So(meta.Name, ShouldEqual, "movingaverage")
		})
		Convey("So meta.Version should equal 3", func() {
			So(meta.Version, ShouldEqual, 3)
		})
		Convey("So meta.Type should be of type plugin.ProcessorPluginType", func() {
			So(meta.Type, ShouldResemble, plugin.ProcessorPluginType)
		})
	})

	proc := NewMovingaverageProcessor()
	Convey("Create Movingaverage processor", t, func() {
		Convey("So proc should not be nil", func() {
			So(proc, ShouldNotBeNil)
		})
		Convey("So proc should be of type movingAverageProcessor", func() {
			So(proc, ShouldHaveSameTypeAs, &movingAverageProcessor{})
		})
		Convey("proc.GetConfigPolicy should return a config policy", func() {
			configPolicy, _ := proc.GetConfigPolicy()
			Convey("So config policy should be a cpolicy.ConfigPolicy", func() {
				So(configPolicy, ShouldHaveSameTypeAs, &cpolicy.ConfigPolicy{})
			})
			testConfig := make(map[string]ctypes.ConfigValue)
			testConfig["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: 10}
			cfg, errs := configPolicy.Get([]string{""}).Process(testConfig)
			Convey("So config policy should process testConfig and return a config", func() {
				So(cfg, ShouldNotBeNil)
			})
			Convey("So testConfig processing should return no errors", func() {
				So(errs.HasErrors(), ShouldBeFalse)
			})
		})
	})
}

func TestMovingAverageProcessorMetrics(t *testing.T) {
	Convey("Moving Average Processor tests", t, func() {
		metrics := make([]plugin.PluginMetricType, 10)
		config := make(map[string]ctypes.ConfigValue)

		config["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: -1}

		Convey("Moving average for int data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", data)
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), config)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for float32 data", func() {
			config["MovingAvgBufLength"] = ctypes.ConfigValueInt{Value: 40}
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", float32(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), config)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})
		Convey("Moving average for float64 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", float64(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for uint32 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", uint32(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for uint64 data", func() {
			for i, _ := range metrics {
				time.Sleep(3)
				rand.Seed(time.Now().UTC().UnixNano())
				data := randInt(65, 90)
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", uint64(data))
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)
			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

		Convey("Moving average for unknown data type", func() {
			for i, _ := range metrics {

				data := "I am an unknow data Type"
				metrics[i] = *plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", data)
			}
			var buf bytes.Buffer
			enc := gob.NewEncoder(&buf)
			enc.Encode(metrics)

			movingAverageObj := NewMovingaverageProcessor()

			_, received_data, _ := movingAverageObj.Process("pulse.gob", buf.Bytes(), nil)

			var metrics_new []plugin.PluginMetricType

			//Decodes the content into pluginMetricType
			dec := gob.NewDecoder(bytes.NewBuffer(received_data))
			dec.Decode(&metrics_new)
			So(metrics, ShouldNotResemble, metrics_new)

		})

	})
}
<|endoftext|>


<commit_before>package bootkube

import (
	"bytes"
	"fmt"
	"time"

	"github.com/coreos-inc/pluton"
	"github.com/coreos-inc/pluton/spawn"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/util"
)

func bootkubeSmoke(c cluster.TestCluster) error {
	// This should not return until cluster is ready
	bc, err := spawn.MakeBootkubeCluster(c, 1, false)
	if err != nil {
		return err
	}

	// run an nginx deployment and ping it
	if err := nginxCheck(bc); err != nil {
		return fmt.Errorf("nginxCheck: %s", err)
	}
	// TODO add more basic or regression tests here
	return nil
}

func bootkubeSmokeEtcd(c cluster.TestCluster) error {
	// This should not return until cluster is ready
	bc, err := spawn.MakeBootkubeCluster(c, 1, true)
	if err != nil {
		return err
	}

	// run an nginx deployment and ping it
	if err := nginxCheck(bc); err != nil {
		return fmt.Errorf("nginxCheck: %s", err)
	}
	return nil
}

func nginxCheck(c *pluton.Cluster) error {
	// start nginx deployment
	_, err := c.Kubectl("run my-nginx --image=nginx --replicas=2 --port=80")
	if err != nil {
		return err
	}

	// expose nginx
	_, err = c.Kubectl("expose deployment my-nginx --port=80 --type=LoadBalancer")
	if err != nil {
		return err
	}
	serviceIP, err := c.Kubectl("get service my-nginx --template={{.spec.clusterIP}}")
	if err != nil {
		return err
	}

	// curl for welcome message
	nginxRunning := func() error {
		out, err := c.Masters[0].SSH("curl " + serviceIP + ":80")
		if err != nil || !bytes.Contains(out, []byte("Welcome to nginx!")) {
			return fmt.Errorf("unable to reach nginx: %s", out)
		}
		return nil
	}
	if err := util.Retry(15, 10*time.Second, nginxRunning); err != nil {
		return err
	}

	// delete pod
	_, err = c.Kubectl("delete deployment my-nginx")
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>tests/bootkube: bump nginx test timeout<commit_after>package bootkube

import (
	"bytes"
	"fmt"
	"time"

	"github.com/coreos-inc/pluton"
	"github.com/coreos-inc/pluton/spawn"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/util"
)

func bootkubeSmoke(c cluster.TestCluster) error {
	// This should not return until cluster is ready
	bc, err := spawn.MakeBootkubeCluster(c, 1, false)
	if err != nil {
		return err
	}

	// run an nginx deployment and ping it
	if err := nginxCheck(bc); err != nil {
		return fmt.Errorf("nginxCheck: %s", err)
	}
	// TODO add more basic or regression tests here
	return nil
}

func bootkubeSmokeEtcd(c cluster.TestCluster) error {
	// This should not return until cluster is ready
	bc, err := spawn.MakeBootkubeCluster(c, 1, true)
	if err != nil {
		return err
	}

	// run an nginx deployment and ping it
	if err := nginxCheck(bc); err != nil {
		return fmt.Errorf("nginxCheck: %s", err)
	}
	return nil
}

func nginxCheck(c *pluton.Cluster) error {
	// start nginx deployment
	_, err := c.Kubectl("run my-nginx --image=nginx --replicas=2 --port=80")
	if err != nil {
		return err
	}

	// expose nginx
	_, err = c.Kubectl("expose deployment my-nginx --port=80 --type=LoadBalancer")
	if err != nil {
		return err
	}
	serviceIP, err := c.Kubectl("get service my-nginx --template={{.spec.clusterIP}}")
	if err != nil {
		return err
	}

	// curl for welcome message
	nginxRunning := func() error {
		out, err := c.Masters[0].SSH("curl " + serviceIP + ":80")
		if err != nil || !bytes.Contains(out, []byte("Welcome to nginx!")) {
			return fmt.Errorf("unable to reach nginx: %s", out)
		}
		return nil
	}
	if err := util.Retry(20, 10*time.Second, nginxRunning); err != nil {
		return err
	}

	// delete pod
	_, err = c.Kubectl("delete deployment my-nginx")
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package travis

import "testing"

func TestIs(t *testing.T) {

}
<commit_msg>Update test<commit_after>package travis

import "testing"

func TestIs(t *testing.T) {
	if Is() == true {
		t.Fatal("Should return true")
	}
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"sync"
	"time"

	"k8s.io/client-go/1.5/kubernetes"
	"k8s.io/client-go/1.5/pkg/api"
	"k8s.io/client-go/1.5/pkg/api/v1"
	"k8s.io/client-go/1.5/pkg/labels"
	"k8s.io/client-go/1.5/pkg/runtime"
	"k8s.io/client-go/1.5/pkg/watch"
	"k8s.io/client-go/1.5/tools/cache"
)

var (
	namespace = api.NamespaceAll
)

// storeToNamespaceLister makes a Store that lists Namespaces.
type storeToNamespaceLister struct {
	cache.Store
}

// List lists all Namespaces in the store.
func (s *storeToNamespaceLister) List() (ns api.NamespaceList, err error) {
	for _, m := range s.Store.List() {
		ns.Items = append(ns.Items, *(m.(*api.Namespace)))
	}
	return ns, nil
}

type dnsController struct {
	client *kubernetes.Clientset

	selector *labels.Selector

	svcController *cache.Controller
	nsController  *cache.Controller

	svcLister cache.StoreToServiceLister
	nsLister  storeToNamespaceLister

	// stopLock is used to enforce only a single call to Stop is active.
	// Needed because we allow stopping through an http endpoint and
	// allowing concurrent stoppers leads to stack traces.
	stopLock sync.Mutex
	shutdown bool
	stopCh   chan struct{}
}

// newDNSController creates a controller for CoreDNS.
func newdnsController(kubeClient *kubernetes.Clientset, resyncPeriod time.Duration, lselector *labels.Selector) *dnsController {
	dns := dnsController{
		client:   kubeClient,
		selector: lselector,
		stopCh:   make(chan struct{}),
	}

	dns.svcLister.Indexer, dns.svcController = cache.NewIndexerInformer(
		&cache.ListWatch{
			ListFunc:  serviceListFunc(dns.client, namespace, dns.selector),
			WatchFunc: serviceWatchFunc(dns.client, namespace, dns.selector),
		},
		&api.Service{},
		resyncPeriod,
		cache.ResourceEventHandlerFuncs{},
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})

	dns.nsLister.Store, dns.nsController = cache.NewInformer(
		&cache.ListWatch{
			ListFunc:  namespaceListFunc(dns.client, dns.selector),
			WatchFunc: namespaceWatchFunc(dns.client, dns.selector),
		},
		&api.Namespace{}, resyncPeriod, cache.ResourceEventHandlerFuncs{})

	return &dns
}

func serviceListFunc(c *kubernetes.Clientset, ns string, s *labels.Selector) func(api.ListOptions) (runtime.Object, error) {
	return func(opts api.ListOptions) (runtime.Object, error) {
		if s != nil {
			opts.LabelSelector = *s
		}
		listV1, err := c.Core().Services(ns).List(opts)
		if err != nil {
			return nil, err
		}
		var listAPI api.ServiceList
		err = v1.Convert_v1_ServiceList_To_api_ServiceList(listV1, &listAPI, nil)
		if err != nil {
			return nil, err
		}
		return &list_api, err
	}
}

func serviceWatchFunc(c *kubernetes.Clientset, ns string, s *labels.Selector) func(options api.ListOptions) (watch.Interface, error) {
	return func(options api.ListOptions) (watch.Interface, error) {
		if s != nil {
			options.LabelSelector = *s
		}
		return c.Core().Services(ns).Watch(options)
	}
}

func namespaceListFunc(c *kubernetes.Clientset, s *labels.Selector) func(api.ListOptions) (runtime.Object, error) {
	return func(opts api.ListOptions) (runtime.Object, error) {
		if s != nil {
			opts.LabelSelector = *s
		}
		listV1, err := c.Core().Namespaces().List(opts)
		if err != nil {
			return nil, err
		}
		var listAPI api.NamespaceList
		err = v1.Convert_v1_NamespaceList_To_api_NamespaceList(listV1, &listAPI, nil)
		if err != nil {
			return nil, err
		}
		return &list_api, err
	}
}

func namespaceWatchFunc(c *kubernetes.Clientset, s *labels.Selector) func(options api.ListOptions) (watch.Interface, error) {
	return func(options api.ListOptions) (watch.Interface, error) {
		if s != nil {
			options.LabelSelector = *s
		}
		return c.Core().Namespaces().Watch(options)
	}
}

func (dns *dnsController) controllersInSync() bool {
	return dns.svcController.HasSynced()
}

// Stop stops the  controller.
func (dns *dnsController) Stop() error {
	dns.stopLock.Lock()
	defer dns.stopLock.Unlock()

	// Only try draining the workqueue if we haven't already.
	if !dns.shutdown {
		close(dns.stopCh)
		dns.shutdown = true

		return nil
	}

	return fmt.Errorf("shutdown already in progress")
}

// Run starts the controller.
func (dns *dnsController) Run() {
	go dns.svcController.Run(dns.stopCh)
	go dns.nsController.Run(dns.stopCh)
	<-dns.stopCh
}

func (dns *dnsController) NamespaceList() *api.NamespaceList {
	nsList, err := dns.nsLister.List()
	if err != nil {
		return &api.NamespaceList{}
	}

	return &nsList
}

func (dns *dnsController) ServiceList() []*api.Service {
	svcs, err := dns.svcLister.List(labels.Everything())
	if err != nil {
		return []*api.Service{}
	}

	return svcs
}

// ServicesByNamespace returns a map of:
//
// namespacename :: [ kubernetesService ]
func (dns *dnsController) ServicesByNamespace() map[string][]api.Service {
	k8sServiceList := dns.ServiceList()
	items := make(map[string][]api.Service, len(k8sServiceList))
	for _, i := range k8sServiceList {
		namespace := i.Namespace
		items[namespace] = append(items[namespace], *i)
	}

	return items
}

// ServiceInNamespace returns the Service that matches servicename in the namespace
func (dns *dnsController) ServiceInNamespace(namespace, servicename string) *api.Service {
	svcObj, err := dns.svcLister.Services(namespace).Get(servicename)
	if err != nil {
		// TODO(...): should return err here
		return nil
	}
	return svcObj
}
<commit_msg>Fix compilation error<commit_after>package kubernetes

import (
	"fmt"
	"sync"
	"time"

	"k8s.io/client-go/1.5/kubernetes"
	"k8s.io/client-go/1.5/pkg/api"
	"k8s.io/client-go/1.5/pkg/api/v1"
	"k8s.io/client-go/1.5/pkg/labels"
	"k8s.io/client-go/1.5/pkg/runtime"
	"k8s.io/client-go/1.5/pkg/watch"
	"k8s.io/client-go/1.5/tools/cache"
)

var (
	namespace = api.NamespaceAll
)

// storeToNamespaceLister makes a Store that lists Namespaces.
type storeToNamespaceLister struct {
	cache.Store
}

// List lists all Namespaces in the store.
func (s *storeToNamespaceLister) List() (ns api.NamespaceList, err error) {
	for _, m := range s.Store.List() {
		ns.Items = append(ns.Items, *(m.(*api.Namespace)))
	}
	return ns, nil
}

type dnsController struct {
	client *kubernetes.Clientset

	selector *labels.Selector

	svcController *cache.Controller
	nsController  *cache.Controller

	svcLister cache.StoreToServiceLister
	nsLister  storeToNamespaceLister

	// stopLock is used to enforce only a single call to Stop is active.
	// Needed because we allow stopping through an http endpoint and
	// allowing concurrent stoppers leads to stack traces.
	stopLock sync.Mutex
	shutdown bool
	stopCh   chan struct{}
}

// newDNSController creates a controller for CoreDNS.
func newdnsController(kubeClient *kubernetes.Clientset, resyncPeriod time.Duration, lselector *labels.Selector) *dnsController {
	dns := dnsController{
		client:   kubeClient,
		selector: lselector,
		stopCh:   make(chan struct{}),
	}

	dns.svcLister.Indexer, dns.svcController = cache.NewIndexerInformer(
		&cache.ListWatch{
			ListFunc:  serviceListFunc(dns.client, namespace, dns.selector),
			WatchFunc: serviceWatchFunc(dns.client, namespace, dns.selector),
		},
		&api.Service{},
		resyncPeriod,
		cache.ResourceEventHandlerFuncs{},
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})

	dns.nsLister.Store, dns.nsController = cache.NewInformer(
		&cache.ListWatch{
			ListFunc:  namespaceListFunc(dns.client, dns.selector),
			WatchFunc: namespaceWatchFunc(dns.client, dns.selector),
		},
		&api.Namespace{}, resyncPeriod, cache.ResourceEventHandlerFuncs{})

	return &dns
}

func serviceListFunc(c *kubernetes.Clientset, ns string, s *labels.Selector) func(api.ListOptions) (runtime.Object, error) {
	return func(opts api.ListOptions) (runtime.Object, error) {
		if s != nil {
			opts.LabelSelector = *s
		}
		listV1, err := c.Core().Services(ns).List(opts)
		if err != nil {
			return nil, err
		}
		var listAPI api.ServiceList
		err = v1.Convert_v1_ServiceList_To_api_ServiceList(listV1, &listAPI, nil)
		if err != nil {
			return nil, err
		}
		return &listAPI, err
	}
}

func serviceWatchFunc(c *kubernetes.Clientset, ns string, s *labels.Selector) func(options api.ListOptions) (watch.Interface, error) {
	return func(options api.ListOptions) (watch.Interface, error) {
		if s != nil {
			options.LabelSelector = *s
		}
		return c.Core().Services(ns).Watch(options)
	}
}

func namespaceListFunc(c *kubernetes.Clientset, s *labels.Selector) func(api.ListOptions) (runtime.Object, error) {
	return func(opts api.ListOptions) (runtime.Object, error) {
		if s != nil {
			opts.LabelSelector = *s
		}
		listV1, err := c.Core().Namespaces().List(opts)
		if err != nil {
			return nil, err
		}
		var listAPI api.NamespaceList
		err = v1.Convert_v1_NamespaceList_To_api_NamespaceList(listV1, &listAPI, nil)
		if err != nil {
			return nil, err
		}
		return &listAPI, err
	}
}

func namespaceWatchFunc(c *kubernetes.Clientset, s *labels.Selector) func(options api.ListOptions) (watch.Interface, error) {
	return func(options api.ListOptions) (watch.Interface, error) {
		if s != nil {
			options.LabelSelector = *s
		}
		return c.Core().Namespaces().Watch(options)
	}
}

func (dns *dnsController) controllersInSync() bool {
	return dns.svcController.HasSynced()
}

// Stop stops the  controller.
func (dns *dnsController) Stop() error {
	dns.stopLock.Lock()
	defer dns.stopLock.Unlock()

	// Only try draining the workqueue if we haven't already.
	if !dns.shutdown {
		close(dns.stopCh)
		dns.shutdown = true

		return nil
	}

	return fmt.Errorf("shutdown already in progress")
}

// Run starts the controller.
func (dns *dnsController) Run() {
	go dns.svcController.Run(dns.stopCh)
	go dns.nsController.Run(dns.stopCh)
	<-dns.stopCh
}

func (dns *dnsController) NamespaceList() *api.NamespaceList {
	nsList, err := dns.nsLister.List()
	if err != nil {
		return &api.NamespaceList{}
	}

	return &nsList
}

func (dns *dnsController) ServiceList() []*api.Service {
	svcs, err := dns.svcLister.List(labels.Everything())
	if err != nil {
		return []*api.Service{}
	}

	return svcs
}

// ServicesByNamespace returns a map of:
//
// namespacename :: [ kubernetesService ]
func (dns *dnsController) ServicesByNamespace() map[string][]api.Service {
	k8sServiceList := dns.ServiceList()
	items := make(map[string][]api.Service, len(k8sServiceList))
	for _, i := range k8sServiceList {
		namespace := i.Namespace
		items[namespace] = append(items[namespace], *i)
	}

	return items
}

// ServiceInNamespace returns the Service that matches servicename in the namespace
func (dns *dnsController) ServiceInNamespace(namespace, servicename string) *api.Service {
	svcObj, err := dns.svcLister.Services(namespace).Get(servicename)
	if err != nil {
		// TODO(...): should return err here
		return nil
	}
	return svcObj
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"os"
	"text/template"

	"github.com/urfave/cli"

	"github.com/drone/drone-cli/drone/internal"
)

var serverInfoCmd = cli.Command{
	Name:      "info",
	Usage:     "show server details",
	ArgsUsage: "<servername>",
	Action:    serverInfo,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:   "format",
			Usage:  "format output",
			Value:  tmplServerInfo,
			Hidden: true,
		},
	},
}

func serverInfo(c *cli.Context) error {
	client, err := internal.NewAutoscaleClient(c)
	if err != nil {
		return err
	}

	name := c.Args().First()
	if len(name) == 0 {
		return fmt.Errorf("Missing or invalid server name")
	}

	server, err := client.Server(name)
	if err != nil {
		return err
	}

	tmpl, err := template.New("_").Parse(c.String("format") + "\n")
	if err != nil {
		return err
	}
	return tmpl.Execute(os.Stdout, server)
}

// template for server information
var tmplServerInfo = `Name: {{ .Name }}
Address: {{ .Address }}
Region: {{ .Region }}
Size: {{.Size}}
State: {{ .State }}
`
<commit_msg>show error message in server info<commit_after>package server

import (
	"fmt"
	"os"
	"text/template"

	"github.com/urfave/cli"

	"github.com/drone/drone-cli/drone/internal"
)

var serverInfoCmd = cli.Command{
	Name:      "info",
	Usage:     "show server details",
	ArgsUsage: "<servername>",
	Action:    serverInfo,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:   "format",
			Usage:  "format output",
			Value:  tmplServerInfo,
			Hidden: true,
		},
	},
}

func serverInfo(c *cli.Context) error {
	client, err := internal.NewAutoscaleClient(c)
	if err != nil {
		return err
	}

	name := c.Args().First()
	if len(name) == 0 {
		return fmt.Errorf("Missing or invalid server name")
	}

	server, err := client.Server(name)
	if err != nil {
		return err
	}

	tmpl, err := template.New("_").Parse(c.String("format") + "\n")
	if err != nil {
		return err
	}
	return tmpl.Execute(os.Stdout, server)
}

// template for server information
var tmplServerInfo = `Name: {{ .Name }}
Address: {{ .Address }}
Region:  {{ .Region }}
Size:    {{.Size}}
State:   {{ .State }}
{{ if .Error -}}
Error:   {{ .Error }}
{{ end -}}
`
<|endoftext|>