<commit_before>// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

import (
	"bufio"
	"errors"
	"io"
	"net/rpc"
	"sync"
)

var errRpcJsonNeedsTermWhitespace = errors.New("rpc requires a JsonHandle with TermWhitespace set to true")

// Rpc provides a rpc Server or Client Codec for rpc communication.
type Rpc interface {
	ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
	ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
}

// RPCOptions holds options specific to rpc functionality
type RPCOptions struct {
	// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
	//
	// Set RPCNoBuffer=true to turn buffering off.
	// Buffering can still be done if buffered connections are passed in, or
	// buffering is configured on the handle.
	RPCNoBuffer bool
}

// rpcCodec defines the struct members and common methods.
type rpcCodec struct {
	c io.Closer
	r io.Reader
	w io.Writer
	f ioFlusher

	dec *Decoder
	enc *Encoder
	// bw  *bufio.Writer
	// br  *bufio.Reader
	mu sync.Mutex
	h  Handle

	cls atomicClsErr
}

func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
	// return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
	return newRPCCodec2(conn, conn, conn, h)
}

func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
	// defensive: ensure that jsonH has TermWhitespace turned on.
	if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
		panic(errRpcJsonNeedsTermWhitespace)
	}
	// always ensure that we use a flusher, and always flush what was written to the connection.
	// we lose nothing by using a buffered writer internally.
	f, ok := w.(ioFlusher)
	bh := h.getBasicHandle()
	if !bh.RPCNoBuffer {
		if bh.WriterBufferSize <= 0 {
			if !ok {
				bw := bufio.NewWriter(w)
				f, w = bw, bw
			}
		}
		if bh.ReaderBufferSize <= 0 {
			if _, ok = w.(ioPeeker); !ok {
				if _, ok = w.(ioBuffered); !ok {
					br := bufio.NewReader(r)
					r = br
				}
			}
		}
	}
	return rpcCodec{
		c:   c,
		w:   w,
		r:   r,
		f:   f,
		h:   h,
		enc: NewEncoder(w, h),
		dec: NewDecoder(r, h),
	}
}

func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
	if c.c != nil {
		cls := c.cls.load()
		if cls.closed {
			return cls.errClosed
		}
	}
	err = c.enc.Encode(obj1)
	if err == nil {
		if writeObj2 {
			err = c.enc.Encode(obj2)
		}
		// if err == nil && c.f != nil {
		// 	err = c.f.Flush()
		// }
	}
	if c.f != nil {
		if err == nil {
			err = c.f.Flush()
		} else {
			_ = c.f.Flush() // swallow flush error, so we maintain prior error on write
		}
	}
	return
}

func (c *rpcCodec) swallow(err *error) {
	defer panicToErr(c.dec, err)
	c.dec.swallow()
}

func (c *rpcCodec) read(obj interface{}) (err error) {
	if c.c != nil {
		cls := c.cls.load()
		if cls.closed {
			return cls.errClosed
		}
	}
	//If nil is passed in, we should read and discard
	if obj == nil {
		// var obj2 interface{}
		// return c.dec.Decode(&obj2)
		c.swallow(&err)
		return
	}
	return c.dec.Decode(obj)
}

func (c *rpcCodec) Close() error {
	if c.c == nil {
		return nil
	}
	cls := c.cls.load()
	if cls.closed {
		return cls.errClosed
	}
	cls.errClosed = c.c.Close()
	cls.closed = true
	c.cls.store(cls)
	return cls.errClosed
}

func (c *rpcCodec) ReadResponseBody(body interface{}) error {
	return c.read(body)
}

// -------------------------------------

type goRpcCodec struct {
	rpcCodec
}

func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
	// Must protect for concurrent access as per API
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.write(r, body, true)
}

func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.write(r, body, true)
}

func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
	return c.read(r)
}

func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error {
	return c.read(r)
}

func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
	return c.read(body)
}

// -------------------------------------

// goRpc is the implementation of Rpc that uses the communication protocol
// as defined in net/rpc package.
type goRpc struct{}

// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
//
// Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
//
// For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
// This ensures we use an adequate buffer during reading and writing.
// If not configured, we will internally initialize and use a buffer during reads and writes.
// This can be turned off via the RPCNoBuffer option on the Handle.
//   var handle codec.JsonHandle
//   handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
//
// Example 1: one way of configuring buffering explicitly:
//   var handle codec.JsonHandle // codec handle
//   handle.ReaderBufferSize = 1024
//   handle.WriterBufferSize = 1024
//   var conn io.ReadWriteCloser // connection got from a socket
//   var serverCodec = GoRpc.ServerCodec(conn, handle)
//   var clientCodec = GoRpc.ClientCodec(conn, handle)
//
// Example 2: you can also explicitly create a buffered connection yourself,
// and not worry about configuring the buffer sizes in the Handle.
//   var handle codec.Handle     // codec handle
//   var conn io.ReadWriteCloser // connection got from a socket
//   var bufconn = struct {      // bufconn here is a buffered io.ReadWriteCloser
//       io.Closer
//       *bufio.Reader
//       *bufio.Writer
//   }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
//   var serverCodec = GoRpc.ServerCodec(bufconn, handle)
//   var clientCodec = GoRpc.ClientCodec(bufconn, handle)
//
var GoRpc goRpc

func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
	return &goRpcCodec{newRPCCodec(conn, h)}
}

func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
	return &goRpcCodec{newRPCCodec(conn, h)}
}
<commit_msg>codec: rpc: remove unnecessary mutex Lock/Unlock during WriteXXX methods of codec<commit_after>// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

import (
	"bufio"
	"errors"
	"io"
	"net/rpc"
)

var errRpcJsonNeedsTermWhitespace = errors.New("rpc requires a JsonHandle with TermWhitespace set to true")

// Rpc provides a rpc Server or Client Codec for rpc communication.
type Rpc interface {
	ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
	ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
}

// RPCOptions holds options specific to rpc functionality
type RPCOptions struct {
	// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
	//
	// Set RPCNoBuffer=true to turn buffering off.
	// Buffering can still be done if buffered connections are passed in, or
	// buffering is configured on the handle.
	RPCNoBuffer bool
}

// rpcCodec defines the struct members and common methods.
type rpcCodec struct {
	c io.Closer
	r io.Reader
	w io.Writer
	f ioFlusher

	dec *Decoder
	enc *Encoder
	// bw  *bufio.Writer
	// br  *bufio.Reader
	h Handle

	cls atomicClsErr
}

func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
	// return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
	return newRPCCodec2(conn, conn, conn, h)
}

func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
	// defensive: ensure that jsonH has TermWhitespace turned on.
	if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
		panic(errRpcJsonNeedsTermWhitespace)
	}
	// always ensure that we use a flusher, and always flush what was written to the connection.
	// we lose nothing by using a buffered writer internally.
	f, ok := w.(ioFlusher)
	bh := h.getBasicHandle()
	if !bh.RPCNoBuffer {
		if bh.WriterBufferSize <= 0 {
			if !ok {
				bw := bufio.NewWriter(w)
				f, w = bw, bw
			}
		}
		if bh.ReaderBufferSize <= 0 {
			if _, ok = w.(ioPeeker); !ok {
				if _, ok = w.(ioBuffered); !ok {
					br := bufio.NewReader(r)
					r = br
				}
			}
		}
	}
	return rpcCodec{
		c:   c,
		w:   w,
		r:   r,
		f:   f,
		h:   h,
		enc: NewEncoder(w, h),
		dec: NewDecoder(r, h),
	}
}

func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
	if c.c != nil {
		cls := c.cls.load()
		if cls.closed {
			return cls.errClosed
		}
	}
	err = c.enc.Encode(obj1)
	if err == nil {
		if writeObj2 {
			err = c.enc.Encode(obj2)
		}
		// if err == nil && c.f != nil {
		// 	err = c.f.Flush()
		// }
	}
	if c.f != nil {
		if err == nil {
			err = c.f.Flush()
		} else {
			_ = c.f.Flush() // swallow flush error, so we maintain prior error on write
		}
	}
	return
}

func (c *rpcCodec) swallow(err *error) {
	defer panicToErr(c.dec, err)
	c.dec.swallow()
}

func (c *rpcCodec) read(obj interface{}) (err error) {
	if c.c != nil {
		cls := c.cls.load()
		if cls.closed {
			return cls.errClosed
		}
	}
	//If nil is passed in, we should read and discard
	if obj == nil {
		// var obj2 interface{}
		// return c.dec.Decode(&obj2)
		c.swallow(&err)
		return
	}
	return c.dec.Decode(obj)
}

func (c *rpcCodec) Close() error {
	if c.c == nil {
		return nil
	}
	cls := c.cls.load()
	if cls.closed {
		return cls.errClosed
	}
	cls.errClosed = c.c.Close()
	cls.closed = true
	c.cls.store(cls)
	return cls.errClosed
}

func (c *rpcCodec) ReadResponseBody(body interface{}) error {
	return c.read(body)
}

// -------------------------------------

type goRpcCodec struct {
	rpcCodec
}

func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
	return c.write(r, body, true)
}

func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
	return c.write(r, body, true)
}

func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
	return c.read(r)
}

func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error {
	return c.read(r)
}

func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
	return c.read(body)
}

// -------------------------------------

// goRpc is the implementation of Rpc that uses the communication protocol
// as defined in net/rpc package.
type goRpc struct{}

// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
//
// Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
//
// For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
// This ensures we use an adequate buffer during reading and writing.
// If not configured, we will internally initialize and use a buffer during reads and writes.
// This can be turned off via the RPCNoBuffer option on the Handle.
//   var handle codec.JsonHandle
//   handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
//
// Example 1: one way of configuring buffering explicitly:
//   var handle codec.JsonHandle // codec handle
//   handle.ReaderBufferSize = 1024
//   handle.WriterBufferSize = 1024
//   var conn io.ReadWriteCloser // connection got from a socket
//   var serverCodec = GoRpc.ServerCodec(conn, handle)
//   var clientCodec = GoRpc.ClientCodec(conn, handle)
//
// Example 2: you can also explicitly create a buffered connection yourself,
// and not worry about configuring the buffer sizes in the Handle.
//   var handle codec.Handle     // codec handle
//   var conn io.ReadWriteCloser // connection got from a socket
//   var bufconn = struct {      // bufconn here is a buffered io.ReadWriteCloser
//       io.Closer
//       *bufio.Reader
//       *bufio.Writer
//   }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
//   var serverCodec = GoRpc.ServerCodec(bufconn, handle)
//   var clientCodec = GoRpc.ClientCodec(bufconn, handle)
//
var GoRpc goRpc

func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
	return &goRpcCodec{newRPCCodec(conn, h)}
}

func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
	return &goRpcCodec{newRPCCodec(conn, h)}
}
<|endoftext|>


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

/*
 move (rename) files
 created by Beletti (rhiguita@gmail.com)
*/

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path"
)

