<commit_before>package broker

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/jinzhu/gorm"
	"github.com/streadway/amqp"
	"labix.org/v2/mgo"
)

type Handler interface {
	HandleEvent(string, []byte) error
	ErrHandler
}

type ErrHandler interface {
	// bool is whether publishing the message to maintenance qeueue or not
	DefaultErrHandler(amqp.Delivery, error) bool
}

func (c *Consumer) withMetrics(handler *SubscriptionHandler, delivery amqp.Delivery) error {
	// if metrics is not enabled just invoke the function
	if c.Metrics == nil {
		return handler.HandleEvent(c.contextValue, delivery.Body)
	}

	c.Metrics.GetCounter("message").Inc(1)

	var err error

	c.Metrics.GetTimer(delivery.Type).Time(func() {
		err = handler.HandleEvent(c.contextValue, delivery.Body)
	})

	return err
}

func (c *Consumer) withCounter(counterName string, fn func()) {
	if c.Metrics == nil {
		fn()
	}

	c.Metrics.GetCounter(counterName).Inc(1)
	fn()
}

func (c *Consumer) Start() func(delivery amqp.Delivery) {
	c.Log.Info("Broker sarted to consume")
	return func(delivery amqp.Delivery) {
		if _, ok := c.handlers[delivery.Type]; !ok {
			// if no handler found, just ack message
			c.Log.Debug("No handler for %s", delivery.Type)
			c.withCounter("nohandlerforevent", func() { delivery.Ack(false) })
			return
		}

		var err error
		for _, handler := range c.handlers[delivery.Type] {
			// do not continue, if one of the handler gives error
			if err != nil {
				break
			}

			err = c.withMetrics(handler, delivery)
		}

		c.handleError(err, delivery)
	}
}

func (c *Consumer) handleError(err error, delivery amqp.Delivery) {
	switch err {
	case nil:
		c.withCounter("success", func() { delivery.Ack(false) })
	case ErrNoHandlerFound:
		c.withCounter("handlernotfound", func() { delivery.Ack(false) })
		c.Log.Debug("unknown event type (%s) recieved, deleting message from RMQ", delivery.Type)
	case gorm.RecordNotFound:
		c.withCounter("gormrecordnotfound", func() { delivery.Ack(false) })
		c.Log.Warning("Record not found in our db (%s) recieved, deleting message from RMQ", string(delivery.Body))
	case mgo.ErrNotFound:
		c.withCounter("mgorecordnotfound", func() { delivery.Ack(false) })
		c.Log.Warning("Record not found in our mongo db (%s) recieved, deleting message from RMQ", string(delivery.Body))
	default:
		c.withCounter("othererror", func() {
			// default err handler should handle the ack process
			if c.context.DefaultErrHandler(delivery, err) {
				if c.MaintenancePublisher == nil {
					return
				}

				data, err := json.Marshal(delivery)
				if err != nil {
					return
				}

				msg := amqp.Publishing{
					Body:  []byte(data),
					AppId: c.WorkerName,
				}

				c.withCounter("publishedtomaintenancequeue", func() {
					c.MaintenancePublisher.Publish(msg)
				})
			}
		})
	}
}

type SubscriptionHandler struct {
	v reflect.Value
}

func NewSubscriptionHandler(i interface{}) (*SubscriptionHandler, error) {
	t := reflect.TypeOf(i)
	if t.Kind() != reflect.Func {
		return nil, fmt.Errorf("kind was %v, not Func", t.Kind())
	}

	// check input parameter count
	if t.NumIn() != 2 {
		return nil, fmt.Errorf("input arity was %v, not 2", t.NumIn())
	}

	// check output parameter count
	if t.NumOut() != 1 {
		return nil, fmt.Errorf("output arity was %v, not 1", t.NumOut())
	}

	// output should be errors
	if t.Out(0).String() != "error" {
		return nil, fmt.Errorf("type of return value was %v, not error", t.Out(0))
	}

	return &SubscriptionHandler{reflect.ValueOf(i)}, nil
}

var nilParameter = reflect.ValueOf((*interface{})(nil))

func (m *SubscriptionHandler) HandleEvent(controllerValue reflect.Value, data []byte) error {
	var parameter reflect.Value

	if m.v.Type().NumIn() == 2 {
		in2 := m.v.Type().In(1)
		// if incoming paramter is an empty interface
		if reflect.Interface == in2.Kind() && in2.NumMethod() == 0 {
			parameter = nilParameter
			// if incoming parameter is a slice or a map
		} else if reflect.Slice == in2.Kind() || reflect.Map == in2.Kind() {
			// non-pointer maps/slices require special treatment because
			// json.Unmarshal won't work on a non-pointer destination. We
			// add a level indirection here, then deref it before .Call()
			parameter = reflect.New(in2)
		} else {
			// if it is a struct
			parameter = reflect.New(in2.Elem())
		}
	} else {
		// if handler doesnt have any incoming paramters
		parameter = nilParameter
	}

	// this is where magic happens:)
	// first read incoming []byte data into a io.reader then
	// put this data into a decoder(create a decoder out of it)
	// finally decode this data into given
	decoder := reflect.ValueOf(json.NewDecoder(bytes.NewReader(data)))
	res := decoder.MethodByName("Decode").Call([]reflect.Value{parameter})
	if len(res) > 0 && !res[0].IsNil() {
		return res[0].Interface().(error)
	}

	if reflect.Slice == parameter.Elem().Kind() || reflect.Map == parameter.Elem().Kind() {
		parameter = parameter.Elem()
	}

	var out []reflect.Value
	switch m.v.Type().NumIn() {
	case 2:
		out = m.v.Call([]reflect.Value{
			controllerValue,
			parameter,
		})
	case 3:
		out = m.v.Call([]reflect.Value{
			controllerValue,
			parameter,
			reflect.ValueOf(logging),
		})
	default:
		return fmt.Errorf("unknown signature %s", m.v.Type())
	}

	if len(out) > 0 && !out[0].IsNil() {
		return out[0].Interface().(error)
	}

	return nil
}
<commit_msg>Borker: commentout unused code<commit_after>package broker

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/jinzhu/gorm"
	"github.com/streadway/amqp"
	"labix.org/v2/mgo"
)

type Handler interface {
	HandleEvent(string, []byte) error
	ErrHandler
}

type ErrHandler interface {
	// bool is whether publishing the message to maintenance qeueue or not
	DefaultErrHandler(amqp.Delivery, error) bool
}

func (c *Consumer) withMetrics(handler *SubscriptionHandler, delivery amqp.Delivery) error {
	// if metrics is not enabled just invoke the function
	if c.Metrics == nil {
		return handler.HandleEvent(c.contextValue, delivery.Body)
	}

	c.Metrics.GetCounter("message").Inc(1)

	var err error

	c.Metrics.GetTimer(delivery.Type).Time(func() {
		err = handler.HandleEvent(c.contextValue, delivery.Body)
	})

	return err
}

func (c *Consumer) withCounter(counterName string, fn func()) {
	if c.Metrics == nil {
		fn()
	}

	c.Metrics.GetCounter(counterName).Inc(1)
	fn()
}

func (c *Consumer) Start() func(delivery amqp.Delivery) {
	c.Log.Info("Broker sarted to consume")
	return func(delivery amqp.Delivery) {
		if _, ok := c.handlers[delivery.Type]; !ok {
			// if no handler found, just ack message
			c.Log.Debug("No handler for %s", delivery.Type)
			c.withCounter("nohandlerforevent", func() { delivery.Ack(false) })
			return
		}

		var err error
		for _, handler := range c.handlers[delivery.Type] {
			// do not continue, if one of the handler gives error
			if err != nil {
				break
			}

			err = c.withMetrics(handler, delivery)
		}

		c.handleError(err, delivery)
	}
}

func (c *Consumer) handleError(err error, delivery amqp.Delivery) {
	switch err {
	case nil:
		c.withCounter("success", func() { delivery.Ack(false) })
	case ErrNoHandlerFound:
		c.withCounter("handlernotfound", func() { delivery.Ack(false) })
		c.Log.Debug("unknown event type (%s) recieved, deleting message from RMQ", delivery.Type)
	case gorm.RecordNotFound:
		c.withCounter("gormrecordnotfound", func() { delivery.Ack(false) })
		c.Log.Warning("Record not found in our db (%s) recieved, deleting message from RMQ", string(delivery.Body))
	case mgo.ErrNotFound:
		c.withCounter("mgorecordnotfound", func() { delivery.Ack(false) })
		c.Log.Warning("Record not found in our mongo db (%s) recieved, deleting message from RMQ", string(delivery.Body))
	default:
		c.withCounter("othererror", func() {
			// default err handler should handle the ack process
			if c.context.DefaultErrHandler(delivery, err) {
				if c.MaintenancePublisher == nil {
					return
				}

				data, err := json.Marshal(delivery)
				if err != nil {
					return
				}

				msg := amqp.Publishing{
					Body:  []byte(data),
					AppId: c.WorkerName,
				}

				c.withCounter("publishedtomaintenancequeue", func() {
					c.MaintenancePublisher.Publish(msg)
				})
			}
		})
	}
}

type SubscriptionHandler struct {
	v reflect.Value
}

func NewSubscriptionHandler(i interface{}) (*SubscriptionHandler, error) {
	t := reflect.TypeOf(i)
	if t.Kind() != reflect.Func {
		return nil, fmt.Errorf("kind was %v, not Func", t.Kind())
	}

	// check input parameter count
	if t.NumIn() != 2 {
		return nil, fmt.Errorf("input arity was %v, not 2", t.NumIn())
	}

	// check output parameter count
	if t.NumOut() != 1 {
		return nil, fmt.Errorf("output arity was %v, not 1", t.NumOut())
	}

	// output should be errors
	if t.Out(0).String() != "error" {
		return nil, fmt.Errorf("type of return value was %v, not error", t.Out(0))
	}

	return &SubscriptionHandler{reflect.ValueOf(i)}, nil
}

var nilParameter = reflect.ValueOf((*interface{})(nil))

func (m *SubscriptionHandler) HandleEvent(controllerValue reflect.Value, data []byte) error {
	var parameter reflect.Value

	if m.v.Type().NumIn() == 2 {
		in2 := m.v.Type().In(1)
		// if incoming paramter is an empty interface
		if reflect.Interface == in2.Kind() && in2.NumMethod() == 0 {
			parameter = nilParameter
			// if incoming parameter is a slice or a map
		} else if reflect.Slice == in2.Kind() || reflect.Map == in2.Kind() {
			// non-pointer maps/slices require special treatment because
			// json.Unmarshal won't work on a non-pointer destination. We
			// add a level indirection here, then deref it before .Call()
			parameter = reflect.New(in2)
		} else {
			// if it is a struct
			parameter = reflect.New(in2.Elem())
		}
	} else {
		// if handler doesnt have any incoming paramters
		parameter = nilParameter
	}

	// this is where magic happens:)
	// first read incoming []byte data into a io.reader then
	// put this data into a decoder(create a decoder out of it)
	// finally decode this data into given
	decoder := reflect.ValueOf(json.NewDecoder(bytes.NewReader(data)))
	res := decoder.MethodByName("Decode").Call([]reflect.Value{parameter})
	if len(res) > 0 && !res[0].IsNil() {
		return res[0].Interface().(error)
	}

	if reflect.Slice == parameter.Elem().Kind() || reflect.Map == parameter.Elem().Kind() {
		parameter = parameter.Elem()
	}

	var out []reflect.Value
	switch m.v.Type().NumIn() {
	case 2:
		out = m.v.Call([]reflect.Value{
			controllerValue,
			parameter,
		})
	// case 3:
	// 	out = m.v.Call([]reflect.Value{
	// 		controllerValue,
	// 		parameter,
	// 		reflect.ValueOf(logging),
	// 	})
	default:
		return fmt.Errorf("unknown signature %s", m.v.Type())
	}

	if len(out) > 0 && !out[0].IsNil() {
		return out[0].Interface().(error)
	}

	return nil
}
<|endoftext|>


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

package fs