func usage() {
	fmt.Printf("usage: mv [-f | -i | -n] [-v] source target\n")
	fmt.Printf("       mv [-f | -i | -n] [-v] source ... directory\n")
	os.Exit(1)
}

func main() {
	todir := false
	flag.Parse()

	if flag.NArg() < 2 {
		usage()
	}

	files := flag.Args()
	lf := files[len(files)-1]
	lfdir, err := os.Stat(lf)
	if err == nil {
		todir = lfdir.IsDir()
	}
	if flag.NArg() > 2 && todir == false {
		fmt.Printf("not a directory: %s\n", lf)
		os.Exit(1)
	}

	if len(files) == 2 && todir == false {
		// rename file
		err := os.Rename(files[0], files[1])
		if err != nil {
			log.Fatalf("%v", err)
		}
	} else {
		// "copying" N files to 1 directory
		for i := 0; i < flag.NArg()-1; i++ {
			ndir := path.Join(lf, files[i])
			err := os.Rename(files[i], ndir)
			if err != nil {
				log.Fatalf("%v", err)
			}
		}
	}
}
<commit_msg>fix mv.go: usage<commit_after>// Copyright 2012 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
 move (rename) files
 created by Beletti (rhiguita@gmail.com)
*/

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path"
)

func usage() {
	fmt.Printf("usage: mv source target\n")
	fmt.Printf("       mv source ... directory\n")
	os.Exit(1)
}

func main() {
	todir := false
	flag.Parse()

	if flag.NArg() < 2 {
		usage()
	}

	files := flag.Args()
	lf := files[len(files)-1]
	lfdir, err := os.Stat(lf)
	if err == nil {
		todir = lfdir.IsDir()
	}
	if flag.NArg() > 2 && todir == false {
		fmt.Printf("not a directory: %s\n", lf)
		os.Exit(1)
	}

	if len(files) == 2 && todir == false {
		// rename file
		err := os.Rename(files[0], files[1])
		if err != nil {
			log.Fatalf("%v", err)
		}
	} else {
		// "copying" N files to 1 directory
		for i := 0; i < flag.NArg()-1; i++ {
			ndir := path.Join(lf, files[i])
			err := os.Rename(files[i], ndir)
			if err != nil {
				log.Fatalf("%v", err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package types

import (
	"fmt"
	. "github.com/tendermint/tendermint/common"
)

//------------------------------------------------------------------------------------------------

var (
	GlobalPermissionsAddress    = Zero256[:20]
	GlobalPermissionsAddress256 = Zero256
	DougAddress                 = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte("THISISDOUG")...)
	DougAddress256              = LeftPadWord256(DougAddress)
)

// A particular permission
type PermFlag uint64

// Base permission references are like unix (the index is already bit shifted)
const (
	Root           PermFlag = 1 << iota // 1
	Send                                // 2
	Call                                // 4
	CreateContract                      // 8
	CreateAccount                       // 16
	Bond                                // 32

	DefaultBBPB = Send | Call | CreateContract | CreateAccount | Bond

	NumBasePermissions uint     = 6
	TopBasePermission  PermFlag = 1 << (NumBasePermissions - 1)
	AllSet             PermFlag = (1 << 63) - 1 + (1 << 63)
)

//---------------------------------------------------------------------------------------------

// Base chain permissions struct
type BasePermissions struct {
	// bit array with "has"/"doesn't have" for each permission
	Perms PermFlag

	// bit array with "set"/"not set" for each permission (not-set should fall back to global)
	SetBit PermFlag
}

func NewBasePermissions() *BasePermissions {
	return &BasePermissions{0, 0}
}

// Get a permission value. ty should be a power of 2.
// ErrValueNotSet is returned if the permission's set bit is off,
// and should be caught by caller so the global permission can be fetched
func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
	if ty == 0 {
		return false, ErrInvalidPermission(ty)
	}
	if p.SetBit&ty == 0 {
		return false, ErrValueNotSet(ty)
	}
	return p.Perms&ty > 0, nil
}

// Set a permission bit. Will set the permission's set bit to true.
func (p *BasePermissions) Set(ty PermFlag, value bool) error {
	p.SetBit |= ty
	if value {
		p.Perms |= ty
	} else {
		p.Perms &= ^ty
	}
	return nil
}

// Set the permission's set bit to false
func (p *BasePermissions) Unset(ty PermFlag) error {
	p.SetBit &= ^ty
	return nil
}

func (p *BasePermissions) Copy() *BasePermissions {
	if p == nil {
		return nil
	}
	return &BasePermissions{
		Perms:  p.Perms,
		SetBit: p.SetBit,
	}
}

func (p *BasePermissions) String() string {
	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
}

//---------------------------------------------------------------------------------------------

type AccountPermissions struct {
	Base  *BasePermissions
	Roles []string
}

func NewAccountPermissions() *AccountPermissions {
	return &AccountPermissions{
		Base:  NewBasePermissions(),
		Roles: []string{},
	}
}

// Returns true if the role is found
func (aP *AccountPermissions) HasRole(role string) bool {
	for _, r := range aP.Roles {
		if r == role {
			return true
		}
	}
	return false
}

// Returns true if the role is added, and false if it already exists
func (aP *AccountPermissions) AddRole(role string) bool {
	for _, r := range aP.Roles {
		if r == role {
			return false
		}
	}
	aP.Roles = append(aP.Roles, role)
	return true
}

// Returns true if the role is removed, and false if it is not found
func (aP *AccountPermissions) RmRole(role string) bool {
	for i, r := range aP.Roles {
		if r == role {
			post := []string{}
			if len(aP.Roles) > i+1 {
				post = aP.Roles[i+1:]
			}
			aP.Roles = append(aP.Roles[:i], post...)
			return true
		}
	}
	return false
}

func (aP *AccountPermissions) Copy() *AccountPermissions {
	if aP == nil {
		return nil
	}
	r := make([]string, len(aP.Roles))
	copy(r, aP.Roles)
	return &AccountPermissions{
		Base:  aP.Base.Copy(),
		Roles: r,
	}
}

func NewDefaultAccountPermissions() *AccountPermissions {
	return &AccountPermissions{
		Base: &BasePermissions{
			Perms:  DefaultBBPB,
			SetBit: AllSet,
		},
		Roles: []string{},
	}
}
<commit_msg>left pad role names :(<commit_after>package types

import (
	"fmt"
	. "github.com/tendermint/tendermint/common"
)

//------------------------------------------------------------------------------------------------

var (
	GlobalPermissionsAddress    = Zero256[:20]
	GlobalPermissionsAddress256 = Zero256
	DougAddress                 = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte("THISISDOUG")...)
	DougAddress256              = LeftPadWord256(DougAddress)
)

// A particular permission
type PermFlag uint64

// Base permission references are like unix (the index is already bit shifted)
const (
	Root           PermFlag = 1 << iota // 1
	Send                                // 2
	Call                                // 4
	CreateContract                      // 8
	CreateAccount                       // 16
	Bond                                // 32

	DefaultBBPB = Send | Call | CreateContract | CreateAccount | Bond

	NumBasePermissions uint     = 6
	TopBasePermission  PermFlag = 1 << (NumBasePermissions - 1)
	AllSet             PermFlag = (1 << 63) - 1 + (1 << 63)
)

//---------------------------------------------------------------------------------------------

// Base chain permissions struct
type BasePermissions struct {
	// bit array with "has"/"doesn't have" for each permission
	Perms PermFlag

	// bit array with "set"/"not set" for each permission (not-set should fall back to global)
	SetBit PermFlag
}

func NewBasePermissions() *BasePermissions {
	return &BasePermissions{0, 0}
}

// Get a permission value. ty should be a power of 2.
// ErrValueNotSet is returned if the permission's set bit is off,
// and should be caught by caller so the global permission can be fetched
func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
	if ty == 0 {
		return false, ErrInvalidPermission(ty)
	}
	if p.SetBit&ty == 0 {
		return false, ErrValueNotSet(ty)
	}
	return p.Perms&ty > 0, nil
}

// Set a permission bit. Will set the permission's set bit to true.
func (p *BasePermissions) Set(ty PermFlag, value bool) error {
	p.SetBit |= ty
	if value {
		p.Perms |= ty
	} else {
		p.Perms &= ^ty
	}
	return nil
}

// Set the permission's set bit to false
func (p *BasePermissions) Unset(ty PermFlag) error {
	p.SetBit &= ^ty
	return nil
}

func (p *BasePermissions) Copy() *BasePermissions {
	if p == nil {
		return nil
	}
	return &BasePermissions{
		Perms:  p.Perms,
		SetBit: p.SetBit,
	}
}

func (p *BasePermissions) String() string {
	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
}

//---------------------------------------------------------------------------------------------

type AccountPermissions struct {
	Base  *BasePermissions
	Roles []string
}

func NewAccountPermissions() *AccountPermissions {
	return &AccountPermissions{
		Base:  NewBasePermissions(),
		Roles: []string{},
	}
}

// Returns true if the role is found
func (aP *AccountPermissions) HasRole(role string) bool {
	role = string(LeftPadBytes([]byte(role), 32))
	for _, r := range aP.Roles {
		if r == role {
			return true
		}
	}
	return false
}

// Returns true if the role is added, and false if it already exists
func (aP *AccountPermissions) AddRole(role string) bool {
	role = string(LeftPadBytes([]byte(role), 32))
	for _, r := range aP.Roles {
		if r == role {
			return false
		}
	}
	aP.Roles = append(aP.Roles, role)
	return true
}

// Returns true if the role is removed, and false if it is not found
func (aP *AccountPermissions) RmRole(role string) bool {
	role = string(LeftPadBytes([]byte(role), 32))
	for i, r := range aP.Roles {
		if r == role {
			post := []string{}
			if len(aP.Roles) > i+1 {
				post = aP.Roles[i+1:]
			}
			aP.Roles = append(aP.Roles[:i], post...)
			return true
		}
	}
	return false
}

func (aP *AccountPermissions) Copy() *AccountPermissions {
	if aP == nil {
		return nil
	}
	r := make([]string, len(aP.Roles))
	copy(r, aP.Roles)
	return &AccountPermissions{
		Base:  aP.Base.Copy(),
		Roles: r,
	}
}

func NewDefaultAccountPermissions() *AccountPermissions {
	return &AccountPermissions{
		Base: &BasePermissions{
			Perms:  DefaultBBPB,
			SetBit: AllSet,
		},
		Roles: []string{},
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Knative Authors

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

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

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

package networking

import (
	"time"
)

const (
	// GroupName is the name for the networking API group.
	GroupName = "networking.internal.knative.dev"

	// IngressClassAnnotationKey is the annotation for the
	// explicit class of ClusterIngress that a particular resource has
	// opted into. For example,
	//
	//    networking.knative.dev/ingress.class: some-network-impl
	//
	// This uses a different domain because unlike the resource, it is
	// user-facing.
	//
	// The parent resource may use its own annotations to choose the
	// annotation value for the ClusterIngress it uses.  Based on such
	// value a different reconciliation logic may be used (for examples,
	// Istio-based ClusterIngress will reconcile into a VirtualService).
	IngressClassAnnotationKey = "networking.knative.dev/ingress.class"

	// IngressLabelKey is the label key attached to underlying network programming
	// resources to indicate which ClusterIngress triggered their creation.
	IngressLabelKey = GroupName + "/clusteringress"

	// SKSLabelKey is the label key that SKS Controller attaches to the
	// underlying resources it controls.
	SKSLabelKey = GroupName + "/serverlessservice"

	// ServiceTypeKey is the label key attached to a service specifying the type of service.
	// e.g. Public, Metrics
	ServiceTypeKey = GroupName + "/serviceType"
)

// ServiceType is the enumeration type for the Kubernetes services
// that we have in our system, classified by usage purpose.
type ServiceType string

const (
	// ServiceTypePrivate is the label value for internal only services
	// for user applications.
	ServiceTypePrivate ServiceType = "Private"
	// ServiceTypePublic is the label value for externally reachable
	// services for user applications.
	ServiceTypePublic ServiceType = "Public"
	// ServiceTypeMetrics is the label value for Metrics services. Such services
	// are used for meric scraping.
	ServiceTypeMetrics ServiceType = "Metrics"
)

// Pseudo-constants
var (
	// DefaultTimeout will be set if timeout not specified.
	DefaultTimeout = 10 * time.Minute

	// DefaultRetryCount will be set if Attempts not specified.
	DefaultRetryCount = 3
)
<commit_msg>Copy the certificate secret from the origin namespace to the namespace of Istio gateway (#3724)<commit_after>/*
Copyright 2018 The Knative Authors

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

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

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

package networking

import (
	"time"
)

const (
	// GroupName is the name for the networking API group.
	GroupName = "networking.internal.knative.dev"

	// IngressClassAnnotationKey is the annotation for the
	// explicit class of ClusterIngress that a particular resource has
	// opted into. For example,
	//
	//    networking.knative.dev/ingress.class: some-network-impl
	//
	// This uses a different domain because unlike the resource, it is
	// user-facing.
	//
	// The parent resource may use its own annotations to choose the
	// annotation value for the ClusterIngress it uses.  Based on such
	// value a different reconciliation logic may be used (for examples,
	// Istio-based ClusterIngress will reconcile into a VirtualService).
	IngressClassAnnotationKey = "networking.knative.dev/ingress.class"

	// IngressLabelKey is the label key attached to underlying network programming
	// resources to indicate which ClusterIngress triggered their creation.
	IngressLabelKey = GroupName + "/clusteringress"

	// SKSLabelKey is the label key that SKS Controller attaches to the
	// underlying resources it controls.
	SKSLabelKey = GroupName + "/serverlessservice"

	// ServiceTypeKey is the label key attached to a service specifying the type of service.
	// e.g. Public, Metrics
	ServiceTypeKey = GroupName + "/serviceType"

	// OriginSecretNameLabelKey is the label key attached to the TLS secret to indicate
	// the name of the origin secret that the TLS secret is copied from.
	OriginSecretNameLabelKey = GroupName + "/originSecretName"

	// OriginSecretNamespaceLabelKey is the label key attached to the TLS secret
	// to indicate the namespace of the origin secret that the TLS secret is copied from.
	OriginSecretNamespaceLabelKey = GroupName + "/originSecretNamespace"
)

// ServiceType is the enumeration type for the Kubernetes services
// that we have in our system, classified by usage purpose.
type ServiceType string

const (
	// ServiceTypePrivate is the label value for internal only services
	// for user applications.
	ServiceTypePrivate ServiceType = "Private"
	// ServiceTypePublic is the label value for externally reachable
	// services for user applications.
	ServiceTypePublic ServiceType = "Public"
	// ServiceTypeMetrics is the label value for Metrics services. Such services
	// are used for meric scraping.
	ServiceTypeMetrics ServiceType = "Metrics"
)

// Pseudo-constants
var (
	// DefaultTimeout will be set if timeout not specified.
	DefaultTimeout = 10 * time.Minute

	// DefaultRetryCount will be set if Attempts not specified.
	DefaultRetryCount = 3
)
<|endoftext|>


<commit_before>// Package internal holds asset templates used by bootkube.
package internal

var (
	KubeConfigTemplate = []byte(`apiVersion: v1
kind: Config
clusters:
- name: local
  cluster:
    server: {{ .Server }}
    certificate-authority-data: {{ .CACert }}
users:
- name: kubelet
  user:
    client-certificate-data: {{ .KubeletCert}}
    client-key-data: {{ .KubeletKey }}
contexts:
- context:
    cluster: local
    user: kubelet
`)
	KubeletTemplate = []byte(`apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: kubelet
  namespace: kube-system
  labels:
    k8s-app: kubelet
spec:
  template:
    metadata:
      labels:
        k8s-app: kubelet
    spec:
      containers:
      - name: kubelet
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /nsenter
        - --target=1
        - --mount
        - --wd=.
        - --
        - ./hyperkube
        - kubelet
        - --pod-manifest-path=/etc/kubernetes/manifests
        - --allow-privileged
        - --hostname-override=$(MY_POD_IP)
        - --cluster-dns=10.3.0.10
        - --cluster-domain=cluster.local
        - --kubeconfig=/etc/kubernetes/kubeconfig
        - --require-kubeconfig
        - --lock-file=/var/run/lock/kubelet.lock
        env:
          - name: MY_POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        securityContext:
          privileged: true
        volumeMounts:
        - name: dev
          mountPath: /dev
        - name: run
          mountPath: /run
        - name: sys
          mountPath: /sys
          readOnly: true
        - name: etc-kubernetes
          mountPath: /etc/kubernetes
          readOnly: true
        - name: etc-ssl-certs
          mountPath: /etc/ssl/certs
          readOnly: true
        - name: var-lib-docker
          mountPath: /var/lib/docker
        - name: var-lib-kubelet
          mountPath: /var/lib/kubelet
        - name: var-lib-rkt
          mountPath: /var/lib/rkt
      hostNetwork: true
      hostPID: true
      volumes:
      - name: dev
        hostPath:
          path: /dev
      - name: run
        hostPath:
          path: /run
      - name: sys
        hostPath:
          path: /sys
      - name: etc-kubernetes
        hostPath:
          path: /etc/kubernetes
      - name: etc-ssl-certs
        hostPath:
          path: /usr/share/ca-certificates
      - name: var-lib-docker
        hostPath:
          path: /var/lib/docker
      - name: var-lib-kubelet
        hostPath:
          path: /var/lib/kubelet
      - name: var-lib-rkt
        hostPath:
          path: /var/lib/rkt
`)
	APIServerTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: kube-apiserver
  namespace: kube-system
  labels:
    k8s-app: kube-apiserver
spec:
  template:
    metadata:
      labels:
        k8s-app: kube-apiserver
    spec:
      nodeSelector:
        master: "true"
      hostNetwork: true
      containers:
      - name: kube-apiserver
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /hyperkube
        - apiserver
        - --bind-address=0.0.0.0
        - --secure-port=443
        - --insecure-port=8080
        - --advertise-address=$(MY_POD_IP)
        - --etcd-servers={{ range $i, $e := .EtcdServers }}{{ if $i }},{{end}}{{ $e }}{{end}}
        - --allow-privileged=true
        - --service-cluster-ip-range=10.3.0.0/24
        - --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota
        - --runtime-config=api/all=true
        - --tls-cert-file=/etc/kubernetes/secrets/apiserver.crt
        - --tls-private-key-file=/etc/kubernetes/secrets/apiserver.key
        - --service-account-key-file=/etc/kubernetes/secrets/service-account.pub
        - --client-ca-file=/etc/kubernetes/secrets/ca.crt
        env:
          - name: MY_POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        volumeMounts:
        - mountPath: /etc/ssl/certs
          name: ssl-certs-host
          readOnly: true
        - mountPath: /etc/kubernetes/secrets
          name: secrets
          readOnly: true
      volumes:
      - name: ssl-certs-host
        hostPath:
          path: /usr/share/ca-certificates
      - name: secrets
        secret:
          secretName: kube-apiserver
`)
	CheckpointerTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: checkpoint-installer
  namespace: kube-system
  labels:
    k8s-app: kube-api-checkpointer
spec:
  template:
    metadata:
      labels:
        k8s-app: kube-api-checkpointer
    spec:
      nodeSelector:
        master: "true"
      hostNetwork: true
      containers:
      - name: checkpoint-installer
        image: quay.io/coreos/pod-checkpointer:f226b70d3a863a5dbcc5846ccd818296c30e703f
        command:
        - /checkpoint-installer.sh
        volumeMounts:
        - mountPath: /etc/kubernetes/manifests
          name: etc-k8s-manifests
      volumes:
      - name: etc-k8s-manifests
        hostPath:
          path: /etc/kubernetes/manifests
`)
	ControllerManagerTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-controller-manager
  namespace: kube-system
  labels:
    k8s-app: kube-controller-manager
spec:
  replicas: 2
  template:
    metadata:
      labels:
        k8s-app: kube-controller-manager
    spec:
      containers:
      - name: kube-controller-manager
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - ./hyperkube
        - controller-manager
        - --root-ca-file=/etc/kubernetes/secrets/ca.crt
        - --service-account-private-key-file=/etc/kubernetes/secrets/service-account.key
        - --leader-elect=true
        volumeMounts:
        - name: secrets
          mountPath: /etc/kubernetes/secrets
          readOnly: true
        - name: ssl-host
          mountPath: /etc/ssl/certs
          readOnly: true
      volumes:
      - name: secrets
        secret:
          secretName: kube-controller-manager
      - name: ssl-host
        hostPath:
          path: /usr/share/ca-certificates
`)
	SchedulerTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-scheduler
  namespace: kube-system
  labels:
    k8s-app: kube-scheduler
spec:
  replicas: 2
  template:
    metadata:
      labels:
        k8s-app: kube-scheduler
    spec:
      containers:
      - name: kube-scheduler
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - ./hyperkube
        - scheduler
        - --leader-elect=true
`)
	ProxyTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: kube-proxy
  namespace: kube-system
  labels:
    k8s_app: kube-proxy
spec:
  template:
    metadata:
      labels:
        k8s_app: kube-proxy
    spec:
      hostNetwork: true
      containers:
      - name: kube-proxy
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /hyperkube
        - proxy
        - --kubeconfig=/etc/kubernetes/kubeconfig
        - --proxy-mode=iptables
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /etc/ssl/certs
          name: ssl-certs-host
          readOnly: true
        - name: etc-kubernetes
          mountPath: /etc/kubernetes
          readOnly: true
      volumes:
      - hostPath:
          path: /usr/share/ca-certificates
        name: ssl-certs-host
      - name: etc-kubernetes
        hostPath:
          path: /etc/kubernetes
`)
	DNSDeploymentTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns-v20
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    version: v20
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: kube-dns
        version: v20
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: kubedns
        image: gcr.io/google_containers/kubedns-amd64:1.8
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthz-kubedns
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        # command = "/kube-dns"
        - --domain=cluster.local.
        - --dns-port=10053
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
      - name: dnsmasq
        image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
        livenessProbe:
          httpGet:
            path: /healthz-dnsmasq
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=127.0.0.1#10053
        - --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
      - name: healthz
        image: gcr.io/google_containers/exechealthz-amd64:1.2
        resources:
          limits:
            memory: 50Mi
          requests:
            cpu: 10m
            # Note that this container shouldn't really need 50Mi of memory. The
            # limits are set higher than expected pending investigation on #29688.
            # The extra memory was stolen from the kubedns container to keep the
            # net memory requested by the pod constant.
            memory: 50Mi
        args:
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - --url=/healthz-dnsmasq
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
        - --url=/healthz-kubedns
        - --port=8080
        - --quiet
        ports:
        - containerPort: 8080
          protocol: TCP
      dnsPolicy: Default  # Don't use cluster DNS.
`)
	DNSSvcTemplate = []byte(`apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP:  10.3.0.10
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
`)
)
<commit_msg>asset: Remove version info from dns addon<commit_after>// Package internal holds asset templates used by bootkube.
package internal

var (
	KubeConfigTemplate = []byte(`apiVersion: v1
kind: Config
clusters:
- name: local
  cluster:
    server: {{ .Server }}
    certificate-authority-data: {{ .CACert }}
users:
- name: kubelet
  user:
    client-certificate-data: {{ .KubeletCert}}
    client-key-data: {{ .KubeletKey }}
contexts:
- context:
    cluster: local
    user: kubelet
`)
	KubeletTemplate = []byte(`apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: kubelet
  namespace: kube-system
  labels:
    k8s-app: kubelet
spec:
  template:
    metadata:
      labels:
        k8s-app: kubelet
    spec:
      containers:
      - name: kubelet
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /nsenter
        - --target=1
        - --mount
        - --wd=.
        - --
        - ./hyperkube
        - kubelet
        - --pod-manifest-path=/etc/kubernetes/manifests
        - --allow-privileged
        - --hostname-override=$(MY_POD_IP)
        - --cluster-dns=10.3.0.10
        - --cluster-domain=cluster.local
        - --kubeconfig=/etc/kubernetes/kubeconfig
        - --require-kubeconfig
        - --lock-file=/var/run/lock/kubelet.lock
        env:
          - name: MY_POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        securityContext:
          privileged: true
        volumeMounts:
        - name: dev
          mountPath: /dev
        - name: run
          mountPath: /run
        - name: sys
          mountPath: /sys
          readOnly: true
        - name: etc-kubernetes
          mountPath: /etc/kubernetes
          readOnly: true
        - name: etc-ssl-certs
          mountPath: /etc/ssl/certs
          readOnly: true
        - name: var-lib-docker
          mountPath: /var/lib/docker
        - name: var-lib-kubelet
          mountPath: /var/lib/kubelet
        - name: var-lib-rkt
          mountPath: /var/lib/rkt
      hostNetwork: true
      hostPID: true
      volumes:
      - name: dev
        hostPath:
          path: /dev
      - name: run
        hostPath:
          path: /run
      - name: sys
        hostPath:
          path: /sys
      - name: etc-kubernetes
        hostPath:
          path: /etc/kubernetes
      - name: etc-ssl-certs
        hostPath:
          path: /usr/share/ca-certificates
      - name: var-lib-docker
        hostPath:
          path: /var/lib/docker
      - name: var-lib-kubelet
        hostPath:
          path: /var/lib/kubelet
      - name: var-lib-rkt
        hostPath:
          path: /var/lib/rkt
`)
	APIServerTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: kube-apiserver
  namespace: kube-system
  labels:
    k8s-app: kube-apiserver
spec:
  template:
    metadata:
      labels:
        k8s-app: kube-apiserver
    spec:
      nodeSelector:
        master: "true"
      hostNetwork: true
      containers:
      - name: kube-apiserver
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /hyperkube
        - apiserver
        - --bind-address=0.0.0.0
        - --secure-port=443
        - --insecure-port=8080
        - --advertise-address=$(MY_POD_IP)
        - --etcd-servers={{ range $i, $e := .EtcdServers }}{{ if $i }},{{end}}{{ $e }}{{end}}
        - --allow-privileged=true
        - --service-cluster-ip-range=10.3.0.0/24
        - --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota
        - --runtime-config=api/all=true
        - --tls-cert-file=/etc/kubernetes/secrets/apiserver.crt
        - --tls-private-key-file=/etc/kubernetes/secrets/apiserver.key
        - --service-account-key-file=/etc/kubernetes/secrets/service-account.pub
        - --client-ca-file=/etc/kubernetes/secrets/ca.crt
        env:
          - name: MY_POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        volumeMounts:
        - mountPath: /etc/ssl/certs
          name: ssl-certs-host
          readOnly: true
        - mountPath: /etc/kubernetes/secrets
          name: secrets
          readOnly: true
      volumes:
      - name: ssl-certs-host
        hostPath:
          path: /usr/share/ca-certificates
      - name: secrets
        secret:
          secretName: kube-apiserver
`)
	CheckpointerTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: checkpoint-installer
  namespace: kube-system
  labels:
    k8s-app: kube-api-checkpointer
spec:
  template:
    metadata:
      labels:
        k8s-app: kube-api-checkpointer
    spec:
      nodeSelector:
        master: "true"
      hostNetwork: true
      containers:
      - name: checkpoint-installer
        image: quay.io/coreos/pod-checkpointer:f226b70d3a863a5dbcc5846ccd818296c30e703f
        command:
        - /checkpoint-installer.sh
        volumeMounts:
        - mountPath: /etc/kubernetes/manifests
          name: etc-k8s-manifests
      volumes:
      - name: etc-k8s-manifests
        hostPath:
          path: /etc/kubernetes/manifests
`)
	ControllerManagerTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-controller-manager
  namespace: kube-system
  labels:
    k8s-app: kube-controller-manager
spec:
  replicas: 2
  template:
    metadata:
      labels:
        k8s-app: kube-controller-manager
    spec:
      containers:
      - name: kube-controller-manager
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - ./hyperkube
        - controller-manager
        - --root-ca-file=/etc/kubernetes/secrets/ca.crt
        - --service-account-private-key-file=/etc/kubernetes/secrets/service-account.key
        - --leader-elect=true
        volumeMounts:
        - name: secrets
          mountPath: /etc/kubernetes/secrets
          readOnly: true
        - name: ssl-host
          mountPath: /etc/ssl/certs
          readOnly: true
      volumes:
      - name: secrets
        secret:
          secretName: kube-controller-manager
      - name: ssl-host
        hostPath:
          path: /usr/share/ca-certificates
`)
	SchedulerTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-scheduler
  namespace: kube-system
  labels:
    k8s-app: kube-scheduler
spec:
  replicas: 2
  template:
    metadata:
      labels:
        k8s-app: kube-scheduler
    spec:
      containers:
      - name: kube-scheduler
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - ./hyperkube
        - scheduler
        - --leader-elect=true
`)
	ProxyTemplate = []byte(`apiVersion: "extensions/v1beta1"
kind: DaemonSet
metadata:
  name: kube-proxy
  namespace: kube-system
  labels:
    k8s_app: kube-proxy
spec:
  template:
    metadata:
      labels:
        k8s_app: kube-proxy
    spec:
      hostNetwork: true
      containers:
      - name: kube-proxy
        image: quay.io/coreos/hyperkube:v1.4.5_coreos.0
        command:
        - /hyperkube
        - proxy
        - --kubeconfig=/etc/kubernetes/kubeconfig
        - --proxy-mode=iptables
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /etc/ssl/certs
          name: ssl-certs-host
          readOnly: true
        - name: etc-kubernetes
          mountPath: /etc/kubernetes
          readOnly: true
      volumes:
      - hostPath:
          path: /usr/share/ca-certificates
        name: ssl-certs-host
      - name: etc-kubernetes
        hostPath:
          path: /etc/kubernetes
`)
	DNSDeploymentTemplate = []byte(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: kubedns
        image: gcr.io/google_containers/kubedns-amd64:1.8
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthz-kubedns
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        # command = "/kube-dns"
        - --domain=cluster.local.
        - --dns-port=10053
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
      - name: dnsmasq
        image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
        livenessProbe:
          httpGet:
            path: /healthz-dnsmasq
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=127.0.0.1#10053
        - --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
      - name: healthz
        image: gcr.io/google_containers/exechealthz-amd64:1.2
        resources:
          limits:
            memory: 50Mi
          requests:
            cpu: 10m
            # Note that this container shouldn't really need 50Mi of memory. The
            # limits are set higher than expected pending investigation on #29688.
            # The extra memory was stolen from the kubedns container to keep the
            # net memory requested by the pod constant.
            memory: 50Mi
        args:
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - --url=/healthz-dnsmasq
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
        - --url=/healthz-kubedns
        - --port=8080
        - --quiet
        ports:
        - containerPort: 8080
          protocol: TCP
      dnsPolicy: Default  # Don't use cluster DNS.
`)
	DNSSvcTemplate = []byte(`apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP:  10.3.0.10
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
`)
)
<|endoftext|>


<commit_before>// Package selfsign is a test helper that generates self signed certificate.
package selfsign

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/hex"
	"errors"
	"math/big"
	"time"
)

var errInvalidPrivateKey = errors.New("selfsign: invalid private key type")

// GenerateSelfSigned creates a self-signed certificate
func GenerateSelfSigned() (tls.Certificate, error) {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return tls.Certificate{}, err
	}

	return SelfSign(priv)
}

// GenerateSelfSignedWithDNS creates a self-signed certificate
func GenerateSelfSignedWithDNS(cn string, sans ...string) (tls.Certificate, error) {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return tls.Certificate{}, err
	}

	return WithDNS(priv, cn, sans...)
}

// SelfSign creates a self-signed certificate from a elliptic curve key
func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
	return WithDNS(key, hex.EncodeToString(make([]byte, 16)))
}

// WithDNS creates a self-signed certificate from a elliptic curve key
func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) {
	var (
		pubKey    crypto.PublicKey
		maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
	)

	switch k := key.(type) {
	case ed25519.PrivateKey:
		pubKey = k.Public()
	case *ecdsa.PrivateKey:
		pubKey = k.Public()
	case *rsa.PrivateKey:
		pubKey = k.Public()
	default:
		return tls.Certificate{}, errInvalidPrivateKey
	}

	/* #nosec */
	maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1))
	/* #nosec */
	serialNumber, err := rand.Int(rand.Reader, maxBigInt)
	if err != nil {
		return tls.Certificate{}, err
	}

	names := []string{cn}
	names = append(names, sans...)

	template := x509.Certificate{
		ExtKeyUsage: []x509.ExtKeyUsage{
			x509.ExtKeyUsageClientAuth,
			x509.ExtKeyUsageServerAuth,
		},
		BasicConstraintsValid: true,
		NotBefore:             time.Now(),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		NotAfter:              time.Now().AddDate(0, 1, 0),
		SerialNumber:          serialNumber,
		Version:               2,
		IsCA:                  true,
		DNSNames:              names,
	}

	raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
	if err != nil {
		return tls.Certificate{}, err
	}

	return tls.Certificate{
		Certificate: [][]byte{raw},
		PrivateKey:  key,
		Leaf:        &template,
	}, nil
}
<commit_msg>Fix KeyUsage on x509 template<commit_after>// Package selfsign is a test helper that generates self signed certificate.
package selfsign

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/hex"
	"errors"
	"math/big"
	"time"
)

var errInvalidPrivateKey = errors.New("selfsign: invalid private key type")

// GenerateSelfSigned creates a self-signed certificate
func GenerateSelfSigned() (tls.Certificate, error) {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return tls.Certificate{}, err
	}

	return SelfSign(priv)
}

// GenerateSelfSignedWithDNS creates a self-signed certificate
func GenerateSelfSignedWithDNS(cn string, sans ...string) (tls.Certificate, error) {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return tls.Certificate{}, err
	}

	return WithDNS(priv, cn, sans...)
}

// SelfSign creates a self-signed certificate from a elliptic curve key
func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
	return WithDNS(key, hex.EncodeToString(make([]byte, 16)))
}

// WithDNS creates a self-signed certificate from a elliptic curve key
func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) {
	var (
		pubKey    crypto.PublicKey
		maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
	)

	switch k := key.(type) {
	case ed25519.PrivateKey:
		pubKey = k.Public()
	case *ecdsa.PrivateKey:
		pubKey = k.Public()
	case *rsa.PrivateKey:
		pubKey = k.Public()
	default:
		return tls.Certificate{}, errInvalidPrivateKey
	}

	/* #nosec */
	maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1))
	/* #nosec */
	serialNumber, err := rand.Int(rand.Reader, maxBigInt)
	if err != nil {
		return tls.Certificate{}, err
	}

	names := []string{cn}
	names = append(names, sans...)

	keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign
	if _, isRSA := key.(*rsa.PrivateKey); isRSA {
		keyUsage |= x509.KeyUsageKeyEncipherment
	}

	template := x509.Certificate{
		ExtKeyUsage: []x509.ExtKeyUsage{
			x509.ExtKeyUsageClientAuth,
			x509.ExtKeyUsageServerAuth,
		},
		BasicConstraintsValid: true,
		NotBefore:             time.Now(),
		KeyUsage:              keyUsage,
		NotAfter:              time.Now().AddDate(0, 1, 0),
		SerialNumber:          serialNumber,
		Version:               2,
		IsCA:                  true,
		DNSNames:              names,
	}

	raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
	if err != nil {
		return tls.Certificate{}, err
	}

	return tls.Certificate{
		Certificate: [][]byte{raw},
		PrivateKey:  key,
		Leaf:        &template,
	}, nil
}
<|endoftext|>


<commit_before>// Copyright 2018-2019 Authors of Cilium
//
// 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.

// +build !privileged_tests

package store

import (
	"encoding/json"
	"fmt"
	"testing"
	"time"

	"github.com/cilium/cilium/pkg/defaults"
	"github.com/cilium/cilium/pkg/kvstore"
	"github.com/cilium/cilium/pkg/lock"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/testutils"

	. "gopkg.in/check.v1"
)

const (
	testPrefix = "store-tests"
)

func Test(t *testing.T) {
	TestingT(t)
}

type StoreSuite struct{}

type StoreEtcdSuite struct {
	StoreSuite
}

var _ = Suite(&StoreEtcdSuite{})

func (e *StoreEtcdSuite) SetUpTest(c *C) {
	kvstore.SetupDummy("etcd")
}

func (e *StoreEtcdSuite) TearDownTest(c *C) {
	kvstore.DeletePrefix(testPrefix)
	kvstore.Close()
}

type StoreConsulSuite struct {
	StoreSuite
}

var _ = Suite(&StoreConsulSuite{})

func (e *StoreConsulSuite) SetUpTest(c *C) {
	kvstore.SetupDummy("consul")
}

func (e *StoreConsulSuite) TearDownTest(c *C) {
	kvstore.DeletePrefix(testPrefix)
	kvstore.Close()
}

type TestType struct {
	Name string
}

var _ = TestType{}

func (t *TestType) GetKeyName() string          { return t.Name }
func (t *TestType) DeepKeyCopy() LocalKey       { return &TestType{Name: t.Name} }
func (t *TestType) Marshal() ([]byte, error)    { return json.Marshal(t) }
func (t *TestType) Unmarshal(data []byte) error { return json.Unmarshal(data, t) }

type opCounter struct {
	deleted int
	updated int
}

var (
	counter     = map[string]*opCounter{}
	counterLock lock.RWMutex
)

func (t *TestType) deleted() int {
	counterLock.RLock()
	defer counterLock.RUnlock()
	return counter[t.Name].deleted
}

func (t *TestType) updated() int {
	counterLock.RLock()
	defer counterLock.RUnlock()
	return counter[t.Name].updated
}

func initTestType(name string) TestType {
	t := TestType{}
	t.Name = name
	counterLock.Lock()
	counter[name] = &opCounter{}
	counterLock.Unlock()
	return t
}

type observer struct{}

func (o *observer) OnUpdate(k Key) {
	counterLock.Lock()
	if c, ok := counter[k.(*TestType).Name]; ok {
		c.updated++
	}
	counterLock.Unlock()
}
func (o *observer) OnDelete(k NamedKey) {
	counterLock.Lock()
	counter[k.(*TestType).Name].deleted++
	counterLock.Unlock()
}

func newTestType() Key {
	t := TestType{}
	return &t
}

func (s *StoreSuite) TestStoreCreation(c *C) {
	// Missing Prefix must result in error
	store, err := JoinSharedStore(Configuration{})
	c.Assert(err, ErrorMatches, "prefix must be specified")
	c.Assert(store, IsNil)

	// Missing KeyCreator must result in error
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune()})
	c.Assert(err, ErrorMatches, "KeyCreator must be specified")
	c.Assert(store, IsNil)

	// Basic creation should result in default values
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	c.Assert(store.conf.SynchronizationInterval, Equals, option.Config.KVstorePeriodicSync)
	store.Close()

	// Test with kvstore client specified
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType, Backend: kvstore.Client()})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	c.Assert(store.conf.SynchronizationInterval, Equals, option.Config.KVstorePeriodicSync)
	store.Close()
}

func expect(check func() bool) error {
	start := time.Now()
	for {
		if check() {
			return nil
		}

		if time.Since(start) > defaults.NodeDeleteDelay+10*time.Second {
			return fmt.Errorf("timeout while waiting for expected value")
		}

		time.Sleep(10 * time.Millisecond)
	}
}

func (s *StoreSuite) TestStoreOperations(c *C) {
	// Basic creation should result in default values
	store, err := JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType, Observer: &observer{}})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")
	localKey2 := initTestType("local2")
	localKey3 := initTestType("local3")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	// due to the short sync interval, it is possible that multiple updates
	// have occurred, make the test reliable by succeeding on at lest one
	// update
	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.updated() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey1)
	// localKey2 will be deleted 2 times, one from local key and other from
	// the kvstore watcher
	c.Assert(expect(func() bool { return localKey1.deleted() == 2 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.deleted() == 0 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey3)
	// localKey3 won't be deleted because it was never added
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey2)
	c.Assert(expect(func() bool { return localKey1.deleted() == 2 }), IsNil)
	// localKey2 will be deleted 2 times, one from local key and other from
	// the kvstore watcher
	c.Assert(expect(func() bool { return localKey2.deleted() == 2 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)
}

func (s *StoreSuite) TestStorePeriodicSync(c *C) {
	// Create a store with a very short periodic sync interval
	store, err := JoinSharedStore(Configuration{
		Prefix:                  testutils.RandomRune(),
		KeyCreator:              newTestType,
		SynchronizationInterval: 10 * time.Millisecond,
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")
	localKey2 := initTestType("local2")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)

	store.DeleteLocalKey(&localKey1)
	store.DeleteLocalKey(&localKey2)

	c.Assert(expect(func() bool { return localKey1.deleted() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.deleted() >= 1 }), IsNil)
}

func (s *StoreSuite) TestStoreLocalKeyProtection(c *C) {
	store, err := JoinSharedStore(Configuration{
		Prefix:                  testutils.RandomRune(),
		KeyCreator:              newTestType,
		SynchronizationInterval: time.Hour, // ensure that periodic sync does not interfer
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)

	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	// delete all keys
	kvstore.DeletePrefix(store.conf.Prefix)
	c.Assert(expect(func() bool {
		v, err := kvstore.Get(store.keyPath(&localKey1))
		return err == nil && string(v) != ""
	}), IsNil)
}

func setupStoreCollaboration(c *C, storePrefix, keyPrefix string) *SharedStore {
	store, err := JoinSharedStore(Configuration{
		Prefix:                  storePrefix,
		KeyCreator:              newTestType,
		SynchronizationInterval: time.Second,
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))

	localKey1 := initTestType(keyPrefix + "-local1")
	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)

	localKey2 := initTestType(keyPrefix + "-local2")
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	// wait until local keys was inserted and until the kvstore has confirmed the
	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)

	c.Assert(len(store.getLocalKeys()), Equals, 2)

	return store
}

func (s *StoreSuite) TestStoreCollaboration(c *C) {
	storePrefix := testutils.RandomRune()

	collab1 := setupStoreCollaboration(c, storePrefix, testutils.RandomRune())
	defer collab1.Close()

	collab2 := setupStoreCollaboration(c, storePrefix, testutils.RandomRune())
	defer collab2.Close()

	c.Assert(expect(func() bool {
		totalKeys := len(collab1.getLocalKeys()) + len(collab2.getLocalKeys())
		keys1, keys2 := collab1.getSharedKeys(), collab2.getSharedKeys()

		log.Debugf("totalKeys %d == keys1 %d == keys2 %d", totalKeys, len(keys1), len(keys2))
		return len(keys1) == totalKeys && len(keys1) == len(keys2)
	}), IsNil)
}
<commit_msg>pkg/kvstore: wait for node delete delay in unit tests<commit_after>// Copyright 2018-2019 Authors of Cilium
//
// 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.

// +build !privileged_tests

package store

import (
	"encoding/json"
	"fmt"
	"testing"
	"time"

	"github.com/cilium/cilium/pkg/defaults"
	"github.com/cilium/cilium/pkg/kvstore"
	"github.com/cilium/cilium/pkg/lock"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/testutils"

	. "gopkg.in/check.v1"
)

const (
	testPrefix = "store-tests"
)

func Test(t *testing.T) {
	TestingT(t)
}

type StoreSuite struct{}

type StoreEtcdSuite struct {
	StoreSuite
}

var _ = Suite(&StoreEtcdSuite{})

func (e *StoreEtcdSuite) SetUpTest(c *C) {
	kvstore.SetupDummy("etcd")
}

func (e *StoreEtcdSuite) TearDownTest(c *C) {
	kvstore.DeletePrefix(testPrefix)
	kvstore.Close()
}

type StoreConsulSuite struct {
	StoreSuite
}

var _ = Suite(&StoreConsulSuite{})

func (e *StoreConsulSuite) SetUpTest(c *C) {
	kvstore.SetupDummy("consul")
}

func (e *StoreConsulSuite) TearDownTest(c *C) {
	kvstore.DeletePrefix(testPrefix)
	kvstore.Close()
	time.Sleep(defaults.NodeDeleteDelay + 5*time.Second)
}

type TestType struct {
	Name string
}

var _ = TestType{}

func (t *TestType) GetKeyName() string          { return t.Name }
func (t *TestType) DeepKeyCopy() LocalKey       { return &TestType{Name: t.Name} }
func (t *TestType) Marshal() ([]byte, error)    { return json.Marshal(t) }
func (t *TestType) Unmarshal(data []byte) error { return json.Unmarshal(data, t) }

type opCounter struct {
	deleted int
	updated int
}

var (
	counter     = map[string]*opCounter{}
	counterLock lock.RWMutex
)

func (t *TestType) deleted() int {
	counterLock.RLock()
	defer counterLock.RUnlock()
	return counter[t.Name].deleted
}

func (t *TestType) updated() int {
	counterLock.RLock()
	defer counterLock.RUnlock()
	return counter[t.Name].updated
}

func initTestType(name string) TestType {
	t := TestType{}
	t.Name = name
	counterLock.Lock()
	counter[name] = &opCounter{}
	counterLock.Unlock()
	return t
}

type observer struct{}

func (o *observer) OnUpdate(k Key) {
	counterLock.Lock()
	if c, ok := counter[k.(*TestType).Name]; ok {
		c.updated++
	}
	counterLock.Unlock()
}
func (o *observer) OnDelete(k NamedKey) {
	counterLock.Lock()
	counter[k.(*TestType).Name].deleted++
	counterLock.Unlock()
}

func newTestType() Key {
	t := TestType{}
	return &t
}

func (s *StoreSuite) TestStoreCreation(c *C) {
	// Missing Prefix must result in error
	store, err := JoinSharedStore(Configuration{})
	c.Assert(err, ErrorMatches, "prefix must be specified")
	c.Assert(store, IsNil)

	// Missing KeyCreator must result in error
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune()})
	c.Assert(err, ErrorMatches, "KeyCreator must be specified")
	c.Assert(store, IsNil)

	// Basic creation should result in default values
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	c.Assert(store.conf.SynchronizationInterval, Equals, option.Config.KVstorePeriodicSync)
	store.Close()

	// Test with kvstore client specified
	store, err = JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType, Backend: kvstore.Client()})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	c.Assert(store.conf.SynchronizationInterval, Equals, option.Config.KVstorePeriodicSync)
	store.Close()
}

func expect(check func() bool) error {
	start := time.Now()
	for {
		if check() {
			return nil
		}

		if time.Since(start) > defaults.NodeDeleteDelay+10*time.Second {
			return fmt.Errorf("timeout while waiting for expected value")
		}

		time.Sleep(10 * time.Millisecond)
	}
}

func (s *StoreSuite) TestStoreOperations(c *C) {
	// Basic creation should result in default values
	store, err := JoinSharedStore(Configuration{Prefix: testutils.RandomRune(), KeyCreator: newTestType, Observer: &observer{}})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")
	localKey2 := initTestType("local2")
	localKey3 := initTestType("local3")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	// due to the short sync interval, it is possible that multiple updates
	// have occurred, make the test reliable by succeeding on at lest one
	// update
	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.updated() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey1)
	// localKey1 will be deleted 2 times, one from local key and other from
	// the kvstore watcher
	c.Assert(expect(func() bool { return localKey1.deleted() == 2 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.deleted() == 0 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey3)
	// localKey3 won't be deleted because it was never added
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)

	store.DeleteLocalKey(&localKey2)
	c.Assert(expect(func() bool { return localKey1.deleted() == 2 }), IsNil)
	// localKey2 will be deleted 2 times, one from local key and other from
	// the kvstore watcher
	c.Assert(expect(func() bool { return localKey2.deleted() == 2 }), IsNil)
	c.Assert(expect(func() bool { return localKey3.deleted() == 0 }), IsNil)
}

func (s *StoreSuite) TestStorePeriodicSync(c *C) {
	// Create a store with a very short periodic sync interval
	store, err := JoinSharedStore(Configuration{
		Prefix:                  testutils.RandomRune(),
		KeyCreator:              newTestType,
		SynchronizationInterval: 10 * time.Millisecond,
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")
	localKey2 := initTestType("local2")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)

	store.DeleteLocalKey(&localKey1)
	store.DeleteLocalKey(&localKey2)

	c.Assert(expect(func() bool { return localKey1.deleted() == 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.deleted() == 1 }), IsNil)
}

func (s *StoreSuite) TestStoreLocalKeyProtection(c *C) {
	store, err := JoinSharedStore(Configuration{
		Prefix:                  testutils.RandomRune(),
		KeyCreator:              newTestType,
		SynchronizationInterval: time.Hour, // ensure that periodic sync does not interfer
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))
	defer store.Close()

	localKey1 := initTestType("local1")

	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)

	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	// delete all keys
	kvstore.DeletePrefix(store.conf.Prefix)
	c.Assert(expect(func() bool {
		v, err := kvstore.Get(store.keyPath(&localKey1))
		return err == nil && string(v) != ""
	}), IsNil)
}

func setupStoreCollaboration(c *C, storePrefix, keyPrefix string) *SharedStore {
	store, err := JoinSharedStore(Configuration{
		Prefix:                  storePrefix,
		KeyCreator:              newTestType,
		SynchronizationInterval: time.Second,
		Observer:                &observer{},
	})
	c.Assert(err, IsNil)
	c.Assert(store, Not(IsNil))

	localKey1 := initTestType(keyPrefix + "-local1")
	err = store.UpdateLocalKeySync(&localKey1)
	c.Assert(err, IsNil)

	localKey2 := initTestType(keyPrefix + "-local2")
	err = store.UpdateLocalKeySync(&localKey2)
	c.Assert(err, IsNil)

	// wait until local keys was inserted and until the kvstore has confirmed the
	c.Assert(expect(func() bool { return localKey1.updated() >= 1 }), IsNil)
	c.Assert(expect(func() bool { return localKey2.updated() >= 1 }), IsNil)

	c.Assert(len(store.getLocalKeys()), Equals, 2)

	return store
}

func (s *StoreSuite) TestStoreCollaboration(c *C) {
	storePrefix := testutils.RandomRune()

	collab1 := setupStoreCollaboration(c, storePrefix, testutils.RandomRune())
	defer collab1.Close()

	collab2 := setupStoreCollaboration(c, storePrefix, testutils.RandomRune())
	defer collab2.Close()

	c.Assert(expect(func() bool {
		totalKeys := len(collab1.getLocalKeys()) + len(collab2.getLocalKeys())
		keys1, keys2 := collab1.getSharedKeys(), collab2.getSharedKeys()

		log.Debugf("totalKeys %d == keys1 %d == keys2 %d", totalKeys, len(keys1), len(keys2))
		return len(keys1) == totalKeys && len(keys1) == len(keys2)
	}), IsNil)
}
<|endoftext|>


<commit_before>package elasticsearch

import (
  "fmt"
  "github.com/packetbeat/elastigo/api"
 "github.com/packetbeat/elastigo/core"
 )

 //need to configure it from conf file.
//api.Port

func Index(data []byte){

  api.Domain = "localhost"
  fmt.Println("Entered inside elasticgo file...lets do this")
  response, _ := core.Index("scalegray_sample", "first_sampleset", "3", nil, data)
   fmt.Println(response)
  fmt.Println("Done pushing the data into elastic search..woohoo!")
}
<commit_msg>small change<commit_after>package elasticsearch

import (
  "fmt"
  "github.com/packetbeat/elastigo/api"
 "github.com/packetbeat/elastigo/core"
 )

 //need to configure it from conf file.
//api.Port

func Index(data []byte){

  api.Domain = "localhost"
  fmt.Println("Entered inside elasticgo file...lets do this")
  response, _ := core.Index("scalegraydata", "sg-type", "3", nil, data)
   fmt.Println(response)
  fmt.Println("Done pushing the data into elastic search..woohoo!")
}
<|endoftext|>


<commit_before>package memory

import (
	"errors"

	"github.com/snickers/snickers/types"
)

// Database struct that persists configurations
type Database struct {
	presets map[string]types.Preset
	jobs    map[string]types.Job
}

var instance *Database

// GetDatabase returns database singleton
func GetDatabase() (*Database, error) {
	if instance != nil {
		return instance, nil
	}
	instance = &Database{}
	instance.presets = map[string]types.Preset{}
	instance.jobs = map[string]types.Job{}
	return instance, nil
}

// ClearDatabase clears the database
func (r *Database) ClearDatabase() error {
	instance.presets = map[string]types.Preset{}
	instance.jobs = map[string]types.Job{}
	return nil
}

// StorePreset stores preset information
func (r *Database) StorePreset(preset types.Preset) (types.Preset, error) {
	r.presets[preset.Name] = preset
	return preset, nil
}

// RetrievePreset retrieves one preset from the database
func (r *Database) RetrievePreset(presetName string) (types.Preset, error) {
	if val, ok := r.presets[presetName]; ok {
		return val, nil
	}
	return types.Preset{}, errors.New("preset not found")
}

// UpdatePreset updates a preset
func (r *Database) UpdatePreset(presetName string, newPreset types.Preset) (types.Preset, error) {
	r.presets[presetName] = newPreset
	return newPreset, nil
}

// GetPresets retrieves all presets of the database
func (r *Database) GetPresets() ([]types.Preset, error) {
	res := make([]types.Preset, 0, len(r.presets))
	for _, value := range r.presets {
		res = append(res, value)
	}
	return res, nil
}

// DeletePreset deletes a preset from the database
func (r *Database) DeletePreset(presetName string) (types.Preset, error) {
	if val, ok := r.presets[presetName]; ok {
		delete(r.presets, presetName)
		return val, nil
	}
	return types.Preset{}, errors.New("preset not found")
}

// StoreJob stores job information
func (r *Database) StoreJob(job types.Job) (types.Job, error) {
	r.jobs[job.ID] = job
	return job, nil
}

// RetrieveJob retrieves one job from the database
func (r *Database) RetrieveJob(jobID string) (types.Job, error) {
	if val, ok := r.jobs[jobID]; ok {
		return val, nil
	}
	return types.Job{}, errors.New("job not found")
}

// UpdateJob updates a job
func (r *Database) UpdateJob(jobID string, newJob types.Job) (types.Job, error) {
	r.jobs[jobID] = newJob
	return newJob, nil
}

//GetJobs retrieves all jobs of the database
func (r *Database) GetJobs() ([]types.Job, error) {
	res := make([]types.Job, 0, len(r.jobs))
	for _, value := range r.jobs {
		res = append(res, value)
	}
	return res, nil
}
<commit_msg>Avoid race conditions in memory database<commit_after>package memory

import (
	"errors"
	"sync"

	"github.com/snickers/snickers/types"
)

// Database struct that persists configurations
type Database struct {
	mtx sync.RWMutex

	presets map[string]types.Preset
	jobs    map[string]types.Job
}

var instance *Database

// GetDatabase returns database singleton
func GetDatabase() (*Database, error) {
	if instance != nil {
		return instance, nil
	}
	instance = &Database{}
	instance.presets = map[string]types.Preset{}
	instance.jobs = map[string]types.Job{}
	return instance, nil
}

// ClearDatabase clears the database
func (r *Database) ClearDatabase() error {
	instance.presets = map[string]types.Preset{}
	instance.jobs = map[string]types.Job{}
	return nil
}

// StorePreset stores preset information
func (r *Database) StorePreset(preset types.Preset) (types.Preset, error) {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	r.presets[preset.Name] = preset
	return preset, nil
}

// RetrievePreset retrieves one preset from the database
func (r *Database) RetrievePreset(presetName string) (types.Preset, error) {
	r.mtx.RLock()
	defer r.mtx.RUnlock()

	if val, ok := r.presets[presetName]; ok {
		return val, nil
	}
	return types.Preset{}, errors.New("preset not found")
}

// UpdatePreset updates a preset
func (r *Database) UpdatePreset(presetName string, newPreset types.Preset) (types.Preset, error) {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	r.presets[presetName] = newPreset
	return newPreset, nil
}

// GetPresets retrieves all presets of the database
func (r *Database) GetPresets() ([]types.Preset, error) {
	r.mtx.RLock()
	defer r.mtx.RUnlock()

	res := make([]types.Preset, 0, len(r.presets))
	for _, value := range r.presets {
		res = append(res, value)
	}
	return res, nil
}

// DeletePreset deletes a preset from the database
func (r *Database) DeletePreset(presetName string) (types.Preset, error) {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	if val, ok := r.presets[presetName]; ok {
		delete(r.presets, presetName)
		return val, nil
	}
	return types.Preset{}, errors.New("preset not found")
}

// StoreJob stores job information
func (r *Database) StoreJob(job types.Job) (types.Job, error) {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	r.jobs[job.ID] = job
	return job, nil
}

// RetrieveJob retrieves one job from the database
func (r *Database) RetrieveJob(jobID string) (types.Job, error) {
	r.mtx.RLock()
	defer r.mtx.RUnlock()

	if val, ok := r.jobs[jobID]; ok {
		return val, nil
	}
	return types.Job{}, errors.New("job not found")
}

// UpdateJob updates a job
func (r *Database) UpdateJob(jobID string, newJob types.Job) (types.Job, error) {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	r.jobs[jobID] = newJob
	return newJob, nil
}

//GetJobs retrieves all jobs of the database
func (r *Database) GetJobs() ([]types.Job, error) {
	r.mtx.RLock()
	defer r.mtx.RUnlock()

	res := make([]types.Job, 0, len(r.jobs))
	for _, value := range r.jobs {
		res = append(res, value)
	}
	return res, nil
}
<|endoftext|>


<commit_before>package roll

import (
  "encoding/json"
  "errors"
  "fmt"
  "os"
  "sort"
  "time"

  "github.com/hashicorp/consul/api"
  "github.com/hashicorp/consul/watch"
  "gopkg.in/yaml.v2"
)

const (
  RollKey = "cascade/roll"
  RunOrderKey = "cascade/run_order"
  ConsulHost = "127.0.0.1:8500"
)

type CascadeEvent struct {
  Source string `json:"source"`
  Msg string `json:"msg"`
  Ref string `json:"ref"`
}

type Roll struct {
  Nodes []string
  Msg chan string

  client *api.Client
  session *api.Session
  kv *api.KV
  event *api.Event

  sessionID string

  pair *api.KVPair
  watch *watch.WatchPlan
  curID string
}

func NewRoll(role string) (*Roll, error) {
  client, _ := api.NewClient(api.DefaultConfig())
  session := client.Session()
  kv := client.KV()
  event := client.Event()

  user := os.Getenv("USER")

  if user == "root" && os.Getenv("SUDO_USER") != "" {
    user = os.Getenv("SUDO_USER")
  }

  se := &api.SessionEntry{
    Name: "cascade",
    TTL: "250s",
    Behavior: api.SessionBehaviorDelete,
  }

  sessionID, _, err := session.Create(se, nil)
  if err != nil {
    return nil, err
  }

  value := []byte(user)
  pair := &api.KVPair{Key: "cascade/roll", Value: value, Session: sessionID}
  if work, _, err := kv.Acquire(pair, nil); err != nil {
    return nil, err
  } else if !work {
    pair, _, err := kv.Get(RollKey, nil)
    if err != nil {
      return nil, err
    }

    if pair != nil {
      return nil, errors.New(fmt.Sprintf("err: failed to obtain lock: %s has the lock", string(pair.Value[:])))
    } else {
      return nil, errors.New("err: possibly a stale lock, try again shortly")
    }
  }

  nodes, err := GetNodes(role)
  if err != nil {
    return nil, err
  }

  // Setup channel
  msg := make(chan string, 3)

  return &Roll{nodes, msg, client, session, kv, event, sessionID, pair, nil, ""}, nil
}

func (r *Roll) Roll() error {
  for _, node := range r.Nodes {

    // roll the thing
    err := r.Dispatch(node)
    // hack for now (debug possible event dedup, watch exec race)
    time.Sleep(1 * time.Second)

    if err != nil {
      return err
    }

    renew, _, err := r.session.Renew(r.sessionID, nil)
    if err != nil {
      return err
    }

    if renew == nil {
      return errors.New("err: session renewal failed")
    }
  }

  return nil
}

func  (r *Roll) Dispatch(host string) error {
  // Setup event
  cascadeEvent := CascadeEvent{"cascade cli", "run", ""}
  payload, _ := json.Marshal(cascadeEvent)
  params := &api.UserEvent{Name: "cascade.cm", Payload: payload, NodeFilter: host}

  var errExit error

  // Setup watch
  watchParams := make(map[string]interface{})
  watchParams["type"] = "event"
  watchParams["name"] = "cascade.cm"

  watch, err := watch.Parse(watchParams)
  if err != nil {
    return err
  }

  r.watch = watch

  // Set handler
  r.watch.Handler = func(idx uint64, data interface{}) {
    events := data.([]*api.UserEvent)

    for _, event := range events {
      var e CascadeEvent
      err := json.Unmarshal(event.Payload, &e)

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

      if e.Ref == r.curID {
        r.Msg <- e.Msg

        if e.Msg == "success" || e.Msg == "fail" {
          r.watch.Stop()

          if e.Msg == "fail" {
            errExit = errors.New("err: failure roll stopped")
          }
        }
      }
    }
  }

  // Fire event
  id, _, err := r.event.Fire(params, nil)

  r.curID = id

  if err != nil {
    return err
  }

  // Send the host we are watching for
  r.Msg <- host

  // Execute Watch
  if err := r.watch.Run(ConsulHost); err != nil {
    return errors.New(fmt.Sprintf("err: querying Consul agent: %s", err))
  }

  return errExit
}

func (r *Roll) Destroy() error {
  r.watch.Stop()

  if work, _, err := r.kv.Release(r.pair, nil); err != nil {
    return err
  } else if !work {
    return errors.New("err: failed to release lock")
  }
  r.session.Destroy(r.sessionID, nil)

  return nil
}

func GetNodes(role string) ([]string, error) {
  client, _ := api.NewClient(api.DefaultConfig())
  catalog := client.Catalog()
  kv := client.KV()

  // We have to use arrays to preserve order :(
  seen := make(map[string]bool)
  result := make([]string, 0)

  nodes, _, err := catalog.Service("cascade", role, nil)

  if err != nil {
    return nil, err
  }

  pair, _, err := kv.Get(RunOrderKey, nil)

  if err != nil {
    return nil, err
  }

  if pair == nil {
    for _,node := range nodes {
      result = append(result, node.Node)
    }

    sort.Strings(result)
  } else {
    roles := make([]string, 0)

    err = yaml.Unmarshal([]byte(pair.Value), &roles)
    if err != nil {
      return nil, err
    }

    // TODO this is gross
    for _, role := range roles {
      tmp := make([]string, 0)

      for _,node := range nodes {
        for _,nodeRole := range node.ServiceTags {
          if role == nodeRole && !seen[node.Node] {
            seen[node.Node] = true
            tmp = append(tmp, node.Node)
          }
        }
      }

      sort.Strings(tmp)
      result = append(result, tmp...)
    }
  }

  return result, nil
}
<commit_msg>fix panic for non existent role<commit_after>package roll

import (
  "encoding/json"
  "errors"
  "fmt"
  "os"
  "sort"
  "time"

  "github.com/hashicorp/consul/api"
  "github.com/hashicorp/consul/watch"
  "gopkg.in/yaml.v2"
)

const (
  RollKey = "cascade/roll"
  RunOrderKey = "cascade/run_order"
  ConsulHost = "127.0.0.1:8500"
)

type CascadeEvent struct {
  Source string `json:"source"`
  Msg string `json:"msg"`
  Ref string `json:"ref"`
}

type Roll struct {
  Nodes []string
  Msg chan string

  client *api.Client
  session *api.Session
  kv *api.KV
  event *api.Event

  sessionID string

  pair *api.KVPair
  watch *watch.WatchPlan
  curID string
}

func NewRoll(role string) (*Roll, error) {
  client, _ := api.NewClient(api.DefaultConfig())
  session := client.Session()
  kv := client.KV()
  event := client.Event()

  user := os.Getenv("USER")

  if user == "root" && os.Getenv("SUDO_USER") != "" {
    user = os.Getenv("SUDO_USER")
  }

  se := &api.SessionEntry{
    Name: "cascade",
    TTL: "250s",
    Behavior: api.SessionBehaviorDelete,
  }

  sessionID, _, err := session.Create(se, nil)
  if err != nil {
    return nil, err
  }

  value := []byte(user)
  pair := &api.KVPair{Key: "cascade/roll", Value: value, Session: sessionID}
  if work, _, err := kv.Acquire(pair, nil); err != nil {
    return nil, err
  } else if !work {
    pair, _, err := kv.Get(RollKey, nil)
    if err != nil {
      return nil, err
    }

    if pair != nil {
      return nil, errors.New(fmt.Sprintf("err: failed to obtain lock: %s has the lock", string(pair.Value[:])))
    } else {
      return nil, errors.New("err: possibly a stale lock, try again shortly")
    }
  }

  nodes, err := GetNodes(role)
  if err != nil {
    return nil, err
  }

  // Setup channel
  msg := make(chan string, 3)

  return &Roll{nodes, msg, client, session, kv, event, sessionID, pair, nil, ""}, nil
}

func (r *Roll) Roll() error {
  for _, node := range r.Nodes {

    // roll the thing
    err := r.Dispatch(node)
    // hack for now (debug possible event dedup, watch exec race)
    time.Sleep(1 * time.Second)

    if err != nil {
      return err
    }

    renew, _, err := r.session.Renew(r.sessionID, nil)
    if err != nil {
      return err
    }

    if renew == nil {
      return errors.New("err: session renewal failed")
    }
  }

  return nil
}

func  (r *Roll) Dispatch(host string) error {
  // Setup event
  cascadeEvent := CascadeEvent{"cascade cli", "run", ""}
  payload, _ := json.Marshal(cascadeEvent)
  params := &api.UserEvent{Name: "cascade.cm", Payload: payload, NodeFilter: host}

  var errExit error

  // Setup watch
  watchParams := make(map[string]interface{})
  watchParams["type"] = "event"
  watchParams["name"] = "cascade.cm"

  watch, err := watch.Parse(watchParams)
  if err != nil {
    return err
  }

  r.watch = watch

  // Set handler
  r.watch.Handler = func(idx uint64, data interface{}) {
    events := data.([]*api.UserEvent)

    for _, event := range events {
      var e CascadeEvent
      err := json.Unmarshal(event.Payload, &e)

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

      if e.Ref == r.curID {
        r.Msg <- e.Msg

        if e.Msg == "success" || e.Msg == "fail" {
          r.watch.Stop()

          if e.Msg == "fail" {
            errExit = errors.New("err: failure roll stopped")
          }
        }
      }
    }
  }

  // Fire event
  id, _, err := r.event.Fire(params, nil)

  r.curID = id

  if err != nil {
    return err
  }

  // Send the host we are watching for
  r.Msg <- host

  // Execute Watch
  if err := r.watch.Run(ConsulHost); err != nil {
    return errors.New(fmt.Sprintf("err: querying Consul agent: %s", err))
  }

  return errExit
}

func (r *Roll) Destroy() error {
  r.watch.Stop()

  if work, _, err := r.kv.Release(r.pair, nil); err != nil {
    return err
  } else if !work {
    return errors.New("err: failed to release lock")
  }
  r.session.Destroy(r.sessionID, nil)

  return nil
}

func GetNodes(role string) ([]string, error) {
  client, _ := api.NewClient(api.DefaultConfig())
  catalog := client.Catalog()
  kv := client.KV()
  var err error

  // We have to use arrays to preserve order :(
  seen := make(map[string]bool)
  result := make([]string, 0)

  nodes, _, err := catalog.Service("cascade", role, nil)

  if err != nil {
    return nil, err
  }

  pair, _, err := kv.Get(RunOrderKey, nil)

  if err != nil {
    return nil, err
  }

  if pair == nil {
    for _,node := range nodes {
      result = append(result, node.Node)
    }

    sort.Strings(result)
  } else {
    roles := make([]string, 0)

    err = yaml.Unmarshal([]byte(pair.Value), &roles)
    if err != nil {
      return nil, err
    }

    // TODO this is gross
    for _, role := range roles {
      tmp := make([]string, 0)

      for _,node := range nodes {
        for _,nodeRole := range node.ServiceTags {
          if role == nodeRole && !seen[node.Node] {
            seen[node.Node] = true
            tmp = append(tmp, node.Node)
          }
        }
      }

      sort.Strings(tmp)
      result = append(result, tmp...)
    }
  }

  if len(result) == 0 {
    err = errors.New(fmt.Sprintf("err: no nodes matching role: %s found", role))

  }

  return result, err
}
<|endoftext|>


<commit_before>package r2router

import (
	"fmt"
	"strings"
)

type routeNode struct {
	paramNode bool
	paramName string
	path      string
	children  []*routeNode
	handler   Handler
}

func newRouteNode() *routeNode {
	r := &routeNode{}
	r.children = make([]*routeNode, 0)
	return r
}

// findChild finds a child node that matches the given node
// It returns nil if no node found. This is to see if
// we already have a similar node registered
func (n *routeNode) findChild(nn *routeNode) *routeNode {
	for _, c := range n.children {
		if c.paramNode && nn.paramNode {
			// both are paramNode
			return c
		} else if c.path == nn.path {
			// same node
			return c
		}
	}
	return nil
}

func (n *routeNode) swapChild(i, j int) {
	n.children[i], n.children[j] = n.children[j], n.children[i]
}

// insertChild registers given node in the route node tree
// If there is already a similar node it will not insert new node
// The returned node is always the registered one ie either
// newly registered or the old one
func (n *routeNode) insertChild(nn *routeNode) *routeNode {
	if child := n.findChild(nn); child != nil {
		if child.paramNode && nn.paramNode {
			// only allow one param child, unique param name
			if child.paramName != nn.paramName {
				panic("Param name must be same for")
			}
		}

		return child
	}

	n.children = append(n.children, nn)
	if len(n.children) > 1 {
		if n.children[len(n.children)-2].paramNode {
			n.swapChild(len(n.children)-2, len(n.children)-1)
		}
	}
	return nn
}

type rootNode struct {
	root    *routeNode
	handler Handler
}

func newRouteTree() *rootNode {
	r := &rootNode{}
	r.root = newRouteNode()
	return r
}

func (n *rootNode) addRoute(path string, handler Handler) {
	path = strings.Trim(path, "/")
	if path != "" {
		paths := strings.Split(path, "/")
		// Start with the roots
		parent := n.root
		for _, p := range paths {
			//fmt.Println(p)
			child := newRouteNode()

			if strings.Contains(p, ":") {
				// param type
				child.paramName = strings.TrimSpace(p[1:])
				if child.paramName == "" {
					panic("Param name can not be empty")
				}
				child.paramNode = true
			} else {
				child.path = p
			}
			// will be parent for the next path token
			parent = parent.insertChild(child)
		}
		// adding handler
		if parent.handler != nil {
			panic(fmt.Sprintf("'%s' has already a handler", path))
		}
		parent.handler = handler

	} else {
		if n.handler != nil {
			panic("There is already a handler for /")
		}
		n.handler = handler
	}
}

func (n *rootNode) match(path string) (Handler, Params) {
	path = strings.Trim(path, "/")
	if path != "" {
		// can be better by getting one at the time
		paths := strings.Split(path, "/")
		var matched bool
		route := n.root
		params := &params_{}
		params.appData = make(map[string]interface{})
		params.requestParams = make(map[string]string)
		for _, p := range paths {
			matched = false
			//fmt.Println("p:", p)
			for _, c := range route.children {
				if c.path == p {
					//fmt.Println("match:", c.path)
					route = c
					matched = true
					break
				}
				if c.paramNode {
					route = c
					matched = true
					params.requestParams[c.paramName] = p
					break
				}
			}
			if !matched {
				break
			}
		}
		if matched {
			return route.handler, params
		}

	} else {
		if n.handler != nil {
			return n.handler, nil
		}
	}

	return nil, nil
}
<commit_msg>Return if false<commit_after>package r2router

import (
	"fmt"
	"strings"
)

type routeNode struct {
	paramNode bool
	paramName string
	path      string
	children  []*routeNode
	handler   Handler
}

func newRouteNode() *routeNode {
	r := &routeNode{}
	r.children = make([]*routeNode, 0)
	return r
}

// findChild finds a child node that matches the given node
// It returns nil if no node found. This is to see if
// we already have a similar node registered
func (n *routeNode) findChild(nn *routeNode) *routeNode {
	for _, c := range n.children {
		if c.paramNode && nn.paramNode {
			// both are paramNode
			return c
		} else if c.path == nn.path {
			// same node
			return c
		}
	}
	return nil
}

func (n *routeNode) swapChild(i, j int) {
	n.children[i], n.children[j] = n.children[j], n.children[i]
}

// insertChild registers given node in the route node tree
// If there is already a similar node it will not insert new node
// The returned node is always the registered one ie either
// newly registered or the old one
func (n *routeNode) insertChild(nn *routeNode) *routeNode {
	if child := n.findChild(nn); child != nil {
		if child.paramNode && nn.paramNode {
			// only allow one param child, unique param name
			if child.paramName != nn.paramName {
				panic("Param name must be same for")
			}
		}

		return child
	}

	n.children = append(n.children, nn)
	if len(n.children) > 1 {
		if n.children[len(n.children)-2].paramNode {
			n.swapChild(len(n.children)-2, len(n.children)-1)
		}
	}
	return nn
}

type rootNode struct {
	root    *routeNode
	handler Handler
}

func newRouteTree() *rootNode {
	r := &rootNode{}
	r.root = newRouteNode()
	return r
}

func (n *rootNode) addRoute(path string, handler Handler) {
	path = strings.Trim(path, "/")
	if path != "" {
		paths := strings.Split(path, "/")
		// Start with the roots
		parent := n.root
		for _, p := range paths {
			//fmt.Println(p)
			child := newRouteNode()

			if strings.Contains(p, ":") {
				// param type
				child.paramName = strings.TrimSpace(p[1:])
				if child.paramName == "" {
					panic("Param name can not be empty")
				}
				child.paramNode = true
			} else {
				child.path = p
			}
			// will be parent for the next path token
			parent = parent.insertChild(child)
		}
		// adding handler
		if parent.handler != nil {
			panic(fmt.Sprintf("'%s' has already a handler", path))
		}
		parent.handler = handler

	} else {
		if n.handler != nil {
			panic("There is already a handler for /")
		}
		n.handler = handler
	}
}

func (n *rootNode) match(path string) (Handler, Params) {
	path = strings.Trim(path, "/")
	if path != "" {
		// can be better by getting one at the time
		paths := strings.Split(path, "/")
		var matched bool
		route := n.root
		params := &params_{}
		params.appData = make(map[string]interface{})
		params.requestParams = make(map[string]string)
		for _, p := range paths {
			matched = false
			//fmt.Println("p:", p)
			for _, c := range route.children {
				if c.path == p {
					//fmt.Println("match:", c.path)
					route = c
					matched = true
					break
				}
				if c.paramNode {
					route = c
					matched = true
					params.requestParams[c.paramName] = p
					break
				}
			}
			if !matched {
				return nil, nil
			}
		}
		return route.handler, params
	} else {
		if n.handler != nil {
			return n.handler, nil
		}
	}

	return nil, nil
}
<|endoftext|>