import (
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"syscall"

	"github.com/pkg/errors"
)

// RenameWithFallback attempts to rename a file or directory, but falls back to
// copying in the event of a cross-device link error. If the fallback copy
// succeeds, src is still removed, emulating normal rename behavior.
func RenameWithFallback(src, dst string) error {
	_, err := os.Stat(src)
	if err != nil {
		return errors.Wrapf(err, "cannot stat %s", src)
	}

	err = os.Rename(src, dst)
	if err == nil {
		return nil
	}

	return renameFallback(err, src, dst)
}

// renameByCopy attempts to rename a file or directory by copying it to the
// destination and then removing the src thus emulating the rename behavior.
func renameByCopy(src, dst string) error {
	var cerr error
	if dir, _ := IsDir(src); dir {
		cerr = CopyDir(src, dst)
		if cerr != nil {
			cerr = errors.Wrap(cerr, "copying directory failed")
		}
	} else {
		cerr = copyFile(src, dst)
		if cerr != nil {
			cerr = errors.Wrap(cerr, "copying file failed")
		}
	}

	if cerr != nil {
		return errors.Wrapf(cerr, "rename fallback failed: cannot rename %s to %s", src, dst)
	}

	return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src)
}

var errPathNotDir = errors.New("given path is not a directory")

var (
	errSrcNotDir = errors.New("source is not a directory")
	errDstExist  = errors.New("destination already exists")
)

// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
func CopyDir(src, dst string) error {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	// We use os.Lstat() here to ensure we don't fall in a loop where a symlink
	// actually links to a one of its parent directories.
	fi, err := os.Lstat(src)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return errSrcNotDir
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return err
	}
	if err == nil {
		return errDstExist
	}

	if err = os.MkdirAll(dst, fi.Mode()); err != nil {
		return errors.Wrapf(err, "cannot mkdir %s", dst)
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return errors.Wrapf(err, "cannot read directory %s", dst)
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())

		if entry.IsDir() {
			if err = CopyDir(srcPath, dstPath); err != nil {
				return errors.Wrap(err, "copying directory failed")
			}
		} else {
			// This will include symlinks, which is what we want when
			// copying things.
			if err = copyFile(srcPath, dstPath); err != nil {
				return errors.Wrap(err, "copying file failed")
			}
		}
	}

	return nil
}

// copyFile copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all its contents will be replaced by the contents
// of the source file. The file mode will be copied from the source.
func copyFile(src, dst string) (err error) {
	if sym, err := IsSymlink(src); err != nil {
		return errors.Wrap(err, "symlink check failed")
	} else if sym {
		if err := cloneSymlink(src, dst); err != nil {
			if runtime.GOOS == "windows" {
				// If cloning the symlink fails on Windows because the user
				// does not have the required privileges, ignore the error and
				// fall back to copying the file contents.
				//
				// ERROR_PRIVILEGE_NOT_HELD is 1314 (0x522):
				// https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
				if lerr, ok := err.(*os.LinkError); ok && lerr.Err != syscall.Errno(1314) {
					return err
				}
			} else {
				return err
			}
		} else {
			return nil
		}
	}

	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

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

	if _, err = io.Copy(out, in); err != nil {
		out.Close()
		return
	}

	// Check for write errors on Close
	if err = out.Close(); err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}

	// Temporary fix for Go < 1.9
	//
	// See: https://github.com/golang/dep/issues/774
	// and https://github.com/golang/go/issues/20829
	if runtime.GOOS == "windows" {
		dst = fixLongPath(dst)
	}
	err = os.Chmod(dst, si.Mode())

	return
}

// cloneSymlink will create a new symlink that points to the resolved path of sl.
// If sl is a relative symlink, dst will also be a relative symlink.
func cloneSymlink(sl, dst string) error {
	resolved, err := os.Readlink(sl)
	if err != nil {
		return err
	}

	return os.Symlink(resolved, dst)
}

// IsDir determines is the path given is a directory or not.
func IsDir(name string) (bool, error) {
	fi, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	if !fi.IsDir() {
		return false, errors.Errorf("%q is not a directory", name)
	}
	return true, nil
}

// IsSymlink determines if the given path is a symbolic link.
func IsSymlink(path string) (bool, error) {
	l, err := os.Lstat(path)
	if err != nil {
		return false, err
	}

	return l.Mode()&os.ModeSymlink == os.ModeSymlink, nil
}

// fixLongPath returns the extended-length (\\?\-prefixed) form of
// path when needed, in order to avoid the default 260 character file
// path limit imposed by Windows. If path is not easily converted to
// the extended-length form (for example, if path is a relative path
// or contains .. elements), or is short enough, fixLongPath returns
// path unmodified.
//
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
func fixLongPath(path string) string {
	// Do nothing (and don't allocate) if the path is "short".
	// Empirically (at least on the Windows Server 2013 builder),
	// the kernel is arbitrarily okay with < 248 bytes. That
	// matches what the docs above say:
	// "When using an API to create a directory, the specified
	// path cannot be so long that you cannot append an 8.3 file
	// name (that is, the directory name cannot exceed MAX_PATH
	// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
	//
	// The MSDN docs appear to say that a normal path that is 248 bytes long
	// will work; empirically the path must be less then 248 bytes long.
	if len(path) < 248 {
		// Don't fix. (This is how Go 1.7 and earlier worked,
		// not automatically generating the \\?\ form)
		return path
	}

	// The extended form begins with \\?\, as in
	// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
	// The extended form disables evaluation of . and .. path
	// elements and disables the interpretation of / as equivalent
	// to \. The conversion here rewrites / to \ and elides
	// . elements as well as trailing or duplicate separators. For
	// simplicity it avoids the conversion entirely for relative
	// paths or paths containing .. elements. For now,
	// \\server\share paths are not converted to
	// \\?\UNC\server\share paths because the rules for doing so
	// are less well-specified.
	if len(path) >= 2 && path[:2] == `\\` {
		// Don't canonicalize UNC paths.
		return path
	}
	if !isAbs(path) {
		// Relative path
		return path
	}

	const prefix = `\\?`

	pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
	copy(pathbuf, prefix)
	n := len(path)
	r, w := 0, len(prefix)
	for r < n {
		switch {
		case os.IsPathSeparator(path[r]):
			// empty block
			r++
		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
			// /./
			r++
		case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
			// /../ is currently unhandled
			return path
		default:
			pathbuf[w] = '\\'
			w++
			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
				pathbuf[w] = path[r]
				w++
			}
		}
	}
	// A drive's root directory needs a trailing \
	if w == len(`\\?\c:`) {
		pathbuf[w] = '\\'
		w++
	}
	return string(pathbuf[:w])
}

func isAbs(path string) (b bool) {
	v := volumeName(path)
	if v == "" {
		return false
	}
	path = path[len(v):]
	if path == "" {
		return false
	}
	return os.IsPathSeparator(path[0])
}

func volumeName(path string) (v string) {
	if len(path) < 2 {
		return ""
	}
	// with drive letter
	c := path[0]
	if path[1] == ':' &&
		('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
			'A' <= c && c <= 'Z') {
		return path[:2]
	}
	// is it UNC
	if l := len(path); l >= 5 && os.IsPathSeparator(path[0]) && os.IsPathSeparator(path[1]) &&
		!os.IsPathSeparator(path[2]) && path[2] != '.' {
		// first, leading `\\` and next shouldn't be `\`. its server name.
		for n := 3; n < l-1; n++ {
			// second, next '\' shouldn't be repeated.
			if os.IsPathSeparator(path[n]) {
				n++
				// third, following something characters. its share name.
				if !os.IsPathSeparator(path[n]) {
					if path[n] == '.' {
						break
					}
					for ; n < l; n++ {
						if os.IsPathSeparator(path[n]) {
							break
						}
					}
					return path[:n]
				}
				break
			}
		}
	}
	return ""
}
<commit_msg>Remove dead code<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fs

import (
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"syscall"

	"github.com/pkg/errors"
)

// RenameWithFallback attempts to rename a file or directory, but falls back to
// copying in the event of a cross-device link error. If the fallback copy
// succeeds, src is still removed, emulating normal rename behavior.
func RenameWithFallback(src, dst string) error {
	_, err := os.Stat(src)
	if err != nil {
		return errors.Wrapf(err, "cannot stat %s", src)
	}

	err = os.Rename(src, dst)
	if err == nil {
		return nil
	}

	return renameFallback(err, src, dst)
}

// renameByCopy attempts to rename a file or directory by copying it to the
// destination and then removing the src thus emulating the rename behavior.
func renameByCopy(src, dst string) error {
	var cerr error
	if dir, _ := IsDir(src); dir {
		cerr = CopyDir(src, dst)
		if cerr != nil {
			cerr = errors.Wrap(cerr, "copying directory failed")
		}
	} else {
		cerr = copyFile(src, dst)
		if cerr != nil {
			cerr = errors.Wrap(cerr, "copying file failed")
		}
	}

	if cerr != nil {
		return errors.Wrapf(cerr, "rename fallback failed: cannot rename %s to %s", src, dst)
	}

	return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src)
}

var (
	errSrcNotDir = errors.New("source is not a directory")
	errDstExist  = errors.New("destination already exists")
)

// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
func CopyDir(src, dst string) error {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	// We use os.Lstat() here to ensure we don't fall in a loop where a symlink
	// actually links to a one of its parent directories.
	fi, err := os.Lstat(src)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return errSrcNotDir
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return err
	}
	if err == nil {
		return errDstExist
	}

	if err = os.MkdirAll(dst, fi.Mode()); err != nil {
		return errors.Wrapf(err, "cannot mkdir %s", dst)
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return errors.Wrapf(err, "cannot read directory %s", dst)
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())

		if entry.IsDir() {
			if err = CopyDir(srcPath, dstPath); err != nil {
				return errors.Wrap(err, "copying directory failed")
			}
		} else {
			// This will include symlinks, which is what we want when
			// copying things.
			if err = copyFile(srcPath, dstPath); err != nil {
				return errors.Wrap(err, "copying file failed")
			}
		}
	}

	return nil
}

// copyFile copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all its contents will be replaced by the contents
// of the source file. The file mode will be copied from the source.
func copyFile(src, dst string) (err error) {
	if sym, err := IsSymlink(src); err != nil {
		return errors.Wrap(err, "symlink check failed")
	} else if sym {
		if err := cloneSymlink(src, dst); err != nil {
			if runtime.GOOS == "windows" {
				// If cloning the symlink fails on Windows because the user
				// does not have the required privileges, ignore the error and
				// fall back to copying the file contents.
				//
				// ERROR_PRIVILEGE_NOT_HELD is 1314 (0x522):
				// https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
				if lerr, ok := err.(*os.LinkError); ok && lerr.Err != syscall.Errno(1314) {
					return err
				}
			} else {
				return err
			}
		} else {
			return nil
		}
	}

	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

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

	if _, err = io.Copy(out, in); err != nil {
		out.Close()
		return
	}

	// Check for write errors on Close
	if err = out.Close(); err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}

	// Temporary fix for Go < 1.9
	//
	// See: https://github.com/golang/dep/issues/774
	// and https://github.com/golang/go/issues/20829
	if runtime.GOOS == "windows" {
		dst = fixLongPath(dst)
	}
	err = os.Chmod(dst, si.Mode())

	return
}

// cloneSymlink will create a new symlink that points to the resolved path of sl.
// If sl is a relative symlink, dst will also be a relative symlink.
func cloneSymlink(sl, dst string) error {
	resolved, err := os.Readlink(sl)
	if err != nil {
		return err
	}

	return os.Symlink(resolved, dst)
}

// IsDir determines is the path given is a directory or not.
func IsDir(name string) (bool, error) {
	fi, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	if !fi.IsDir() {
		return false, errors.Errorf("%q is not a directory", name)
	}
	return true, nil
}

// IsSymlink determines if the given path is a symbolic link.
func IsSymlink(path string) (bool, error) {
	l, err := os.Lstat(path)
	if err != nil {
		return false, err
	}

	return l.Mode()&os.ModeSymlink == os.ModeSymlink, nil
}

// fixLongPath returns the extended-length (\\?\-prefixed) form of
// path when needed, in order to avoid the default 260 character file
// path limit imposed by Windows. If path is not easily converted to
// the extended-length form (for example, if path is a relative path
// or contains .. elements), or is short enough, fixLongPath returns
// path unmodified.
//
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
func fixLongPath(path string) string {
	// Do nothing (and don't allocate) if the path is "short".
	// Empirically (at least on the Windows Server 2013 builder),
	// the kernel is arbitrarily okay with < 248 bytes. That
	// matches what the docs above say:
	// "When using an API to create a directory, the specified
	// path cannot be so long that you cannot append an 8.3 file
	// name (that is, the directory name cannot exceed MAX_PATH
	// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
	//
	// The MSDN docs appear to say that a normal path that is 248 bytes long
	// will work; empirically the path must be less then 248 bytes long.
	if len(path) < 248 {
		// Don't fix. (This is how Go 1.7 and earlier worked,
		// not automatically generating the \\?\ form)
		return path
	}

	// The extended form begins with \\?\, as in
	// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
	// The extended form disables evaluation of . and .. path
	// elements and disables the interpretation of / as equivalent
	// to \. The conversion here rewrites / to \ and elides
	// . elements as well as trailing or duplicate separators. For
	// simplicity it avoids the conversion entirely for relative
	// paths or paths containing .. elements. For now,
	// \\server\share paths are not converted to
	// \\?\UNC\server\share paths because the rules for doing so
	// are less well-specified.
	if len(path) >= 2 && path[:2] == `\\` {
		// Don't canonicalize UNC paths.
		return path
	}
	if !isAbs(path) {
		// Relative path
		return path
	}

	const prefix = `\\?`

	pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
	copy(pathbuf, prefix)
	n := len(path)
	r, w := 0, len(prefix)
	for r < n {
		switch {
		case os.IsPathSeparator(path[r]):
			// empty block
			r++
		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
			// /./
			r++
		case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
			// /../ is currently unhandled
			return path
		default:
			pathbuf[w] = '\\'
			w++
			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
				pathbuf[w] = path[r]
				w++
			}
		}
	}
	// A drive's root directory needs a trailing \
	if w == len(`\\?\c:`) {
		pathbuf[w] = '\\'
		w++
	}
	return string(pathbuf[:w])
}

func isAbs(path string) (b bool) {
	v := volumeName(path)
	if v == "" {
		return false
	}
	path = path[len(v):]
	if path == "" {
		return false
	}
	return os.IsPathSeparator(path[0])
}

func volumeName(path string) (v string) {
	if len(path) < 2 {
		return ""
	}
	// with drive letter
	c := path[0]
	if path[1] == ':' &&
		('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
			'A' <= c && c <= 'Z') {
		return path[:2]
	}
	// is it UNC
	if l := len(path); l >= 5 && os.IsPathSeparator(path[0]) && os.IsPathSeparator(path[1]) &&
		!os.IsPathSeparator(path[2]) && path[2] != '.' {
		// first, leading `\\` and next shouldn't be `\`. its server name.
		for n := 3; n < l-1; n++ {
			// second, next '\' shouldn't be repeated.
			if os.IsPathSeparator(path[n]) {
				n++
				// third, following something characters. its share name.
				if !os.IsPathSeparator(path[n]) {
					if path[n] == '.' {
						break
					}
					for ; n < l; n++ {
						if os.IsPathSeparator(path[n]) {
							break
						}
					}
					return path[:n]
				}
				break
			}
		}
	}
	return ""
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

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 tabletmanager

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
	"vitess.io/vitess/go/vt/logutil"
	"vitess.io/vitess/go/vt/mysqlctl"
	"vitess.io/vitess/go/vt/topo/topoproto"
	"vitess.io/vitess/go/vt/topotools"
	"vitess.io/vitess/go/vt/vterrors"

	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

// Backup takes a db backup and sends it to the BackupStorage
func (agent *ActionAgent) Backup(ctx context.Context, concurrency int, logger logutil.Logger, allowMaster bool) error {
	if agent.Cnf == nil {
		return fmt.Errorf("cannot perform backup without my.cnf, please restart vttablet with a my.cnf file specified")
	}

	// Check tablet type current process has.
	// During a network partition it is possible that from the topology perspective this is no longer the master,
	// but the process didn't find out about this.
	// It is not safe to take backups from tablet in this state
	currentTablet := agent.Tablet()
	if !allowMaster && currentTablet.Type == topodatapb.TabletType_MASTER {
		return fmt.Errorf("type MASTER cannot take backup. if you really need to do this, rerun the backup command with -allow_master")
	}
	engine, err := mysqlctl.GetBackupEngine()
	if err != nil {
		return vterrors.Wrap(err, "failed to find backup engine")
	}
	builtin, _ := engine.(*mysqlctl.BuiltinBackupEngine)
	// get Tablet info from topo so that it is up to date
	tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
	if err != nil {
		return err
	}
	originalType := tablet.Type
	if builtin != nil {
		if err := agent.lock(ctx); err != nil {
			return err
		}
		defer agent.unlock()

		tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
		if err != nil {
			return err
		}

		// update our type to BACKUP
		if _, err := topotools.ChangeType(ctx, agent.TopoServer, tablet.Alias, topodatapb.TabletType_BACKUP); err != nil {
			return err
		}

		// let's update our internal state (stop query service and other things)
		if err := agent.refreshTablet(ctx, "before backup"); err != nil {
			return err
		}
	}
	// create the loggers: tee to console and source
	l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)

	// now we can run the backup
	dir := fmt.Sprintf("%v/%v", tablet.Keyspace, tablet.Shard)
	name := fmt.Sprintf("%v.%v", time.Now().UTC().Format("2006-01-02.150405"), topoproto.TabletAliasString(tablet.Alias))
	returnErr := mysqlctl.Backup(ctx, agent.Cnf, agent.MysqlDaemon, l, dir, name, concurrency, agent.hookExtraEnv())

	if builtin != nil {
		bgCtx := context.Background()
		// Starting from here we won't be able to recover if we get stopped by a cancelled
		// context. It is also possible that the context already timed out during the
		// above call to Backup. Thus we use the background context to get through to the finish.

		// change our type back to the original value
		_, err = topotools.ChangeType(bgCtx, agent.TopoServer, tablet.Alias, originalType)
		if err != nil {
			// failure in changing the topology type is probably worse,
			// so returning that (we logged the snapshot error anyway)
			if returnErr != nil {
				l.Errorf("mysql backup command returned error: %v", returnErr)
			}
			returnErr = err
		}

		// let's update our internal state (start query service and other things)
		if err := agent.refreshTablet(bgCtx, "after backup"); err != nil {
			return err
		}
	}
	// and re-run health check to be sure to capture any replication delay
	agent.runHealthCheckLocked()

	return returnErr
}

// RestoreFromBackup deletes all local data and restores anew from the latest backup.
func (agent *ActionAgent) RestoreFromBackup(ctx context.Context, logger logutil.Logger) error {
	if err := agent.lock(ctx); err != nil {
		return err
	}
	defer agent.unlock()

	tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
	if err != nil {
		return err
	}
	if tablet.Type == topodatapb.TabletType_MASTER {
		return fmt.Errorf("type MASTER cannot restore from backup, if you really need to do this, restart vttablet in replica mode")
	}

	// create the loggers: tee to console and source
	l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)

	// now we can run restore
	err = agent.restoreDataLocked(ctx, l, 0 /* waitForBackupInterval */, true /* deleteBeforeRestore */)

	// re-run health check to be sure to capture any replication delay
	agent.runHealthCheckLocked()

	return err
}
<commit_msg>address review comments<commit_after>/*
Copyright 2017 Google Inc.

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 tabletmanager

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
	"vitess.io/vitess/go/vt/logutil"
	"vitess.io/vitess/go/vt/mysqlctl"
	"vitess.io/vitess/go/vt/topo/topoproto"
	"vitess.io/vitess/go/vt/topotools"
	"vitess.io/vitess/go/vt/vterrors"

	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

// Backup takes a db backup and sends it to the BackupStorage
func (agent *ActionAgent) Backup(ctx context.Context, concurrency int, logger logutil.Logger, allowMaster bool) error {
	if agent.Cnf == nil {
		return fmt.Errorf("cannot perform backup without my.cnf, please restart vttablet with a my.cnf file specified")
	}

	// Check tablet type current process has.
	// During a network partition it is possible that from the topology perspective this is no longer the master,
	// but the process didn't find out about this.
	// It is not safe to take backups from tablet in this state
	currentTablet := agent.Tablet()
	if !allowMaster && currentTablet.Type == topodatapb.TabletType_MASTER {
		return fmt.Errorf("type MASTER cannot take backup. if you really need to do this, rerun the backup command with -allow_master")
	}
	engine, err := mysqlctl.GetBackupEngine()
	if err != nil {
		return vterrors.Wrap(err, "failed to find backup engine")
	}
	builtin, _ := engine.(*mysqlctl.BuiltinBackupEngine)
	// get Tablet info from topo so that it is up to date
	tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
	if err != nil {
		return err
	}
	if !allowMaster && tablet.Type == topodatapb.TabletType_MASTER {
		return fmt.Errorf("type MASTER cannot take backup. if you really need to do this, rerun the backup command with -allow_master")
	}
	var originalType topodatapb.TabletType
	if builtin != nil {
		if err := agent.lock(ctx); err != nil {
			return err
		}
		defer agent.unlock()

		tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
		if err != nil {
			return err
		}
		originalType = tablet.Type
		// update our type to BACKUP
		if _, err := topotools.ChangeType(ctx, agent.TopoServer, tablet.Alias, topodatapb.TabletType_BACKUP); err != nil {
			return err
		}

		// let's update our internal state (stop query service and other things)
		if err := agent.refreshTablet(ctx, "before backup"); err != nil {
			return err
		}
	}
	// create the loggers: tee to console and source
	l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)

	// now we can run the backup
	dir := fmt.Sprintf("%v/%v", tablet.Keyspace, tablet.Shard)
	name := fmt.Sprintf("%v.%v", time.Now().UTC().Format("2006-01-02.150405"), topoproto.TabletAliasString(tablet.Alias))
	returnErr := mysqlctl.Backup(ctx, agent.Cnf, agent.MysqlDaemon, l, dir, name, concurrency, agent.hookExtraEnv())

	if builtin != nil {
		bgCtx := context.Background()
		// Starting from here we won't be able to recover if we get stopped by a cancelled
		// context. It is also possible that the context already timed out during the
		// above call to Backup. Thus we use the background context to get through to the finish.

		// change our type back to the original value
		_, err = topotools.ChangeType(bgCtx, agent.TopoServer, tablet.Alias, originalType)
		if err != nil {
			// failure in changing the topology type is probably worse,
			// so returning that (we logged the snapshot error anyway)
			if returnErr != nil {
				l.Errorf("mysql backup command returned error: %v", returnErr)
			}
			returnErr = err
		}

		// let's update our internal state (start query service and other things)
		if err := agent.refreshTablet(bgCtx, "after backup"); err != nil {
			return err
		}
	}
	// and re-run health check to be sure to capture any replication delay
	agent.runHealthCheckLocked()

	return returnErr
}

// RestoreFromBackup deletes all local data and restores anew from the latest backup.
func (agent *ActionAgent) RestoreFromBackup(ctx context.Context, logger logutil.Logger) error {
	if err := agent.lock(ctx); err != nil {
		return err
	}
	defer agent.unlock()

	tablet, err := agent.TopoServer.GetTablet(ctx, agent.TabletAlias)
	if err != nil {
		return err
	}
	if tablet.Type == topodatapb.TabletType_MASTER {
		return fmt.Errorf("type MASTER cannot restore from backup, if you really need to do this, restart vttablet in replica mode")
	}

	// create the loggers: tee to console and source
	l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)

	// now we can run restore
	err = agent.restoreDataLocked(ctx, l, 0 /* waitForBackupInterval */, true /* deleteBeforeRestore */)

	// re-run health check to be sure to capture any replication delay
	agent.runHealthCheckLocked()

	return err
}
<|endoftext|>


<commit_before>package proto

import (
	"bytes"
	"errors"
	"io"
	"fmt"
	"github.com/vapourismo/knx-go/knx/binary"
)

// A TPCI is the transport-layer protocol control information (TPCI).
type TPCI uint8

//
const (
	UnnumberedDataPacket    TPCI = 0
	NumberedDataPacket      TPCI = 1
	UnnumberedControlPacket TPCI = 2
	NumberedControlPacket   TPCI = 3
)

// An APCI is the application-layer protocol control information (APCI).
type APCI uint8

//
const (
	GroupValueRead         APCI = 0
	GroupValueResponse     APCI = 1
	GroupValueWrite        APCI = 2
	IndividualAddrWrite    APCI = 3
	IndividualAddrRequest  APCI = 4
	IndividualAddrResponse APCI = 5
	AdcRead                APCI = 6
	AdcResponse            APCI = 7
	MemoryRead             APCI = 8
	MemoryResponse         APCI = 9
	MemoryWrite            APCI = 10
	UserMessage            APCI = 11
	MaskVersionRead        APCI = 12
	MaskVersionResponse    APCI = 13
	Restart                APCI = 14
	Escape                 APCI = 15
)

// A TPDU is the transport-layer protocol data unit within a L_Data frame.
type TPDU struct {
	PacketType TPCI
	SeqNumber  uint8
	Control    uint8
	Info       APCI
	Data       []byte
}

// Errors returned from ReadTPDU
var (
	ErrDataUnitTooShort = errors.New("Data segment of the TPDU is too short")
)

// ReadFrom parses the given data in order to fill the TPDU struct.
func (tpdu *TPDU) ReadFrom(r io.Reader) error {
	var head uint8

	err := binary.ReadSequence(r, &head)
	if err != nil {
		return err
	}

	packetType := TPCI((head >> 6) & 3)
	seqNumber := (head >> 2) & 15

	switch packetType {
	case UnnumberedControlPacket, NumberedControlPacket:
		tpdu.PacketType = packetType
		tpdu.SeqNumber = seqNumber
		tpdu.Control = head & 3
		tpdu.Info = 0
		tpdu.Data = nil

		return nil

	case UnnumberedDataPacket, NumberedDataPacket:
		buffer := &bytes.Buffer{}

		// Empty the reader's remaining contents into a buffer.
		len, err := buffer.ReadFrom(r)
		if err != nil {
			return err
		} else if len < 1 {
			return ErrDataUnitTooShort
		}

		data := buffer.Bytes()

		tpdu.PacketType = packetType
		tpdu.SeqNumber = seqNumber
		tpdu.Control = 0
		tpdu.Info = APCI((head & 3) << 2 | (data[0] >> 6) & 3)
		tpdu.Data = data

		// The first 2 bits of the data contain rest of the APCI, we don't need them anymore.
		tpdu.Data[0] &= 63

		return nil
	}

	return errors.New("Unreachable")
}

// WriteTo writes the TPDU structure to the given Writer.
func (tpdu *TPDU) WriteTo(w io.Writer) error {
	headMask := byte(tpdu.PacketType & 3) << 6 | byte(tpdu.SeqNumber & 15) << 2

	switch tpdu.PacketType & 3 {
	case UnnumberedControlPacket, NumberedControlPacket:
		_, err := w.Write([]byte{headMask | byte(tpdu.Control & 3)})
		return err

	case UnnumberedDataPacket, NumberedDataPacket:
		data := make([]byte, 1, 2)
		if len(tpdu.Data) > 0 {
			data = append(data, tpdu.Data...)
		} else {
			data = append(data, 0)
		}

		data[0] |= byte(tpdu.Info >> 2) & 3
		data[1] &= 63

		_, err := w.Write(data)
		return err
	}

	return errors.New("Unreachable")
}
<commit_msg>Remove unused imports<commit_after>package proto

import (
	"bytes"
	"errors"
	"io"
	"github.com/vapourismo/knx-go/knx/binary"
)

// A TPCI is the transport-layer protocol control information (TPCI).
type TPCI uint8

//
const (
	UnnumberedDataPacket    TPCI = 0
	NumberedDataPacket      TPCI = 1
	UnnumberedControlPacket TPCI = 2
	NumberedControlPacket   TPCI = 3
)

// An APCI is the application-layer protocol control information (APCI).
type APCI uint8

//
const (
	GroupValueRead         APCI = 0
	GroupValueResponse     APCI = 1
	GroupValueWrite        APCI = 2
	IndividualAddrWrite    APCI = 3
	IndividualAddrRequest  APCI = 4
	IndividualAddrResponse APCI = 5
	AdcRead                APCI = 6
	AdcResponse            APCI = 7
	MemoryRead             APCI = 8
	MemoryResponse         APCI = 9
	MemoryWrite            APCI = 10
	UserMessage            APCI = 11
	MaskVersionRead        APCI = 12
	MaskVersionResponse    APCI = 13
	Restart                APCI = 14
	Escape                 APCI = 15
)

// A TPDU is the transport-layer protocol data unit within a L_Data frame.
type TPDU struct {
	PacketType TPCI
	SeqNumber  uint8
	Control    uint8
	Info       APCI
	Data       []byte
}

// Errors returned from ReadTPDU
var (
	ErrDataUnitTooShort = errors.New("Data segment of the TPDU is too short")
)

// ReadFrom parses the given data in order to fill the TPDU struct.
func (tpdu *TPDU) ReadFrom(r io.Reader) error {
	var head uint8

	err := binary.ReadSequence(r, &head)
	if err != nil {
		return err
	}

	packetType := TPCI((head >> 6) & 3)
	seqNumber := (head >> 2) & 15

	switch packetType {
	case UnnumberedControlPacket, NumberedControlPacket:
		tpdu.PacketType = packetType
		tpdu.SeqNumber = seqNumber
		tpdu.Control = head & 3
		tpdu.Info = 0
		tpdu.Data = nil

		return nil

	case UnnumberedDataPacket, NumberedDataPacket:
		buffer := &bytes.Buffer{}

		// Empty the reader's remaining contents into a buffer.
		len, err := buffer.ReadFrom(r)
		if err != nil {
			return err
		} else if len < 1 {
			return ErrDataUnitTooShort
		}

		data := buffer.Bytes()

		tpdu.PacketType = packetType
		tpdu.SeqNumber = seqNumber
		tpdu.Control = 0
		tpdu.Info = APCI((head & 3) << 2 | (data[0] >> 6) & 3)
		tpdu.Data = data

		// The first 2 bits of the data contain rest of the APCI, we don't need them anymore.
		tpdu.Data[0] &= 63

		return nil
	}

	return errors.New("Unreachable")
}

// WriteTo writes the TPDU structure to the given Writer.
func (tpdu *TPDU) WriteTo(w io.Writer) error {
	headMask := byte(tpdu.PacketType & 3) << 6 | byte(tpdu.SeqNumber & 15) << 2

	switch tpdu.PacketType & 3 {
	case UnnumberedControlPacket, NumberedControlPacket:
		_, err := w.Write([]byte{headMask | byte(tpdu.Control & 3)})
		return err

	case UnnumberedDataPacket, NumberedDataPacket:
		data := make([]byte, 1, 2)
		if len(tpdu.Data) > 0 {
			data = append(data, tpdu.Data...)
		} else {
			data = append(data, 0)
		}

		data[0] |= byte(tpdu.Info >> 2) & 3
		data[1] &= 63

		_, err := w.Write(data)
		return err
	}

	return errors.New("Unreachable")
}
<|endoftext|>


<commit_before>package rtda

type OperandStack struct {
    size    uint16
    slots   []any
}

func (self *OperandStack) pushInt(val int32) {
    self.slots[self.size] = val
    self.size++
}

func (self *OperandStack) popInt() (int32) {
    return self.slots[self.size].(int32)
}

func NewOperandStack(length uint16) (*OperandStack) {
    slots := make([]any, length)
    return &OperandStack{0, slots}
}
<commit_msg>OperandStack.popInt()<commit_after>package rtda

type OperandStack struct {
    size    uint16
    slots   []any
}

func (self *OperandStack) pushInt(val int32) {
    self.slots[self.size] = val
    self.size++
}
func (self *OperandStack) popInt() (val int32) {
    val = self.slots[self.size].(int32)
    self.size--
    return
}

func NewOperandStack(length uint16) (*OperandStack) {
    slots := make([]any, length)
    return &OperandStack{0, slots}
}
<|endoftext|>


<commit_before><commit_msg>delete test data<commit_after><|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

    https://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 resources

import (
	"sort"
	"strings"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	"github.com/knative/pkg/system"
	"github.com/knative/serving/pkg/activator"
	"github.com/knative/serving/pkg/apis/networking"
	"github.com/knative/serving/pkg/apis/networking/v1alpha1"
	"github.com/knative/serving/pkg/apis/serving"
	servingv1alpha1 "github.com/knative/serving/pkg/apis/serving/v1alpha1"
	"github.com/knative/serving/pkg/reconciler"
	revisionresources "github.com/knative/serving/pkg/reconciler/v1alpha1/revision/resources"
	"github.com/knative/serving/pkg/reconciler/v1alpha1/route/resources/names"
	"github.com/knative/serving/pkg/reconciler/v1alpha1/route/traffic"
	"github.com/knative/serving/pkg/utils"
)

func isClusterLocal(r *servingv1alpha1.Route) bool {
	return strings.HasSuffix(r.Status.Domain, utils.GetClusterDomainName())
}

// MakeClusterIngress creates ClusterIngress to set up routing rules. Such ClusterIngress specifies
// which Hosts that it applies to, as well as the routing rules.
func MakeClusterIngress(r *servingv1alpha1.Route, tc *traffic.Config, ingressClass string) *v1alpha1.ClusterIngress {
	ci := &v1alpha1.ClusterIngress{
		ObjectMeta: metav1.ObjectMeta{
			// As ClusterIngress resource is cluster-scoped,
			// here we use GenerateName to avoid conflict.
			Name: names.ClusterIngress(r),
			Labels: map[string]string{
				serving.RouteLabelKey:          r.Name,
				serving.RouteNamespaceLabelKey: r.Namespace,
			},
			Annotations: r.ObjectMeta.Annotations,
		},
		Spec: makeClusterIngressSpec(r, tc.Targets),
	}
	// Set the ingress class annotation.
	if ci.ObjectMeta.Annotations == nil {
		ci.ObjectMeta.Annotations = make(map[string]string)
	}
	ci.ObjectMeta.Annotations[networking.IngressClassAnnotationKey] = ingressClass
	return ci
}

func makeClusterIngressSpec(r *servingv1alpha1.Route, targets map[string]traffic.RevisionTargets) v1alpha1.IngressSpec {
	// Domain should have been specified in route status
	// before calling this func.
	names := make([]string, 0, len(targets))
	for name := range targets {
		names = append(names, name)
	}
	// Sort the names to give things a deterministic ordering.
	sort.Strings(names)

	// The routes are matching rule based on domain name to traffic split targets.
	rules := make([]v1alpha1.ClusterIngressRule, 0, len(names))
	for _, name := range names {
		rules = append(rules, *makeClusterIngressRule(
			routeDomains(name, r), r.Namespace, targets[name]))
	}
	spec := v1alpha1.IngressSpec{
		Rules:      rules,
		Visibility: v1alpha1.IngressVisibilityExternalIP,
	}
	if isClusterLocal(r) {
		spec.Visibility = v1alpha1.IngressVisibilityClusterLocal
	}
	return spec
}

func routeDomains(targetName string, r *servingv1alpha1.Route) []string {

	domains := []string{traffic.SubrouteDomain(targetName, r.Status.Domain)}

	if targetName == traffic.DefaultTarget {
		// The default target is also referred to by its internal K8s
		// generated domain name.
		internalHost := names.K8sServiceFullname(r)
		if internalHost != "" && domains[0] != internalHost {
			domains = append(domains, internalHost)
		}
	}

	return domains

}

func makeClusterIngressRule(domains []string, ns string, targets traffic.RevisionTargets) *v1alpha1.ClusterIngressRule {
	active, inactive := targets.GroupTargets()
	// Optimistically allocate |active| elements.
	splits := make([]v1alpha1.ClusterIngressBackendSplit, 0, len(active))
	for _, t := range active {
		splits = append(splits, v1alpha1.ClusterIngressBackendSplit{
			ClusterIngressBackend: v1alpha1.ClusterIngressBackend{
				ServiceNamespace: ns,
				ServiceName:      reconciler.GetServingK8SServiceNameForObj(t.TrafficTarget.RevisionName),
				ServicePort:      intstr.FromInt(int(revisionresources.ServicePort)),
			},
			Percent: t.Percent,
		})
	}
	path := &v1alpha1.HTTPClusterIngressPath{
		Splits: splits,
		// TODO(lichuqiang): #2201, plumbing to config timeout and retries.
	}
	return &v1alpha1.ClusterIngressRule{
		Hosts: domains,
		HTTP: &v1alpha1.HTTPClusterIngressRuleValue{
			Paths: []v1alpha1.HTTPClusterIngressPath{
				*addInactive(path, ns, inactive),
			},
		},
	}
}

// addInactive constructs Splits for the inactive targets, and add into given IngressPath.
func addInactive(r *v1alpha1.HTTPClusterIngressPath, ns string, inactive traffic.RevisionTargets) *v1alpha1.HTTPClusterIngressPath {
	if len(inactive) == 0 {
		return r
	}
	totalInactivePercent := 0
	maxInactiveTarget := &inactive[0]
	for i, t := range inactive {
		totalInactivePercent += t.Percent
		if t.Percent >= maxInactiveTarget.Percent {
			maxInactiveTarget = &inactive[i]
		}
	}
	r.Splits = append(r.Splits, v1alpha1.ClusterIngressBackendSplit{
		ClusterIngressBackend: v1alpha1.ClusterIngressBackend{
			ServiceNamespace: system.Namespace(),
			ServiceName:      activator.K8sServiceName,
			ServicePort:      intstr.FromInt(int(activator.ServicePort(maxInactiveTarget.Protocol))),
		},
		Percent: totalInactivePercent,
	})
	r.AppendHeaders = map[string]string{
		activator.RevisionHeaderName:      maxInactiveTarget.RevisionName,
		activator.RevisionHeaderNamespace: ns,
	}
	return r
}
<commit_msg>Use UnionMaps for cluster ingress annotations. (#3755)<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

    https://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 resources

import (
	"sort"
	"strings"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	"github.com/knative/pkg/system"
	"github.com/knative/serving/pkg/activator"
	"github.com/knative/serving/pkg/apis/networking"
	"github.com/knative/serving/pkg/apis/networking/v1alpha1"
	"github.com/knative/serving/pkg/apis/serving"
	servingv1alpha1 "github.com/knative/serving/pkg/apis/serving/v1alpha1"
	"github.com/knative/serving/pkg/reconciler"
	revisionresources "github.com/knative/serving/pkg/reconciler/v1alpha1/revision/resources"
	"github.com/knative/serving/pkg/reconciler/v1alpha1/route/resources/names"
	"github.com/knative/serving/pkg/reconciler/v1alpha1/route/traffic"
	"github.com/knative/serving/pkg/resources"
	"github.com/knative/serving/pkg/utils"
)

func isClusterLocal(r *servingv1alpha1.Route) bool {
	return strings.HasSuffix(r.Status.Domain, utils.GetClusterDomainName())
}

// MakeClusterIngress creates ClusterIngress to set up routing rules. Such ClusterIngress specifies
// which Hosts that it applies to, as well as the routing rules.
func MakeClusterIngress(r *servingv1alpha1.Route, tc *traffic.Config, ingressClass string) *v1alpha1.ClusterIngress {
	return &v1alpha1.ClusterIngress{
		ObjectMeta: metav1.ObjectMeta{
			// As ClusterIngress resource is cluster-scoped,
			// here we use GenerateName to avoid conflict.
			Name: names.ClusterIngress(r),
			Labels: map[string]string{
				serving.RouteLabelKey:          r.Name,
				serving.RouteNamespaceLabelKey: r.Namespace,
			},
			Annotations: resources.UnionMaps(map[string]string{
				networking.IngressClassAnnotationKey: ingressClass,
			}, r.ObjectMeta.Annotations),
		},
		Spec: makeClusterIngressSpec(r, tc.Targets),
	}
}

func makeClusterIngressSpec(r *servingv1alpha1.Route, targets map[string]traffic.RevisionTargets) v1alpha1.IngressSpec {
	// Domain should have been specified in route status
	// before calling this func.
	names := make([]string, 0, len(targets))
	for name := range targets {
		names = append(names, name)
	}
	// Sort the names to give things a deterministic ordering.
	sort.Strings(names)

	// The routes are matching rule based on domain name to traffic split targets.
	rules := make([]v1alpha1.ClusterIngressRule, 0, len(names))
	for _, name := range names {
		rules = append(rules, *makeClusterIngressRule(
			routeDomains(name, r), r.Namespace, targets[name]))
	}
	spec := v1alpha1.IngressSpec{
		Rules:      rules,
		Visibility: v1alpha1.IngressVisibilityExternalIP,
	}
	if isClusterLocal(r) {
		spec.Visibility = v1alpha1.IngressVisibilityClusterLocal
	}
	return spec
}

func routeDomains(targetName string, r *servingv1alpha1.Route) []string {

	domains := []string{traffic.SubrouteDomain(targetName, r.Status.Domain)}

	if targetName == traffic.DefaultTarget {
		// The default target is also referred to by its internal K8s
		// generated domain name.
		internalHost := names.K8sServiceFullname(r)
		if internalHost != "" && domains[0] != internalHost {
			domains = append(domains, internalHost)
		}
	}

	return domains

}

func makeClusterIngressRule(domains []string, ns string, targets traffic.RevisionTargets) *v1alpha1.ClusterIngressRule {
	active, inactive := targets.GroupTargets()
	// Optimistically allocate |active| elements.
	splits := make([]v1alpha1.ClusterIngressBackendSplit, 0, len(active))
	for _, t := range active {
		splits = append(splits, v1alpha1.ClusterIngressBackendSplit{
			ClusterIngressBackend: v1alpha1.ClusterIngressBackend{
				ServiceNamespace: ns,
				ServiceName:      reconciler.GetServingK8SServiceNameForObj(t.TrafficTarget.RevisionName),
				ServicePort:      intstr.FromInt(int(revisionresources.ServicePort)),
			},
			Percent: t.Percent,
		})
	}
	path := &v1alpha1.HTTPClusterIngressPath{
		Splits: splits,
		// TODO(lichuqiang): #2201, plumbing to config timeout and retries.
	}
	return &v1alpha1.ClusterIngressRule{
		Hosts: domains,
		HTTP: &v1alpha1.HTTPClusterIngressRuleValue{
			Paths: []v1alpha1.HTTPClusterIngressPath{
				*addInactive(path, ns, inactive),
			},
		},
	}
}

// addInactive constructs Splits for the inactive targets, and add into given IngressPath.
func addInactive(r *v1alpha1.HTTPClusterIngressPath, ns string, inactive traffic.RevisionTargets) *v1alpha1.HTTPClusterIngressPath {
	if len(inactive) == 0 {
		return r
	}
	totalInactivePercent := 0
	maxInactiveTarget := &inactive[0]
	for i, t := range inactive {
		totalInactivePercent += t.Percent
		if t.Percent >= maxInactiveTarget.Percent {
			maxInactiveTarget = &inactive[i]
		}
	}
	r.Splits = append(r.Splits, v1alpha1.ClusterIngressBackendSplit{
		ClusterIngressBackend: v1alpha1.ClusterIngressBackend{
			ServiceNamespace: system.Namespace(),
			ServiceName:      activator.K8sServiceName,
			ServicePort:      intstr.FromInt(int(activator.ServicePort(maxInactiveTarget.Protocol))),
		},
		Percent: totalInactivePercent,
	})
	r.AppendHeaders = map[string]string{
		activator.RevisionHeaderName:      maxInactiveTarget.RevisionName,
		activator.RevisionHeaderNamespace: ns,
	}
	return r
}
<|endoftext|>


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

package scriptable_disk

import (
	"encoding/base64"
	"fmt"
	"os/exec"
	"strings"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/volume"
	"github.com/cnaize/kubernetes/pkg/api"
	"github.com/cnaize/kubernetes/pkg/types"
	"github.com/golang/glog"
)

// This is the primary entrypoint for volume plugins.
func ProbeVolumePlugins() []volume.VolumePlugin {
	return []volume.VolumePlugin{&scriptableDiskPlugin{nil}}
}

type scriptableDiskPlugin struct {
	host volume.VolumeHost
}

var _ volume.VolumePlugin = &scriptableDiskPlugin{}

const (
	scriptableDiskPluginName = "kubernetes.io/scriptable-disk"
)

func (plugin *scriptableDiskPlugin) Init(host volume.VolumeHost) {
	plugin.host = host
}

func (plugin *scriptableDiskPlugin) Name() string {
	return scriptableDiskPluginName
}

func (plugin *scriptableDiskPlugin) CanSupport(spec *api.Volume) bool {
	if spec.Source.ScriptableDisk != nil {
		return true
	}

	return false
}

func (plugin *scriptableDiskPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
	return &scriptablePersistentDisk{
		script:  spec.Source.ScriptableDisk.Script,
		params:  spec.Source.ScriptableDisk.Params,
		podRef:  podRef,
		volName: spec.Name,
		plugin:  plugin,
	}, nil
}

func (plugin *scriptableDiskPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
	return &scriptableDisk{
		podRef:  &api.ObjectReference{UID: podUID},
		volName: volName,
		plugin:  plugin,
	}, nil
}

type scriptableDisk struct {
	script  string
	params  string
	volName string
	podRef  *api.ObjectReference
	plugin  *scriptableDiskPlugin
}

func (sd *scriptableDisk) SetUp() error {
	return sd.SetUpAt(sd.GetPath())
}

func (sd *scriptableDisk) SetUpAt(dir string) error {
	glog.Infoln("SCIPTABLE DISK SETUPING")

	scriptParams, err := base64.StdEncoding.DecodeString(sd.params)
	if err != nil {
		return err
	}

	params := []string{"-c", sd.script}
	params = append(params, strings.Split(string(scriptParams), ";")...)

	if out, err := exec.Command("sh", params...).Output(); err != nil {
		return fmt.Errorf("can't execute script: %v\n", err)
	} else {
		glog.Infof("script finished: %v\n", string(out))
	}

	return nil
}

func (sd *scriptableDisk) GetPath() string {
	name := scriptableDiskPluginName
	return sd.plugin.host.GetPodVolumeDir(sd.podRef.UID, util.EscapeQualifiedNameForDisk(name), sd.volName)
}

func (sd *scriptableDisk) TearDown() error {
	return sd.TearDownAt(sd.GetPath())
}

func (sd *scriptableDisk) TearDownAt(dir string) error {
	return nil
}
<commit_msg>fixed scriptable disk<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scriptable_disk

import (
	"encoding/base64"
	"fmt"
	"os/exec"
	"strings"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/volume"
	"github.com/cnaize/kubernetes/pkg/api"
	"github.com/cnaize/kubernetes/pkg/types"
	"github.com/golang/glog"
)

// This is the primary entrypoint for volume plugins.
func ProbeVolumePlugins() []volume.VolumePlugin {
	return []volume.VolumePlugin{&scriptableDiskPlugin{nil}}
}

type scriptableDiskPlugin struct {
	host volume.VolumeHost
}

var _ volume.VolumePlugin = &scriptableDiskPlugin{}

const (
	scriptableDiskPluginName = "kubernetes.io/scriptable-disk"
)

func (plugin *scriptableDiskPlugin) Init(host volume.VolumeHost) {
	plugin.host = host
}

func (plugin *scriptableDiskPlugin) Name() string {
	return scriptableDiskPluginName
}

func (plugin *scriptableDiskPlugin) CanSupport(spec *api.Volume) bool {
	if spec.VolumeSource.ScriptableDisk != nil {
		return true
	}

	return false
}

func (plugin *scriptableDiskPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
	return &scriptableDisk{
		script:  spec.VolumeSource.ScriptableDisk.Script,
		params:  spec.VolumeSource.ScriptableDisk.Params,
		podRef:  podRef,
		volName: spec.Name,
		plugin:  plugin,
	}, nil
}

func (plugin *scriptableDiskPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
	return &scriptableDisk{
		podRef:  &api.ObjectReference{UID: podUID},
		volName: volName,
		plugin:  plugin,
	}, nil
}

type scriptableDisk struct {
	script  string
	params  string
	volName string
	podRef  *api.ObjectReference
	plugin  *scriptableDiskPlugin
}

func (sd *scriptableDisk) SetUp() error {
	return sd.SetUpAt(sd.GetPath())
}

func (sd *scriptableDisk) SetUpAt(dir string) error {
	glog.Infoln("SCIPTABLE DISK SETUPING")

	scriptParams, err := base64.StdEncoding.DecodeString(sd.params)
	if err != nil {
		return err
	}

	params := []string{"-c", sd.script}
	params = append(params, strings.Split(string(scriptParams), ";")...)

	if out, err := exec.Command("sh", params...).Output(); err != nil {
		return fmt.Errorf("can't execute script: %v\n", err)
	} else {
		glog.Infof("script finished: %v\n", string(out))
	}

	return nil
}

func (sd *scriptableDisk) GetPath() string {
	name := scriptableDiskPluginName
	return sd.plugin.host.GetPodVolumeDir(sd.podRef.UID, util.EscapeQualifiedNameForDisk(name), sd.volName)
}

func (sd *scriptableDisk) TearDown() error {
	return sd.TearDownAt(sd.GetPath())
}

func (sd *scriptableDisk) TearDownAt(dir string) error {
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"sync"
	"time"
)

func MustLoadCertificates(cafile string) *x509.CertPool {
	pem, err := ioutil.ReadFile(cafile)
	if err != nil {
		panic(err)
	}

	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pem) {
		panic("Failed appending certs")
	}

	return certPool
}

func MustGetTlsConfiguration(servername string, cafile string) *tls.Config {
	config := &tls.Config{}
	certPool := MustLoadCertificates(cafile)

	config.RootCAs = certPool
	config.ClientCAs = certPool

	config.ClientAuth = tls.RequireAndVerifyClientCert

	config.CipherSuites = []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}

	//Use only TLS v1.2
	config.MinVersion = tls.VersionTLS12

	//Don't allow session resumption
	config.SessionTicketsDisabled = true
	return config
}

func RandomString(strlen int) string {
	rand.Seed(time.Now().UTC().UnixNano())
	const chars = "abcdefghijklmnopqrstuvwzyz0123456789/"
	result := make([]byte, strlen)
	for i := 0; i < strlen; i++ {
		result[i] = chars[rand.Intn(len(chars))]
	}
	return string(result)
}

func DoRequest(tlsConfig *tls.Config, host string) {
	transport := &http.Transport{TLSClientConfig: tlsConfig}

	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Transport: transport,
	}

	url := fmt.Sprintf("https://ccr.%v/%v/stuff?fakeClientIpAddress=68.87.25.123", host, RandomString(23))
	req, err := http.NewRequest("GET", url, nil)

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

	req.Header.Set("Connection", "close")

	resp, err := client.Do(req)

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

	if resp != nil {
		io.Copy(ioutil.Discard, resp.Body)
		resp.Body.Close()
		if resp.StatusCode != 302 {
			fmt.Println("Received unexpected http status", resp.StatusCode)
		}
	}
}

func ExerciseDeliveryService(tlsConfig *tls.Config, host string, numRequests int, maxWorkers int) {
	fmt.Println("Sending", numRequests, "requests to", host)
	var waitGroup sync.WaitGroup

	workers := make(chan int, maxWorkers)
	start := time.Now()
	for worker := 0; worker < maxWorkers; worker++ {
		waitGroup.Add(1)

		go func(ch <-chan int) {
			defer waitGroup.Done()

			for _ = range ch {
				DoRequest(tlsConfig, host)
			}
		}(workers)
	}

	for i := 0; i < numRequests; i++ {
		if i%maxWorkers == 0 {
			fmt.Println(host, i)
		}
		time.Sleep(100 * time.Microsecond)
		workers <- i
	}
	close(workers)

	fmt.Println(host, "waiting")
	waitGroup.Wait()
	elapsed := time.Since(start)
	fmt.Println(host, "Took", elapsed)
}

func main() {
	txCountFlag := flag.Int("txcount", 100, "Number of transactions to execute per delivery service")
	workersFlag := flag.Int("workers", 10, "Number of concurrent d")
	cafileFlag := flag.String("cafile", "ca.crt", "root Certificate Authority file")

	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr, "\tloadtest")
		fmt.Fprintln(os.Stderr, "\t\t[-cafile <file name>]")
		fmt.Fprintln(os.Stderr, "\t\t[-txcount <number of transactions per delivery service>]")
		fmt.Fprintln(os.Stderr, "\t\t[-workers <number of concurrent requests per delivery service>]")
		fmt.Fprintln(os.Stderr, "\t\tmy-cdn.example.com delivery-service-1 delivery-service-2 ...")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "\tSome example locations of trusted certificate files to use for -cafile are:")
		fmt.Fprintln(os.Stderr, "/etc/ssl/certs");
		fmt.Fprintln(os.Stderr, "/etc/pki/tls/certs/ca-bundle.crt");
		fmt.Fprintln(os.Stderr, "/etc/ssl/certs/ca-bundle.crt");
		fmt.Fprintln(os.Stderr, "/etc/pki/tls/certs/ca-bundle.trust.crt");
		fmt.Fprintln(os.Stderr, "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem");
		fmt.Fprintln(os.Stderr, "/System/Library/OpenSSL");
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
	}
	flag.Parse()

	if _, err := os.Stat(*cafileFlag); os.IsNotExist(err) {
		fmt.Fprintln(os.Stderr, "Loadtest requires a root certificate authority file, by default it looks for ca.crt in the current working directory")
		fmt.Fprintln(os.Stderr)
		flag.Usage()
		os.Exit(1)
	}

	cdnDomain := flag.Args()[0]
	deliveryServices := flag.Args()[1:]

	fmt.Println(deliveryServices)

	var waitGroup sync.WaitGroup

	start := time.Now()
	for _, deliveryService := range deliveryServices {
		waitGroup.Add(1)
		go func(ds string) {
			defer waitGroup.Done()
			host := strings.Join([]string{ds, cdnDomain}, ".")
			fmt.Println(host)
			tlsConfig := MustGetTlsConfiguration(host, *cafileFlag)
			ExerciseDeliveryService(tlsConfig, host, *txCountFlag, *workersFlag)
		}(deliveryService)
	}

	waitGroup.Wait()
	elapsed := time.Since(start)
	totalRequests := *txCountFlag * len(deliveryServices)
	fmt.Println(totalRequests)
	tps := float64(totalRequests) / elapsed.Seconds()
	fmt.Println("Took", elapsed)
	fmt.Println("TPS", tps)
}
<commit_msg>Traffic Router - update usage instructions for loadtest<commit_after>package main

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"sync"
	"time"
)

func MustLoadCertificates(cafile string) *x509.CertPool {
	pem, err := ioutil.ReadFile(cafile)
	if err != nil {
		panic(err)
	}

	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pem) {
		panic("Failed appending certs")
	}

	return certPool
}

func MustGetTlsConfiguration(servername string, cafile string) *tls.Config {
	config := &tls.Config{}
	certPool := MustLoadCertificates(cafile)

	config.RootCAs = certPool
	config.ClientCAs = certPool

	config.ClientAuth = tls.RequireAndVerifyClientCert

	config.CipherSuites = []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}

	//Use only TLS v1.2
	config.MinVersion = tls.VersionTLS12

	//Don't allow session resumption
	config.SessionTicketsDisabled = true
	return config
}

func RandomString(strlen int) string {
	rand.Seed(time.Now().UTC().UnixNano())
	const chars = "abcdefghijklmnopqrstuvwzyz0123456789/"
	result := make([]byte, strlen)
	for i := 0; i < strlen; i++ {
		result[i] = chars[rand.Intn(len(chars))]
	}
	return string(result)
}

func DoRequest(tlsConfig *tls.Config, host string) {
	transport := &http.Transport{TLSClientConfig: tlsConfig}

	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Transport: transport,
	}

	url := fmt.Sprintf("https://ccr.%v/%v/stuff?fakeClientIpAddress=68.87.25.123", host, RandomString(23))
	req, err := http.NewRequest("GET", url, nil)

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

	req.Header.Set("Connection", "close")

	resp, err := client.Do(req)

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

	if resp != nil {
		io.Copy(ioutil.Discard, resp.Body)
		resp.Body.Close()
		if resp.StatusCode != 302 {
			fmt.Println("Received unexpected http status", resp.StatusCode)
		}
	}
}

func ExerciseDeliveryService(tlsConfig *tls.Config, host string, numRequests int, maxWorkers int) {
	fmt.Println("Sending", numRequests, "requests to", host)
	var waitGroup sync.WaitGroup

	workers := make(chan int, maxWorkers)
	start := time.Now()
	for worker := 0; worker < maxWorkers; worker++ {
		waitGroup.Add(1)

		go func(ch <-chan int) {
			defer waitGroup.Done()

			for _ = range ch {
				DoRequest(tlsConfig, host)
			}
		}(workers)
	}

	for i := 0; i < numRequests; i++ {
		if i%maxWorkers == 0 {
			fmt.Println(host, i)
		}
		time.Sleep(100 * time.Microsecond)
		workers <- i
	}
	close(workers)

	fmt.Println(host, "waiting")
	waitGroup.Wait()
	elapsed := time.Since(start)
	fmt.Println(host, "Took", elapsed)
}

func main() {
	txCountFlag := flag.Int("txcount", 100, "Number of transactions to execute per delivery service")
	connectionsFlag := flag.Int("connections", 10, "Number of concurrent connections")
	cafileFlag := flag.String("cafile", "ca.crt", "root Certificate Authority file")

	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "  loadtest [options] my-cdn.example.com delivery-service-1 delivery-service-2 ...")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Options:")
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Some typical locations of trusted certificate files to use for -cafile are:")
		fmt.Fprintln(os.Stderr, "\t/etc/ssl/certs");
		fmt.Fprintln(os.Stderr, "\t/etc/pki/tls/certs/ca-bundle.crt");
		fmt.Fprintln(os.Stderr, "\t/etc/ssl/certs/ca-bundle.crt");
		fmt.Fprintln(os.Stderr, "\t/etc/pki/tls/certs/ca-bundle.trust.crt");
		fmt.Fprintln(os.Stderr, "\t/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem");
		fmt.Fprintln(os.Stderr, "\t/System/Library/OpenSSL");
		fmt.Fprintln(os.Stderr)
    fmt.Fprintln(os.Stderr, "Or you could create your own self signed certificate authority and use that as your cafile");
		fmt.Fprintln(os.Stderr)
	}
	flag.Parse()

	if _, err := os.Stat(*cafileFlag); os.IsNotExist(err) {
		fmt.Fprintln(os.Stderr, "Loadtest requires a root certificate authority file, by default it looks for ca.crt in the current working directory")
		fmt.Fprintln(os.Stderr)
		flag.Usage()
		os.Exit(1)
	}

	cdnDomain := flag.Args()[0]
	deliveryServices := flag.Args()[1:]

	fmt.Println(deliveryServices)

	var waitGroup sync.WaitGroup

	start := time.Now()
	for _, deliveryService := range deliveryServices {
		waitGroup.Add(1)
		go func(ds string) {
			defer waitGroup.Done()
			host := strings.Join([]string{ds, cdnDomain}, ".")
			fmt.Println(host)
			tlsConfig := MustGetTlsConfiguration(host, *cafileFlag)
			ExerciseDeliveryService(tlsConfig, host, *txCountFlag, *connectionsFlag)
		}(deliveryService)
	}

	waitGroup.Wait()
	elapsed := time.Since(start)
	totalRequests := *txCountFlag * len(deliveryServices)
	fmt.Println(totalRequests)
	tps := float64(totalRequests) / elapsed.Seconds()
	fmt.Println("Took", elapsed)
	fmt.Println("TPS", tps)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes 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 main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.3.0"
<commit_msg>Cluster-autoscaler: bump version to 0.4.0-alpha<commit_after>/*
Copyright 2016 The Kubernetes 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 main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.4.0-alpha1"
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"os/exec"
	"strings"
	"time"
)

var charactersForRandom = []byte("1234567890abcdef")

func init() {
	rand.Seed(time.Now().UnixNano())
}

func urisFromOpts(opts GlobalOptions) map[string]string {

	uris := make(map[string]string)
	uris["primary"] = opts.Primary
	uris["introducer"] = opts.Introducer

	return uris
}

func copyToClipboard(data string) error {

	// TODO support more than OSX

	fmt.Printf("copy data: %s\n", data)

	var cmd *exec.Cmd

	if _, err := exec.LookPath("pbcopy"); err == nil {
		cmd = exec.Command("pbcopy")
	} else if _, err := exec.LookPath("tmux"); err == nil {
		cmd = exec.Command("tmux", "load-buffer", "-")
	}
	cmd.Stdin = strings.NewReader(data)

	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

func displayNotice(message string, sticky bool) error {
	fmt.Printf("display message: %s\n", message)

	var cmd *exec.Cmd

	if _, err := exec.LookPath("growlnotify"); err == nil {
		cmdParts := []string{"growlnotify", "-m", message}
		if sticky {
			cmdParts = append(cmdParts, "-s")
		}

		cmd = exec.Command(cmdParts[0], cmdParts[1:]...)
	} else if _, err := exec.LookPath("tmux"); err == nil {
		cmd = exec.Command("tmux", "display-message", message)
	}

	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

func generateRandomString(length int) string {
	random := make([]byte, length)
	for i, _ := range random {
		random[i] = charactersForRandom[rand.Intn(len(charactersForRandom))]
	}
	return string(random)
}

func generateRandomID(prefix string) string {
	return fmt.Sprintf("%s-%s", prefix, generateRandomString(12))
}
<commit_msg>clean up output, trucate long data in log<commit_after>package main

import (
	"fmt"
	"math/rand"
	"os/exec"
	"strings"
	"time"
)

var charactersForRandom = []byte("1234567890abcdef")

func init() {
	rand.Seed(time.Now().UnixNano())
}

func urisFromOpts(opts GlobalOptions) map[string]string {

	uris := make(map[string]string)
	uris["primary"] = opts.Primary
	uris["introducer"] = opts.Introducer

	return uris
}

func copyToClipboard(data string) error {

	logger.Infof("copy data: %s\n", strings.Replace(truncate(data, 30), "\n", "\\n", -1))

	var cmd *exec.Cmd

	// TODO support more than OSX and tmux
	if _, err := exec.LookPath("pbcopy"); err == nil {
		cmd = exec.Command("pbcopy")
	} else if _, err := exec.LookPath("tmux"); err == nil {
		cmd = exec.Command("tmux", "load-buffer", "-")
	}
	cmd.Stdin = strings.NewReader(data)

	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

func truncate(data string, length int) string {
	if len(data) > length {
		return fmt.Sprintf("%s (truncated)", data[0:length])
	}
	return data
}

func displayNotice(message string, sticky bool) error {
	logger.Infof("display message: %s\n", message)

	var cmd *exec.Cmd

	if _, err := exec.LookPath("growlnotify"); err == nil {
		cmdParts := []string{"growlnotify", "-m", message}
		if sticky {
			cmdParts = append(cmdParts, "-s")
		}

		cmd = exec.Command(cmdParts[0], cmdParts[1:]...)
	} else if _, err := exec.LookPath("tmux"); err == nil {
		cmd = exec.Command("tmux", "display-message", message)
	}

	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

func generateRandomString(length int) string {
	random := make([]byte, length)
	for i, _ := range random {
		random[i] = charactersForRandom[rand.Intn(len(charactersForRandom))]
	}
	return string(random)
}

func generateRandomID(prefix string) string {
	return fmt.Sprintf("%s-%s", prefix, generateRandomString(12))
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"time"
	"strings"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{}
)

func entryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}

func factoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	ds := fmt.Sprintf("%d", d)
	rs := fmt.Sprintf("%08d", r)
	rs = strings.TrimRight(rs, "0")
	if len(rs) > 0 {
		ds = ds + "."
	}
	return fmt.Sprintf("%s%s", ds, rs)
}
<commit_msg>go fmt<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"strings"
	"time"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{}
)

func entryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}

func factoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	ds := fmt.Sprintf("%d", d)
	rs := fmt.Sprintf("%08d", r)
	rs = strings.TrimRight(rs, "0")
	if len(rs) > 0 {
		ds = ds + "."
	}
	return fmt.Sprintf("%s%s", ds, rs)
}
<|endoftext|>


<commit_before>package eyego

import (
	"io"
	"bufio"
	"strconv"
	"os"
)

func EachLine(r io.Reader, f func(string) interface {}) (rv []interface {}, err error){
	br := bufio.NewReader(r)

	rv = make([]interface {}, 10)

	for {
		line, err := br.ReadString('\n')

		if line != "" {
			rv = append(rv, f(line[:len(line) - 1]))
		}

		if err != nil {
			break
		}
	}

	return rv, err
}

func Atoi(s string) (i int) {
	i, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return
}

func Abs(i int) int {
	if i < 0 {
		return -i
	}
	return i
}

func CopyFile(dst, src string) (int64, error) {
	sf, err := os.Open(src)
	if err != nil {
		return 0, err
	}
	defer sf.Close()
	df, err := os.Create(dst)
	if err != nil {
		return 0, err
	}
	defer df.Close()
	return io.Copy(df, sf)
}
<commit_msg>now trims null bytes from number conversions<commit_after>package eyego

import (
	"io"
	"bufio"
	"strconv"
	"os"
	"strings"
)

func EachLine(r io.Reader, f func(string) interface {}) (rv []interface {}, err error){
	br := bufio.NewReader(r)

	rv = make([]interface {}, 10)

	for {
		line, err := br.ReadString('\n')

		if line != "" {
			rv = append(rv, f(line[:len(line) - 1]))
		}

		if err != nil {
			break
		}
	}

	return rv, err
}

func Atoi(s string) (i int) {
	i, err := strconv.Atoi(strings.Trim(s, "\x00"));
	if err != nil {
		panic(err)
	}
	return
}

func Abs(i int) int {
	if i < 0 {
		return -i
	}
	return i
}

func CopyFile(dst, src string) (int64, error) {
	sf, err := os.Open(src)
	if err != nil {
		return 0, err
	}
	defer sf.Close()
	df, err := os.Create(dst)
	if err != nil {
		return 0, err
	}
	defer df.Close()
	return io.Copy(df, sf)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"code.cloudfoundry.org/guardian/guardiancmd"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/localip"
	"github.com/concourse/atc"
	"github.com/jessevdk/go-flags"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
)

type GardenBackend struct {
	guardiancmd.ServerCommand

	DNS DNSConfig `group:"DNS Proxy Configuration" namespace:"dns-proxy"`
}

func (cmd WorkerCommand) lessenRequirements(command *flags.Command) {
	command.FindOptionByLongName("garden-bind-port").Default = []string{"7777"}

	// configured as work-dir/depot
	command.FindOptionByLongName("garden-depot").Required = false

	// un-configure graph (default /var/gdn/graph)
	command.FindOptionByLongName("garden-graph").Required = false
	command.FindOptionByLongName("garden-graph").Default = []string{}

	// these are provided as assets embedded in the 'concourse' binary
	command.FindOptionByLongName("garden-runc-bin").Required = false
	command.FindOptionByLongName("garden-dadoo-bin").Required = false
	command.FindOptionByLongName("garden-init-bin").Required = false
	command.FindOptionByLongName("garden-nstar-bin").Required = false
	command.FindOptionByLongName("garden-tar-bin").Required = false

	// configured as work-dir/volumes
	command.FindOptionByLongName("baggageclaim-volumes").Required = false
}

func (cmd *WorkerCommand) gardenRunner(logger lager.Logger, hasAssets bool) (atc.Worker, ifrit.Runner, error) {
	err := cmd.checkRoot()
	if err != nil {
		return atc.Worker{}, nil, err
	}

	depotDir := filepath.Join(cmd.WorkDir.Path(), "depot")

	// must be readable by other users so unprivileged containers can run their
	// own `initc' process
	err = os.MkdirAll(depotDir, 0755)
	if err != nil {
		return atc.Worker{}, nil, err
	}

	cmd.Garden.Server.BindIP = guardiancmd.IPFlag(cmd.BindIP)
	cmd.Garden.Containers.Dir = depotDir

	cmd.Garden.Network.AllowHostAccess = true

	worker := atc.Worker{
		Platform: "linux",
		Tags:     cmd.Tags,
		Team:     cmd.TeamName,

		HTTPProxyURL:  cmd.HTTPProxy.String(),
		HTTPSProxyURL: cmd.HTTPSProxy.String(),
		NoProxy:       strings.Join(cmd.NoProxy, ","),
		StartTime:     time.Now().Unix(),
	}

	if hasAssets {
		cmd.Garden.Runtime.Plugin = cmd.assetPath("bin", "runc")
		cmd.Garden.Bin.Dadoo = guardiancmd.FileFlag(cmd.assetPath("bin", "dadoo"))
		cmd.Garden.Bin.Init = guardiancmd.FileFlag(cmd.assetPath("bin", "init"))
		cmd.Garden.Bin.NSTar = guardiancmd.FileFlag(cmd.assetPath("bin", "nstar"))
		cmd.Garden.Bin.Tar = guardiancmd.FileFlag(cmd.assetPath("bin", "tar"))

		iptablesDir := cmd.assetPath("iptables")
		cmd.Garden.Bin.IPTables = guardiancmd.FileFlag(filepath.Join(iptablesDir, "sbin", "iptables"))

		worker.ResourceTypes, err = cmd.extractResources(logger.Session("extract-resources"))
		if err != nil {
			return atc.Worker{}, nil, err
		}
	}

	worker.Name, err = cmd.workerName()
	if err != nil {
		return atc.Worker{}, nil, err
	}

	members := grouper.Members{
		{
			Name:   "garden-runc",
			Runner: &cmd.Garden.ServerCommand,
		},
	}

	if cmd.Garden.DNS.Enable {
		dnsProxyRunner, err := cmd.dnsProxyRunner(logger.Session("dns-proxy"))
		if err != nil {
			return atc.Worker{}, nil, err
		}

		lip, err := localip.LocalIP()
		if err != nil {
			return atc.Worker{}, nil, err
		}

		cmd.Garden.Network.AdditionalDNSServers = append(
			cmd.Garden.Network.AdditionalDNSServers,
			guardiancmd.IPFlag(net.ParseIP(lip)),
		)

		members = append(members, grouper.Member{
			Name:   "dns-proxy",
			Runner: dnsProxyRunner,
		})
	}

	return worker, grouper.NewParallel(os.Interrupt, members), nil
}

func (cmd *WorkerCommand) extractResources(logger lager.Logger) ([]atc.WorkerResourceType, error) {
	var resourceTypes []atc.WorkerResourceType

	resourcesDir := cmd.assetPath("resources")

	infos, err := ioutil.ReadDir(resourcesDir)
	if err != nil {
		logger.Error("failed-to-list-resource-assets", err)
		return nil, err
	}

	for _, info := range infos {
		resourceType := info.Name()

		workerResourceType, err := cmd.extractResource(
			logger.Session("extract", lager.Data{"resource-type": resourceType}),
			resourcesDir,
			resourceType,
		)
		if err != nil {
			logger.Error("failed-to-extract-resource", err)
			return nil, err
		}

		resourceTypes = append(resourceTypes, workerResourceType)
	}

	return resourceTypes, nil
}

func (cmd *WorkerCommand) extractResource(
	logger lager.Logger,
	resourcesDir string,
	resourceType string,
) (atc.WorkerResourceType, error) {
	resourceImagesDir := cmd.assetPath("resource-images")
	tarBin := cmd.assetPath("bin", "tar")

	archive := filepath.Join(resourcesDir, resourceType, "rootfs.tar.gz")

	extractedDir := filepath.Join(resourceImagesDir, resourceType)

	rootfsDir := filepath.Join(extractedDir, "rootfs")
	okMarker := filepath.Join(extractedDir, "ok")

	var version string
	versionFile, err := os.Open(filepath.Join(resourcesDir, resourceType, "version"))
	if err != nil {
		logger.Error("failed-to-read-version", err)
		return atc.WorkerResourceType{}, err
	}

	_, err = fmt.Fscanf(versionFile, "%s", &version)
	if err != nil {
		logger.Error("failed-to-parse-version", err)
		return atc.WorkerResourceType{}, err
	}

	defer versionFile.Close()

	var privileged bool
	_, err = os.Stat(filepath.Join(resourcesDir, resourceType, "privileged"))
	if err == nil {
		privileged = true
	}

	_, err = os.Stat(okMarker)
	if err == nil {
		logger.Info("already-extracted")
	} else {
		logger.Info("extracting")

		err := os.RemoveAll(rootfsDir)
		if err != nil {
			logger.Error("failed-to-clear-out-existing-rootfs", err)
			return atc.WorkerResourceType{}, err
		}

		err = os.MkdirAll(rootfsDir, 0755)
		if err != nil {
			logger.Error("failed-to-create-rootfs-dir", err)
			return atc.WorkerResourceType{}, err
		}

		tar := exec.Command(tarBin, "-zxf", archive, "-C", rootfsDir)

		output, err := tar.CombinedOutput()
		if err != nil {
			logger.Error("failed-to-extract-resource", err, lager.Data{
				"output": string(output),
			})
			return atc.WorkerResourceType{}, err
		}

		ok, err := os.Create(okMarker)
		if err != nil {
			logger.Error("failed-to-create-ok-marker", err)
			return atc.WorkerResourceType{}, err
		}

		err = ok.Close()
		if err != nil {
			logger.Error("failed-to-close-ok-marker", err)
			return atc.WorkerResourceType{}, err
		}
	}

	return atc.WorkerResourceType{
		Type:       resourceType,
		Image:      rootfsDir,
		Version:    version,
		Privileged: privileged,
	}, nil
}

var ErrNotRoot = errors.New("worker must be run as root")

func (cmd *WorkerCommand) checkRoot() error {
	currentUser, err := user.Current()
	if err != nil {
		return err
	}

	if currentUser.Uid != "0" {
		return ErrNotRoot
	}

	return nil
}

func (cmd *WorkerCommand) dnsProxyRunner(logger lager.Logger) (ifrit.Runner, error) {
	server, err := cmd.Garden.DNS.Server()
	if err != nil {
		return nil, err
	}

	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		server.NotifyStartedFunc = func() {
			close(ready)
			logger.Info("started")
		}

		serveErr := make(chan error, 1)

		go func() {
			serveErr <- server.ListenAndServe()
		}()

		for {
			select {
			case err := <-serveErr:
				return err
			case <-signals:
				server.Shutdown()
			}
		}
	}), nil
}
<commit_msg>fix flag for new garden command<commit_after>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"code.cloudfoundry.org/guardian/guardiancmd"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/localip"
	"github.com/concourse/atc"
	"github.com/jessevdk/go-flags"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
)

type GardenBackend struct {
	guardiancmd.ServerCommand

	DNS DNSConfig `group:"DNS Proxy Configuration" namespace:"dns-proxy"`
}

func (cmd WorkerCommand) lessenRequirements(command *flags.Command) {
	command.FindOptionByLongName("garden-bind-port").Default = []string{"7777"}

	// configured as work-dir/depot
	command.FindOptionByLongName("garden-depot").Required = false

	// un-configure graph (default /var/gdn/graph)
	command.FindOptionByLongName("garden-graph").Required = false
	command.FindOptionByLongName("garden-graph").Default = []string{}

	// these are provided as assets embedded in the 'concourse' binary
	command.FindOptionByLongName("garden-runtime-plugin").Required = false
	command.FindOptionByLongName("garden-dadoo-bin").Required = false
	command.FindOptionByLongName("garden-init-bin").Required = false
	command.FindOptionByLongName("garden-nstar-bin").Required = false
	command.FindOptionByLongName("garden-tar-bin").Required = false

	// configured as work-dir/volumes
	command.FindOptionByLongName("baggageclaim-volumes").Required = false
}

func (cmd *WorkerCommand) gardenRunner(logger lager.Logger, hasAssets bool) (atc.Worker, ifrit.Runner, error) {
	err := cmd.checkRoot()
	if err != nil {
		return atc.Worker{}, nil, err
	}

	depotDir := filepath.Join(cmd.WorkDir.Path(), "depot")

	// must be readable by other users so unprivileged containers can run their
	// own `initc' process
	err = os.MkdirAll(depotDir, 0755)
	if err != nil {
		return atc.Worker{}, nil, err
	}

	cmd.Garden.Server.BindIP = guardiancmd.IPFlag(cmd.BindIP)
	cmd.Garden.Containers.Dir = depotDir

	cmd.Garden.Network.AllowHostAccess = true

	worker := atc.Worker{
		Platform: "linux",
		Tags:     cmd.Tags,
		Team:     cmd.TeamName,

		HTTPProxyURL:  cmd.HTTPProxy.String(),
		HTTPSProxyURL: cmd.HTTPSProxy.String(),
		NoProxy:       strings.Join(cmd.NoProxy, ","),
		StartTime:     time.Now().Unix(),
	}

	if hasAssets {
		cmd.Garden.Runtime.Plugin = cmd.assetPath("bin", "runc")
		cmd.Garden.Bin.Dadoo = guardiancmd.FileFlag(cmd.assetPath("bin", "dadoo"))
		cmd.Garden.Bin.Init = guardiancmd.FileFlag(cmd.assetPath("bin", "init"))
		cmd.Garden.Bin.NSTar = guardiancmd.FileFlag(cmd.assetPath("bin", "nstar"))
		cmd.Garden.Bin.Tar = guardiancmd.FileFlag(cmd.assetPath("bin", "tar"))

		iptablesDir := cmd.assetPath("iptables")
		cmd.Garden.Bin.IPTables = guardiancmd.FileFlag(filepath.Join(iptablesDir, "sbin", "iptables"))

		worker.ResourceTypes, err = cmd.extractResources(logger.Session("extract-resources"))
		if err != nil {
			return atc.Worker{}, nil, err
		}
	}

	worker.Name, err = cmd.workerName()
	if err != nil {
		return atc.Worker{}, nil, err
	}

	members := grouper.Members{
		{
			Name:   "garden-runc",
			Runner: &cmd.Garden.ServerCommand,
		},
	}

	if cmd.Garden.DNS.Enable {
		dnsProxyRunner, err := cmd.dnsProxyRunner(logger.Session("dns-proxy"))
		if err != nil {
			return atc.Worker{}, nil, err
		}

		lip, err := localip.LocalIP()
		if err != nil {
			return atc.Worker{}, nil, err
		}

		cmd.Garden.Network.AdditionalDNSServers = append(
			cmd.Garden.Network.AdditionalDNSServers,
			guardiancmd.IPFlag(net.ParseIP(lip)),
		)

		members = append(members, grouper.Member{
			Name:   "dns-proxy",
			Runner: dnsProxyRunner,
		})
	}

	return worker, grouper.NewParallel(os.Interrupt, members), nil
}

func (cmd *WorkerCommand) extractResources(logger lager.Logger) ([]atc.WorkerResourceType, error) {
	var resourceTypes []atc.WorkerResourceType

	resourcesDir := cmd.assetPath("resources")

	infos, err := ioutil.ReadDir(resourcesDir)
	if err != nil {
		logger.Error("failed-to-list-resource-assets", err)
		return nil, err
	}

	for _, info := range infos {
		resourceType := info.Name()

		workerResourceType, err := cmd.extractResource(
			logger.Session("extract", lager.Data{"resource-type": resourceType}),
			resourcesDir,
			resourceType,
		)
		if err != nil {
			logger.Error("failed-to-extract-resource", err)
			return nil, err
		}

		resourceTypes = append(resourceTypes, workerResourceType)
	}

	return resourceTypes, nil
}

func (cmd *WorkerCommand) extractResource(
	logger lager.Logger,
	resourcesDir string,
	resourceType string,
) (atc.WorkerResourceType, error) {
	resourceImagesDir := cmd.assetPath("resource-images")
	tarBin := cmd.assetPath("bin", "tar")

	archive := filepath.Join(resourcesDir, resourceType, "rootfs.tar.gz")

	extractedDir := filepath.Join(resourceImagesDir, resourceType)

	rootfsDir := filepath.Join(extractedDir, "rootfs")
	okMarker := filepath.Join(extractedDir, "ok")

	var version string
	versionFile, err := os.Open(filepath.Join(resourcesDir, resourceType, "version"))
	if err != nil {
		logger.Error("failed-to-read-version", err)
		return atc.WorkerResourceType{}, err
	}

	_, err = fmt.Fscanf(versionFile, "%s", &version)
	if err != nil {
		logger.Error("failed-to-parse-version", err)
		return atc.WorkerResourceType{}, err
	}

	defer versionFile.Close()

	var privileged bool
	_, err = os.Stat(filepath.Join(resourcesDir, resourceType, "privileged"))
	if err == nil {
		privileged = true
	}

	_, err = os.Stat(okMarker)
	if err == nil {
		logger.Info("already-extracted")
	} else {
		logger.Info("extracting")

		err := os.RemoveAll(rootfsDir)
		if err != nil {
			logger.Error("failed-to-clear-out-existing-rootfs", err)
			return atc.WorkerResourceType{}, err
		}

		err = os.MkdirAll(rootfsDir, 0755)
		if err != nil {
			logger.Error("failed-to-create-rootfs-dir", err)
			return atc.WorkerResourceType{}, err
		}

		tar := exec.Command(tarBin, "-zxf", archive, "-C", rootfsDir)

		output, err := tar.CombinedOutput()
		if err != nil {
			logger.Error("failed-to-extract-resource", err, lager.Data{
				"output": string(output),
			})
			return atc.WorkerResourceType{}, err
		}

		ok, err := os.Create(okMarker)
		if err != nil {
			logger.Error("failed-to-create-ok-marker", err)
			return atc.WorkerResourceType{}, err
		}

		err = ok.Close()
		if err != nil {
			logger.Error("failed-to-close-ok-marker", err)
			return atc.WorkerResourceType{}, err
		}
	}

	return atc.WorkerResourceType{
		Type:       resourceType,
		Image:      rootfsDir,
		Version:    version,
		Privileged: privileged,
	}, nil
}

var ErrNotRoot = errors.New("worker must be run as root")

func (cmd *WorkerCommand) checkRoot() error {
	currentUser, err := user.Current()
	if err != nil {
		return err
	}

	if currentUser.Uid != "0" {
		return ErrNotRoot
	}

	return nil
}

func (cmd *WorkerCommand) dnsProxyRunner(logger lager.Logger) (ifrit.Runner, error) {
	server, err := cmd.Garden.DNS.Server()
	if err != nil {
		return nil, err
	}

	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		server.NotifyStartedFunc = func() {
			close(ready)
			logger.Info("started")
		}

		serveErr := make(chan error, 1)

		go func() {
			serveErr <- server.ListenAndServe()
		}()

		for {
			select {
			case err := <-serveErr:
				return err
			case <-signals:
				server.Shutdown()
			}
		}
	}), nil
}
<|endoftext|>