<commit_before>package fission

import (
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/fission/fission-workflows/pkg/fnenv"
	"github.com/fission/fission-workflows/pkg/types/typedvalues/httpconv"
	"github.com/fission/fission-workflows/pkg/types/validate"
	"github.com/sirupsen/logrus"

	"github.com/fission/fission-workflows/pkg/types"
	"github.com/fission/fission-workflows/pkg/types/typedvalues"

	executor "github.com/fission/fission/executor/client"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	Name = "fission"
)

var log = logrus.WithField("component", "fnenv.fission")

// FunctionEnv adapts the Fission platform to the function execution runtime. This allows the workflow engine
// to invoke Fission functions.
type FunctionEnv struct {
	executor         *executor.Client
	routerURL        string
	timedExecService *timedExecPool
}

const (
	defaultHTTPMethod = http.MethodPost
	defaultProtocol   = "http"
	provisionDuration = time.Duration(500) - time.Millisecond
)

func NewFunctionEnv(executor *executor.Client, routerURL string) *FunctionEnv {
	return &FunctionEnv{
		executor:         executor,
		routerURL:        routerURL,
		timedExecService: newTimedExecPool(),
	}
}

// Invoke executes the task in a blocking way.
//
// spec contains the complete configuration needed for the execution.
// It returns the TaskInvocationStatus with a completed (FINISHED, FAILED, ABORTED) status.
// An error is returned only when error occurs outside of the runtime's control.
func (fe *FunctionEnv) Invoke(spec *types.TaskInvocationSpec) (*types.TaskInvocationStatus, error) {
	ctxLog := log.WithField("fn", spec.FnRef)
	if err := validate.TaskInvocationSpec(spec); err != nil {
		return nil, err
	}
	fnRef := *spec.FnRef

	// Construct request and add body
	url := fe.createRouterURL(fnRef)
	req, err := http.NewRequest(defaultHTTPMethod, url, nil)
	if err != nil {
		panic(fmt.Errorf("failed to create request for '%v': %v", url, err))
	}
	// Map task inputs to request
	err = httpconv.FormatRequest(spec.Inputs, req)
	if err != nil {
		return nil, err
	}

	// Perform request
	timeStart := time.Now()
	fnenv.FnActive.WithLabelValues(Name).Inc()
	defer fnenv.FnExecTime.WithLabelValues(Name).Observe(float64(time.Since(timeStart)))
	ctxLog.Infof("Invoking Fission function: '%v'.", req.URL)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error for reqUrl '%v': %v", url, err)
	}
	fnenv.FnActive.WithLabelValues(Name).Dec()
	fnenv.FnActive.WithLabelValues(Name).Inc()

	// Parse output
	output, err := httpconv.ParseBody(resp.Body, resp.Header.Get("Content-Type"))
	if err != nil {
		return nil, fmt.Errorf("failed to parse output: %v", err)
	}

	ctxLog.Infof("[%s][status]: %v", fnRef.ID, resp.StatusCode)
	ctxLog.Infof("[%s][Content-Type]: %v ", fnRef.ID, resp.Header.Get("Content-Type"))
	ctxLog.Infof("[%s][output]: '%s'", fnRef.ID, typedvalues.MustFormat(&output))

	// Determine status of the task invocation
	if resp.StatusCode >= 400 {
		msg, _ := typedvalues.Format(&output)
		ctxLog.Warnf("[%s] Failed %v: %v", resp.StatusCode, msg)
		return &types.TaskInvocationStatus{
			Status: types.TaskInvocationStatus_FAILED,
			Error: &types.Error{
				Message: fmt.Sprintf("fission function error: %v", msg),
			},
		}, nil
	}

	return &types.TaskInvocationStatus{
		Status: types.TaskInvocationStatus_SUCCEEDED,
		Output: &output,
	}, nil
}

// Notify signals the Fission runtime that a function request is expected at a specific time.
func (fe *FunctionEnv) Notify(fn types.FnRef, expectedAt time.Time) error {
	reqURL, err := fe.getFnURL(fn)
	if err != nil {
		return err
	}

	// For this now assume a standard cold start delay; use profiling to provide a better estimate.
	execAt := expectedAt.Add(-provisionDuration)

	// Tap the Fission function at the right time
	fe.timedExecService.Submit(func() {
		log.WithField("fn", fn).Infof("Tapping Fission function: %v", reqURL)
		fe.executor.TapService(reqURL)
	}, execAt)
	return nil
}

func (fe *FunctionEnv) getFnURL(fn types.FnRef) (*url.URL, error) {
	meta := createFunctionMeta(fn)
	serviceURL, err := fe.executor.GetServiceForFunction(meta)
	if err != nil {
		log.WithFields(logrus.Fields{
			"err":  err,
			"meta": meta,
		}).Error("Fission function could not be found!")
		return nil, err
	}
	rawURL := fmt.Sprintf("%s://%s", defaultProtocol, serviceURL)
	reqURL, err := url.Parse(rawURL)
	if err != nil {
		logrus.Errorf("Failed to parse url: '%v'", rawURL)
		panic(err)
	}
	return reqURL, nil
}

func createFunctionMeta(fn types.FnRef) *metav1.ObjectMeta {

	return &metav1.ObjectMeta{
		Name:      fn.ID,
		Namespace: metav1.NamespaceDefault,
	}
}

func (fe *FunctionEnv) createRouterURL(fn types.FnRef) string {
	if fn.Namespace == metav1.NamespaceDefault {
		return fe.routerURL + "/fission-function/" + fn.ID
	}

	return fe.routerURL + "/fission-function/" + fn.Namespace + "/" + fn.ID
}
<commit_msg>close response body<commit_after>package fission

import (
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/fission/fission-workflows/pkg/fnenv"
	"github.com/fission/fission-workflows/pkg/types/typedvalues/httpconv"
	"github.com/fission/fission-workflows/pkg/types/validate"
	"github.com/sirupsen/logrus"

	"github.com/fission/fission-workflows/pkg/types"
	"github.com/fission/fission-workflows/pkg/types/typedvalues"

	executor "github.com/fission/fission/executor/client"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	Name = "fission"
)

var log = logrus.WithField("component", "fnenv.fission")

// FunctionEnv adapts the Fission platform to the function execution runtime. This allows the workflow engine
// to invoke Fission functions.
type FunctionEnv struct {
	executor         *executor.Client
	routerURL        string
	timedExecService *timedExecPool
}

const (
	defaultHTTPMethod = http.MethodPost
	defaultProtocol   = "http"
	provisionDuration = time.Duration(500) - time.Millisecond
)

func NewFunctionEnv(executor *executor.Client, routerURL string) *FunctionEnv {
	return &FunctionEnv{
		executor:         executor,
		routerURL:        routerURL,
		timedExecService: newTimedExecPool(),
	}
}

// Invoke executes the task in a blocking way.
//
// spec contains the complete configuration needed for the execution.
// It returns the TaskInvocationStatus with a completed (FINISHED, FAILED, ABORTED) status.
// An error is returned only when error occurs outside of the runtime's control.
func (fe *FunctionEnv) Invoke(spec *types.TaskInvocationSpec) (*types.TaskInvocationStatus, error) {
	ctxLog := log.WithField("fn", spec.FnRef)
	if err := validate.TaskInvocationSpec(spec); err != nil {
		return nil, err
	}
	fnRef := *spec.FnRef

	// Construct request and add body
	url := fe.createRouterURL(fnRef)
	req, err := http.NewRequest(defaultHTTPMethod, url, nil)
	if err != nil {
		panic(fmt.Errorf("failed to create request for '%v': %v", url, err))
	}
	// Map task inputs to request
	err = httpconv.FormatRequest(spec.Inputs, req)
	if err != nil {
		return nil, err
	}

	// Perform request
	timeStart := time.Now()
	fnenv.FnActive.WithLabelValues(Name).Inc()
	defer fnenv.FnExecTime.WithLabelValues(Name).Observe(float64(time.Since(timeStart)))
	ctxLog.Infof("Invoking Fission function: '%v'.", req.URL)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error for reqUrl '%v': %v", url, err)
	}
	defer resp.Body.Close()

	fnenv.FnActive.WithLabelValues(Name).Dec()
	fnenv.FnActive.WithLabelValues(Name).Inc()

	// Parse output
	output, err := httpconv.ParseBody(resp.Body, resp.Header.Get("Content-Type"))
	if err != nil {
		return nil, fmt.Errorf("failed to parse output: %v", err)
	}

	ctxLog.Infof("[%s][status]: %v", fnRef.ID, resp.StatusCode)
	ctxLog.Infof("[%s][Content-Type]: %v ", fnRef.ID, resp.Header.Get("Content-Type"))
	ctxLog.Infof("[%s][output]: '%s'", fnRef.ID, typedvalues.MustFormat(&output))

	// Determine status of the task invocation
	if resp.StatusCode >= 400 {
		msg, _ := typedvalues.Format(&output)
		ctxLog.Warnf("[%s] Failed %v: %v", resp.StatusCode, msg)
		return &types.TaskInvocationStatus{
			Status: types.TaskInvocationStatus_FAILED,
			Error: &types.Error{
				Message: fmt.Sprintf("fission function error: %v", msg),
			},
		}, nil
	}

	return &types.TaskInvocationStatus{
		Status: types.TaskInvocationStatus_SUCCEEDED,
		Output: &output,
	}, nil
}

// Notify signals the Fission runtime that a function request is expected at a specific time.
func (fe *FunctionEnv) Notify(fn types.FnRef, expectedAt time.Time) error {
	reqURL, err := fe.getFnURL(fn)
	if err != nil {
		return err
	}

	// For this now assume a standard cold start delay; use profiling to provide a better estimate.
	execAt := expectedAt.Add(-provisionDuration)

	// Tap the Fission function at the right time
	fe.timedExecService.Submit(func() {
		log.WithField("fn", fn).Infof("Tapping Fission function: %v", reqURL)
		fe.executor.TapService(reqURL)
	}, execAt)
	return nil
}

func (fe *FunctionEnv) getFnURL(fn types.FnRef) (*url.URL, error) {
	meta := createFunctionMeta(fn)
	serviceURL, err := fe.executor.GetServiceForFunction(meta)
	if err != nil {
		log.WithFields(logrus.Fields{
			"err":  err,
			"meta": meta,
		}).Error("Fission function could not be found!")
		return nil, err
	}
	rawURL := fmt.Sprintf("%s://%s", defaultProtocol, serviceURL)
	reqURL, err := url.Parse(rawURL)
	if err != nil {
		logrus.Errorf("Failed to parse url: '%v'", rawURL)
		panic(err)
	}
	return reqURL, nil
}

func createFunctionMeta(fn types.FnRef) *metav1.ObjectMeta {

	return &metav1.ObjectMeta{
		Name:      fn.ID,
		Namespace: metav1.NamespaceDefault,
	}
}

func (fe *FunctionEnv) createRouterURL(fn types.FnRef) string {
	if fn.Namespace == metav1.NamespaceDefault {
		return fe.routerURL + "/fission-function/" + fn.ID
	}

	return fe.routerURL + "/fission-function/" + fn.Namespace + "/" + fn.ID
}
<|endoftext|>


<commit_before>package myslave

import (
	"encoding/json"
	"strings"
	"time"

	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/golib/sync2"
	zklib "github.com/samuel/go-zookeeper/zk"
)

var _ positioner = &positionerZk{}

type positionerZk struct {
	File   string `json:"file"`
	Offset uint32 `json:"offset"`
	Owner  string `json:"owner"`

	zkzone        *zk.ZkZone
	masterAddr    string
	birthCry      sync2.AtomicBool
	interval      time.Duration
	lastCommitted time.Time

	posPath string // cache
}

func newPositionerZk(zkzone *zk.ZkZone, masterAddr string, interval time.Duration) *positionerZk {
	return &positionerZk{
		masterAddr: masterAddr,
		interval:   interval,
		posPath:    posPath(masterAddr),
		zkzone:     zkzone,
		Owner:      myNode(),
	}
}

func (z *positionerZk) MarkAsProcessed(file string, offset uint32) error {
	z.File = file
	z.Offset = offset
	z.birthCry.Set(true)

	now := time.Now()
	if now.Sub(z.lastCommitted) > z.interval {
		// real commit
		data, _ := json.Marshal(z)
		var err error
		if _, err = z.zkzone.Conn().Set(z.posPath, data, -1); err == zklib.ErrNoNode {
			_, err = z.zkzone.Conn().Create(z.posPath, data, 0, zklib.WorldACL(zklib.PermAll))
		}

		z.lastCommitted = now
		return err
	}

	return nil
}

func (z *positionerZk) Flush() (err error) {
	if !z.birthCry.Get() {
		return
	}

	data, _ := json.Marshal(z)
	if _, err = z.zkzone.Conn().Set(z.posPath, data, -1); err == zklib.ErrNoNode {
		_, err = z.zkzone.Conn().Create(z.posPath, data, 0, zklib.WorldACL(zklib.PermAll))
	}

	z.lastCommitted = time.Now() // FIXME race condition with MarkAsProcessed()
	return
}

func (z *positionerZk) Committed() (file string, offset uint32, err error) {
	var data []byte
	data, _, err = z.zkzone.Conn().Get(z.posPath)
	if err != nil {
		if err == zklib.ErrNoNode {
			data, _ = json.Marshal(z)
			_, err = z.zkzone.Conn().Create(z.posPath, data, 0, zklib.WorldACL(zklib.PermAll))
		}

		return
	}

	if len(strings.TrimSpace(string(data))) == 0 {
		// empty data, return default position
		return
	}

	if err = json.Unmarshal(data, z); err != nil {
		panic(err)
	}

	file = z.File
	offset = z.Offset
	z.Owner = myNode()
	return
}
<commit_msg>remove dup code<commit_after>package myslave

import (
	"encoding/json"
	"strings"
	"time"

	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/golib/sync2"
	zklib "github.com/samuel/go-zookeeper/zk"
)

var _ positioner = &positionerZk{}

type positionerZk struct {
	File   string `json:"file"`
	Offset uint32 `json:"offset"`
	Owner  string `json:"owner"`

	zkzone        *zk.ZkZone
	masterAddr    string
	birthCry      sync2.AtomicBool
	interval      time.Duration
	lastCommitted time.Time

	posPath string // cache
}

func newPositionerZk(zkzone *zk.ZkZone, masterAddr string, interval time.Duration) *positionerZk {
	return &positionerZk{
		masterAddr: masterAddr,
		interval:   interval,
		posPath:    posPath(masterAddr),
		zkzone:     zkzone,
		Owner:      myNode(),
	}
}

func (z *positionerZk) MarkAsProcessed(file string, offset uint32) error {
	z.File = file
	z.Offset = offset
	z.birthCry.Set(true)

	now := time.Now()
	if now.Sub(z.lastCommitted) > z.interval {
		return z.Flush()
	}

	return nil
}

func (z *positionerZk) Flush() (err error) {
	if !z.birthCry.Get() {
		return
	}

	data, _ := json.Marshal(z)
	if _, err = z.zkzone.Conn().Set(z.posPath, data, -1); err == zklib.ErrNoNode {
		_, err = z.zkzone.Conn().Create(z.posPath, data, 0, zklib.WorldACL(zklib.PermAll))
	}

	z.lastCommitted = time.Now() // FIXME race condition with MarkAsProcessed()
	return
}

func (z *positionerZk) Committed() (file string, offset uint32, err error) {
	var data []byte
	data, _, err = z.zkzone.Conn().Get(z.posPath)
	if err != nil {
		if err == zklib.ErrNoNode {
			data, _ = json.Marshal(z)
			_, err = z.zkzone.Conn().Create(z.posPath, data, 0, zklib.WorldACL(zklib.PermAll))
		}

		return
	}

	if len(strings.TrimSpace(string(data))) == 0 {
		// empty data, return default position
		return
	}

	if err = json.Unmarshal(data, z); err != nil {
		panic(err)
	}

	file = z.File
	offset = z.Offset
	z.Owner = myNode()
	return
}
<|endoftext|>


<commit_before>package netutils

import (
	"fmt"
	"net"
)

type IPAllocator struct {
	network  *net.IPNet
	allocMap map[string]bool
}

func NewIPAllocator(network string) (*IPAllocator, error) {
	_, netIP, err := net.ParseCIDR(network)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse network address: %q", network)
	}

	amap := make(map[string]bool)
	return &IPAllocator{network: netIP, allocMap: amap}, nil
}

func (ipa *IPAllocator) GetIP() (net.IP, error) {
	return ipa.network.IP, nil
}
<commit_msg>Add IP Allocator.<commit_after>package netutils

import (
	"fmt"
	"net"
)

type IPAllocator struct {
	network  *net.IPNet
	allocMap map[string]bool
}

func NewIPAllocator(network string, inUse []string) (*IPAllocator, error) {
	_, netIP, err := net.ParseCIDR(network)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse network address: %q", network)
	}

	amap := make(map[string]bool)
	for _, netStr := range inUse {
		_, nIp, err := net.ParseCIDR(netStr)
		if err != nil {
			fmt.Println("Failed to parse network address: ", netStr)
			continue
		}
		if !netIP.Contains(nIp.IP) {
			fmt.Println("Provided subnet doesn't belong to network: ", nIp)
			continue
		}
		amap[netStr] = true
	}

	// Add the network address to the map
	amap[netIP.String()] = true
	return &IPAllocator{network: netIP, allocMap: amap}, nil
}

func (ipa *IPAllocator) GetIP() (*net.IPNet, error) {
	var (
		numIPs    uint32
		numIPBits uint
	)
	baseipu := IPToUint32(ipa.network.IP)
	netMaskSize, _ := ipa.network.Mask.Size()
	numIPBits = 32 - uint(netMaskSize)
	numIPs = 1 << numIPBits

	var i uint32
	// We exclude the last address as it is reserved for broadcast
	for i = 0; i < numIPs-1; i++ {
		ipu := baseipu | i
		genIP := &net.IPNet{IP: Uint32ToIP(ipu), Mask: net.CIDRMask(netMaskSize, 32)}
		if !ipa.allocMap[genIP.String()] {
			ipa.allocMap[genIP.String()] = true
			return genIP, nil
		}
	}

	return nil, fmt.Errorf("No IPs available.")
}

func (ipa *IPAllocator) ReleaseIP(ip *net.IPNet) error {
	if !ipa.network.Contains(ip.IP) {
		return fmt.Errorf("Provided IP %v doesn't belong to the network %v.", ip, ipa.network)
	}

	ipStr := ip.String()
	if !ipa.allocMap[ipStr] {
		return fmt.Errorf("Provided IP %v is already available.", ip)
	}

	ipa.allocMap[ipStr] = false

	return nil
}
<|endoftext|>


<commit_before>package provider

import (
	"database/sql"
	"errors"
)

var (
	ErrProviderNotFound = errors.New("provider not found")
)

const selectProvider = `
SELECT
	id,
	name
FROM provider
`

const selectProviderByID = selectProvider + `
WHERE
	id = ?
`

func scanSingleRow(row *sql.Row) (Provider, error) {
	p := Provider{}
	err := row.Scan(&p.ID, &p.Name)
	if err != nil {
		if err == sql.ErrNoRows {
			return p, ErrProviderNotFound
		}
		return p, err
	}
	return p, nil
}

func ProviderByIDTx(db *sql.Tx, id int64) (Provider, error) {
	row := db.QueryRow(selectProviderByID, id)
	return scanSingleRow(row)
}
<commit_msg>add provider by id on sql.DB<commit_after>package provider

import (
	"database/sql"
	"errors"
)

var (
	ErrProviderNotFound = errors.New("provider not found")
)

const selectProvider = `
SELECT
	id,
	name
FROM provider
`

const selectProviderByID = selectProvider + `
WHERE
	id = ?
`

func scanSingleRow(row *sql.Row) (Provider, error) {
	p := Provider{}
	err := row.Scan(&p.ID, &p.Name)
	if err != nil {
		if err == sql.ErrNoRows {
			return p, ErrProviderNotFound
		}
		return p, err
	}
	return p, nil
}

func ProviderByIDDB(db *sql.DB, id int64) (Provider, error) {
	row := db.QueryRow(selectProviderByID, id)
	return scanSingleRow(row)
}

func ProviderByIDTx(db *sql.Tx, id int64) (Provider, error) {
	row := db.QueryRow(selectProviderByID, id)
	return scanSingleRow(row)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 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.
*/

// nolint[lll]
package promobot

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"

	"golang.org/x/xerrors"

	// TODO: Use k/release/pkg/log instead
	"k8s.io/klog/v2"
	api "k8s.io/release/pkg/api/files"
	"k8s.io/release/pkg/filepromoter"
)

// PromoteFilesOptions holds the flag-values for a file promotion
type PromoteFilesOptions struct {
	// FilestoresPath is the path to the manifest file containing the filestores section
	FilestoresPath string

	// FilesPath specifies a path to manifest files containing the files section.
	FilesPath string

	// DryRun (if set) will not perform operations, but print them instead
	DryRun bool

	// UseServiceAccount must be true, for service accounts to be used
	// This gives some protection against a hostile manifest.
	UseServiceAccount bool

	// Out is the destination for "normal" output (such as dry-run)
	Out io.Writer
}

// PopulateDefaults sets the default values for PromoteFilesOptions
func (o *PromoteFilesOptions) PopulateDefaults() {
	o.DryRun = true
	o.UseServiceAccount = false
	o.Out = os.Stdout
}

// RunPromoteFiles executes a file promotion command
// nolint[gocyclo]
func RunPromoteFiles(ctx context.Context, options PromoteFilesOptions) error {
	manifest, err := ReadManifest(options)
	if err != nil {
		return err
	}

	if options.DryRun {
		fmt.Fprintf(
			options.Out,
			"********** START (DRY RUN) **********\n")
	} else {
		fmt.Fprintf(
			options.Out,
			"********** START **********\n")
	}

	promoter := &filepromoter.ManifestPromoter{
		Manifest:          manifest,
		UseServiceAccount: options.UseServiceAccount,
	}

	ops, err := promoter.BuildOperations(ctx)
	if err != nil {
		return fmt.Errorf(
			"error building operations: %v",
			err)
	}

	// So that we can support future parallel execution, an error
	// in one operation does not prevent us attempting the
	// remaining operations
	var errors []error
	for _, op := range ops {
		if _, err := fmt.Fprintf(options.Out, "%v\n", op); err != nil {
			errors = append(errors, fmt.Errorf(
				"error writing to output: %v", err))
		}

		if !options.DryRun {
			if err := op.Run(ctx); err != nil {
				klog.Warningf("error copying file: %v", err)
				errors = append(errors, err)
			}
		}
	}

	if len(errors) != 0 {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED WITH ERRORS **********\n")
		for _, err := range errors {
			fmt.Fprintf(options.Out, "%v\n", err)
		}

		return errors[0]
	}

	if options.DryRun {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED (DRY RUN) **********\n")
	} else {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED **********\n")
	}

	return nil
}

// ReadManifest reads a manifest.
func ReadManifest(options PromoteFilesOptions) (*api.Manifest, error) {
	merged := &api.Manifest{}

	filestores, err := readFilestores(options.FilestoresPath)
	if err != nil {
		return nil, err
	}
	merged.Filestores = filestores

	files, err := readFiles(options.FilesPath)
	if err != nil {
		return nil, err
	}
	merged.Files = files

	// Validate the merged manifest
	if err := merged.Validate(); err != nil {
		return nil, fmt.Errorf("error validating merged manifest: %v", err)
	}

	return merged, nil
}

// readFilestores reads a filestores manifest
func readFilestores(p string) ([]api.Filestore, error) {
	if p == "" {
		return nil, fmt.Errorf("FilestoresPath is required")
	}

	b, err := ioutil.ReadFile(p)
	if err != nil {
		return nil, fmt.Errorf("error reading manifest %q: %v", p, err)
	}

	manifest, err := api.ParseManifest(b)
	if err != nil {
		return nil, fmt.Errorf("error parsing manifest %q: %v", p, err)
	}

	if len(manifest.Files) != 0 {
		return nil, xerrors.Errorf(
			"files should not be present in filestore manifest %q",
			p)
	}

	return manifest.Filestores, nil
}

// readFiles reads and merges the file manifests from the file or directory filesPath
func readFiles(filesPath string) ([]api.File, error) {
	// We first list and sort the paths, for a consistent ordering
	var paths []string
	err := filepath.Walk(filesPath, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		paths = append(paths, p)
		return nil
	})
	if err != nil {
		return nil, xerrors.Errorf("error listing file manifests: %w", err)
	}

	sort.Strings(paths)

	var files []api.File
	for _, p := range paths {
		b, err := ioutil.ReadFile(p)
		if err != nil {
			return nil, xerrors.Errorf("error reading file %q: %w", p, err)
		}

		manifest, err := api.ParseManifest(b)
		if err != nil {
			return nil, xerrors.Errorf("error parsing manifest %q: %v", p, err)
		}

		if len(manifest.Filestores) != 0 {
			return nil, xerrors.Errorf("filestores should not be present in manifest %q", p)
		}

		files = append(files, manifest.Files...)
	}

	return files, nil
}
<commit_msg>promobot: replace klog to use logrus<commit_after>/*
Copyright 2019 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.
*/

// nolint[lll]
package promobot

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"

	"github.com/sirupsen/logrus"
	"golang.org/x/xerrors"

	api "k8s.io/release/pkg/api/files"
	"k8s.io/release/pkg/filepromoter"
)

// PromoteFilesOptions holds the flag-values for a file promotion
type PromoteFilesOptions struct {
	// FilestoresPath is the path to the manifest file containing the filestores section
	FilestoresPath string

	// FilesPath specifies a path to manifest files containing the files section.
	FilesPath string

	// DryRun (if set) will not perform operations, but print them instead
	DryRun bool

	// UseServiceAccount must be true, for service accounts to be used
	// This gives some protection against a hostile manifest.
	UseServiceAccount bool

	// Out is the destination for "normal" output (such as dry-run)
	Out io.Writer
}

// PopulateDefaults sets the default values for PromoteFilesOptions
func (o *PromoteFilesOptions) PopulateDefaults() {
	o.DryRun = true
	o.UseServiceAccount = false
	o.Out = os.Stdout
}

// RunPromoteFiles executes a file promotion command
// nolint[gocyclo]
func RunPromoteFiles(ctx context.Context, options PromoteFilesOptions) error {
	manifest, err := ReadManifest(options)
	if err != nil {
		return err
	}

	if options.DryRun {
		fmt.Fprintf(
			options.Out,
			"********** START (DRY RUN) **********\n")
	} else {
		fmt.Fprintf(
			options.Out,
			"********** START **********\n")
	}

	promoter := &filepromoter.ManifestPromoter{
		Manifest:          manifest,
		UseServiceAccount: options.UseServiceAccount,
	}

	ops, err := promoter.BuildOperations(ctx)
	if err != nil {
		return fmt.Errorf(
			"error building operations: %v",
			err)
	}

	// So that we can support future parallel execution, an error
	// in one operation does not prevent us attempting the
	// remaining operations
	var errors []error
	for _, op := range ops {
		if _, err := fmt.Fprintf(options.Out, "%v\n", op); err != nil {
			errors = append(errors, fmt.Errorf(
				"error writing to output: %v", err))
		}

		if !options.DryRun {
			if err := op.Run(ctx); err != nil {
				logrus.Warnf("error copying file: %v", err)
				errors = append(errors, err)
			}
		}
	}

	if len(errors) != 0 {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED WITH ERRORS **********\n")
		for _, err := range errors {
			fmt.Fprintf(options.Out, "%v\n", err)
		}

		return errors[0]
	}

	if options.DryRun {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED (DRY RUN) **********\n")
	} else {
		fmt.Fprintf(
			options.Out,
			"********** FINISHED **********\n")
	}

	return nil
}

// ReadManifest reads a manifest.
func ReadManifest(options PromoteFilesOptions) (*api.Manifest, error) {
	merged := &api.Manifest{}

	filestores, err := readFilestores(options.FilestoresPath)
	if err != nil {
		return nil, err
	}
	merged.Filestores = filestores

	files, err := readFiles(options.FilesPath)
	if err != nil {
		return nil, err
	}
	merged.Files = files

	// Validate the merged manifest
	if err := merged.Validate(); err != nil {
		return nil, fmt.Errorf("error validating merged manifest: %v", err)
	}

	return merged, nil
}

// readFilestores reads a filestores manifest
func readFilestores(p string) ([]api.Filestore, error) {
	if p == "" {
		return nil, fmt.Errorf("FilestoresPath is required")
	}

	b, err := ioutil.ReadFile(p)
	if err != nil {
		return nil, fmt.Errorf("error reading manifest %q: %v", p, err)
	}

	manifest, err := api.ParseManifest(b)
	if err != nil {
		return nil, fmt.Errorf("error parsing manifest %q: %v", p, err)
	}

	if len(manifest.Files) != 0 {
		return nil, xerrors.Errorf(
			"files should not be present in filestore manifest %q",
			p)
	}

	return manifest.Filestores, nil
}

// readFiles reads and merges the file manifests from the file or directory filesPath
func readFiles(filesPath string) ([]api.File, error) {
	// We first list and sort the paths, for a consistent ordering
	var paths []string
	err := filepath.Walk(filesPath, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		paths = append(paths, p)
		return nil
	})
	if err != nil {
		return nil, xerrors.Errorf("error listing file manifests: %w", err)
	}

	sort.Strings(paths)

	var files []api.File
	for _, p := range paths {
		b, err := ioutil.ReadFile(p)
		if err != nil {
			return nil, xerrors.Errorf("error reading file %q: %w", p, err)
		}

		manifest, err := api.ParseManifest(b)
		if err != nil {
			return nil, xerrors.Errorf("error parsing manifest %q: %v", p, err)
		}

		if len(manifest.Filestores) != 0 {
			return nil, xerrors.Errorf("filestores should not be present in manifest %q", p)
		}

		files = append(files, manifest.Files...)
	}

	return files, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative Authors

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

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

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

package reconciler

import (
	"context"

	"k8s.io/client-go/tools/cache"
	"knative.dev/eventing-prometheus/pkg/apis/sources/v1alpha1"
	"knative.dev/eventing/pkg/reconciler/source"
	"knative.dev/pkg/configmap"
	"knative.dev/pkg/controller"
	"knative.dev/pkg/logging"
	"knative.dev/pkg/resolver"

	prometheusinformer "knative.dev/eventing-prometheus/pkg/client/injection/informers/sources/v1alpha1/prometheussource"
	promreconciler "knative.dev/eventing-prometheus/pkg/client/injection/reconciler/sources/v1alpha1/prometheussource"
	kubeclient "knative.dev/pkg/client/injection/kube/client"
	deploymentinformer "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment"
)

const (
	// controllerAgentName is the string used by this controller to identify
	// itself when creating events.
	controllerAgentName = "prometheus-source-controller"
)

// NewController initializes the controller and is called by the generated code
// Registers event handlers to enqueue events
func NewController(
	ctx context.Context,
	cmw configmap.Watcher,
) *controller.Impl {
	deploymentInformer := deploymentinformer.Get(ctx)
	prometheusSourceInformer := prometheusinformer.Get(ctx)

	r := &Reconciler{
		kubeClientSet:    kubeclient.Get(ctx),
		deploymentLister: deploymentInformer.Lister(),
		configs:          source.WatchConfigurations(ctx, controllerAgentName, cmw),
	}
	impl := promreconciler.NewImpl(ctx, r)
	r.sinkResolver = resolver.NewURIResolver(ctx, impl.EnqueueKey)

	logging.FromContext(ctx).Info("Setting up event handlers")
	prometheusSourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))

	deploymentInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
		FilterFunc: controller.FilterControllerGK(v1alpha1.Kind("PrometheusSource")),
		Handler:    controller.HandleAll(impl.EnqueueControllerOf),
	})

	return impl
}
<commit_msg>Use `controller.Impl` tracker and cleanups (#141)<commit_after>/*
Copyright 2019 The Knative Authors

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

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

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

package reconciler

import (
	"context"

	"k8s.io/client-go/tools/cache"
	"knative.dev/eventing-prometheus/pkg/apis/sources/v1alpha1"
	"knative.dev/eventing/pkg/reconciler/source"
	"knative.dev/pkg/configmap"
	"knative.dev/pkg/controller"
	"knative.dev/pkg/resolver"

	prometheusinformer "knative.dev/eventing-prometheus/pkg/client/injection/informers/sources/v1alpha1/prometheussource"
	promreconciler "knative.dev/eventing-prometheus/pkg/client/injection/reconciler/sources/v1alpha1/prometheussource"
	kubeclient "knative.dev/pkg/client/injection/kube/client"
	deploymentinformer "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment"
)

const (
	// controllerAgentName is the string used by this controller to identify
	// itself when creating events.
	controllerAgentName = "prometheus-source-controller"
)

// NewController initializes the controller and is called by the generated code
// Registers event handlers to enqueue events
func NewController(
	ctx context.Context,
	cmw configmap.Watcher,
) *controller.Impl {
	deploymentInformer := deploymentinformer.Get(ctx)
	prometheusSourceInformer := prometheusinformer.Get(ctx)

	r := &Reconciler{
		kubeClientSet:    kubeclient.Get(ctx),
		deploymentLister: deploymentInformer.Lister(),
		configs:          source.WatchConfigurations(ctx, controllerAgentName, cmw),
	}
	impl := promreconciler.NewImpl(ctx, r)
	r.sinkResolver = resolver.NewURIResolverFromTracker(ctx, impl.Tracker)

	prometheusSourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))

	deploymentInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
		FilterFunc: controller.FilterController(&v1alpha1.PrometheusSource{}),
		Handler:    controller.HandleAll(impl.EnqueueControllerOf),
	})

	return impl
}
<|endoftext|>


<commit_before>// Copyright 2016 CoreOS, 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 main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strings"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/clientv3/concurrency"
)

func main() {
	log.SetFlags(log.Lmicroseconds)

	endpointStr := flag.String("endpoints", "localhost:2379", "endpoints of etcd cluster")
	mode := flag.String("mode", "lock-racer", "test mode (lock-racer, lease-renewer)")
	round := flag.Int("rounds", 100, "number of rounds to run")
	flag.Parse()
	eps := strings.Split(*endpointStr, ",")

	switch *mode {
	case "lock-racer":
		runRacer(eps, *round)
	case "lease-renewer":
		runLeaseRenewer(eps)
	default:
		fmt.Fprintf(os.Stderr, "unsupported mode %v\n", *mode)
	}
}

func runLeaseRenewer(eps []string) {
	c := randClient(eps)
	ctx := context.Background()

	for {
		var (
			l   *clientv3.LeaseGrantResponse
			lk  *clientv3.LeaseKeepAliveResponse
			err error
		)
		for {
			l, err = c.Lease.Grant(ctx, 5)
			if err == nil {
				break
			}
		}
		expire := time.Now().Add(time.Duration(l.TTL-1) * time.Second)

		for {
			lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
			if grpc.Code(err) == codes.NotFound {
				if time.Since(expire) < 0 {
					log.Printf("bad renew! exceeded: %v", time.Since(expire))
					for {
						lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
						fmt.Println(lk, err)
						time.Sleep(time.Second)
					}
				}
				log.Printf("lost lease %d, expire: %v\n", l.ID, expire)
				break
			}
			if err != nil {
				continue
			}
			expire = time.Now().Add(time.Duration(lk.TTL-1) * time.Second)
			log.Printf("renewed lease %d, expire: %v\n", lk.ID, expire)
			time.Sleep(time.Duration(lk.TTL-2) * time.Second)
		}
	}
}

func runRacer(eps []string, round int) {
	rcs := make([]roundClient, 15)
	ctx := context.Background()
	cnt := 0
	for i := range rcs {
		rcs[i].c = randClient(eps)
		m := concurrency.NewMutex(rcs[i].c, "racers")
		rcs[i].acquire = func() error { return m.Lock(ctx) }
		rcs[i].validate = func() error {
			if cnt++; cnt != 1 {
				return fmt.Errorf("bad lock; count: %d", cnt)
			}
			return nil
		}
		rcs[i].release = func() error {
			if err := m.Unlock(); err != nil {
				return err
			}
			cnt = 0
			return nil
		}
	}
	doRounds(rcs, round)
}

func randClient(eps []string) *clientv3.Client {
	neps := make([]string, len(eps))
	copy(neps, eps)

	for i := range neps {
		j := rand.Intn(i + 1)
		neps[i], neps[j] = neps[j], neps[i]
	}

	c, err := clientv3.New(clientv3.Config{
		Endpoints:   eps,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	return c
}

type roundClient struct {
	c        *clientv3.Client
	progress int
	acquire  func() error
	validate func() error
	release  func() error
}

func doRounds(rcs []roundClient, rounds int) {
	var mu sync.Mutex
	var wg sync.WaitGroup

	wg.Add(len(rcs))
	finished := make(chan struct{}, 0)
	for i := range rcs {
		go func(rc *roundClient) {
			defer wg.Done()
			for rc.progress < rounds {
				for rc.acquire() != nil { /* spin */
				}

				mu.Lock()
				if err := rc.validate(); err != nil {
					log.Fatal(err)
				}
				mu.Unlock()

				time.Sleep(10 * time.Millisecond)
				rc.progress++
				finished <- struct{}{}

				mu.Lock()
				for rc.release() != nil {
					mu.Unlock()
					mu.Lock()
				}
				mu.Unlock()
			}
		}(&rcs[i])
	}

	start := time.Now()
	for i := 1; i < len(rcs)*rounds+1; i++ {
		select {
		case <-finished:
			if i%100 == 0 {
				fmt.Printf("finished %d, took %v\n", i, time.Since(start))
				start = time.Now()
			}
		case <-time.After(time.Minute):
			log.Panic("no progress after 1 minute!")
		}
	}

	wg.Wait()
	for _, rc := range rcs {
		rc.c.Close()
	}
}
<commit_msg>etcd-runner: election mode<commit_after>// Copyright 2016 CoreOS, 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 main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strings"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/clientv3/concurrency"
)

func main() {
	log.SetFlags(log.Lmicroseconds)

	endpointStr := flag.String("endpoints", "localhost:2379", "endpoints of etcd cluster")
	mode := flag.String("mode", "lock-racer", "test mode (election, lock-racer, lease-renewer)")
	round := flag.Int("rounds", 100, "number of rounds to run")
	flag.Parse()
	eps := strings.Split(*endpointStr, ",")

	switch *mode {
	case "election":
		runElection(eps, *round)
	case "lock-racer":
		runRacer(eps, *round)
	case "lease-renewer":
		runLeaseRenewer(eps)
	default:
		fmt.Fprintf(os.Stderr, "unsupported mode %v\n", *mode)
	}
}

func runElection(eps []string, rounds int) {
	rcs := make([]roundClient, 15)
	validatec, releasec := make(chan struct{}, len(rcs)), make(chan struct{}, len(rcs))
	for range rcs {
		releasec <- struct{}{}
	}

	for i := range rcs {
		v := fmt.Sprintf("%d", i)
		observedLeader := ""
		validateWaiters := 0

		rcs[i].c = randClient(eps)
		e := concurrency.NewElection(rcs[i].c, "electors")

		rcs[i].acquire = func() error {
			<-releasec
			ctx, cancel := context.WithCancel(context.Background())
			go func() {
				if ol, ok := <-e.Observe(ctx); ok {
					observedLeader = string(ol.Kvs[0].Value)
					if observedLeader != v {
						cancel()
					}
				}
			}()
			err := e.Campaign(ctx, v)
			if err == nil {
				observedLeader = v
			}
			if observedLeader == v {
				validateWaiters = len(rcs)
			}
			select {
			case <-ctx.Done():
				return nil
			default:
				cancel()
				return err
			}
		}
		rcs[i].validate = func() error {
			if l, err := e.Leader(); err == nil && l != observedLeader {
				return fmt.Errorf("expected leader %q, got %q", observedLeader, l)
			}
			validatec <- struct{}{}
			return nil
		}
		rcs[i].release = func() error {
			for validateWaiters > 0 {
				select {
				case <-validatec:
					validateWaiters--
				default:
					return fmt.Errorf("waiting on followers")
				}
			}
			if err := e.Resign(); err != nil {
				return err
			}
			if observedLeader == v {
				for range rcs {
					releasec <- struct{}{}
				}
			}
			observedLeader = ""
			return nil
		}
	}
	doRounds(rcs, rounds)
}

func runLeaseRenewer(eps []string) {
	c := randClient(eps)
	ctx := context.Background()

	for {
		var (
			l   *clientv3.LeaseGrantResponse
			lk  *clientv3.LeaseKeepAliveResponse
			err error
		)
		for {
			l, err = c.Lease.Grant(ctx, 5)
			if err == nil {
				break
			}
		}
		expire := time.Now().Add(time.Duration(l.TTL-1) * time.Second)

		for {
			lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
			if grpc.Code(err) == codes.NotFound {
				if time.Since(expire) < 0 {
					log.Printf("bad renew! exceeded: %v", time.Since(expire))
					for {
						lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
						fmt.Println(lk, err)
						time.Sleep(time.Second)
					}
				}
				log.Printf("lost lease %d, expire: %v\n", l.ID, expire)
				break
			}
			if err != nil {
				continue
			}
			expire = time.Now().Add(time.Duration(lk.TTL-1) * time.Second)
			log.Printf("renewed lease %d, expire: %v\n", lk.ID, expire)
			time.Sleep(time.Duration(lk.TTL-2) * time.Second)
		}
	}
}

func runRacer(eps []string, round int) {
	rcs := make([]roundClient, 15)
	ctx := context.Background()
	cnt := 0
	for i := range rcs {
		rcs[i].c = randClient(eps)
		m := concurrency.NewMutex(rcs[i].c, "racers")
		rcs[i].acquire = func() error { return m.Lock(ctx) }
		rcs[i].validate = func() error {
			if cnt++; cnt != 1 {
				return fmt.Errorf("bad lock; count: %d", cnt)
			}
			return nil
		}
		rcs[i].release = func() error {
			if err := m.Unlock(); err != nil {
				return err
			}
			cnt = 0
			return nil
		}
	}
	doRounds(rcs, round)
}

func randClient(eps []string) *clientv3.Client {
	neps := make([]string, len(eps))
	copy(neps, eps)

	for i := range neps {
		j := rand.Intn(i + 1)
		neps[i], neps[j] = neps[j], neps[i]
	}

	c, err := clientv3.New(clientv3.Config{
		Endpoints:   eps,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	return c
}

type roundClient struct {
	c        *clientv3.Client
	progress int
	acquire  func() error
	validate func() error
	release  func() error
}

func doRounds(rcs []roundClient, rounds int) {
	var mu sync.Mutex
	var wg sync.WaitGroup

	wg.Add(len(rcs))
	finished := make(chan struct{}, 0)
	for i := range rcs {
		go func(rc *roundClient) {
			defer wg.Done()
			for rc.progress < rounds {
				for rc.acquire() != nil { /* spin */
				}

				mu.Lock()
				if err := rc.validate(); err != nil {
					log.Fatal(err)
				}
				mu.Unlock()

				time.Sleep(10 * time.Millisecond)
				rc.progress++
				finished <- struct{}{}

				mu.Lock()
				for rc.release() != nil {
					mu.Unlock()
					mu.Lock()
				}
				mu.Unlock()
			}
		}(&rcs[i])
	}

	start := time.Now()
	for i := 1; i < len(rcs)*rounds+1; i++ {
		select {
		case <-finished:
			if i%100 == 0 {
				fmt.Printf("finished %d, took %v\n", i, time.Since(start))
				start = time.Now()
			}
		case <-time.After(time.Minute):
			log.Panic("no progress after 1 minute!")
		}
	}

	wg.Wait()
	for _, rc := range rcs {
		rc.c.Close()
	}
}
<|endoftext|>


<commit_before>package events

import (
	"fmt"
	"testing"
)

func TestSampleLogs(t *testing.T) {
	parser := NewStackatoParser()
	for process, event_types := range parser.tree {
		for event_type, event_parser := range event_types {
			event, err := parser.Parse(process, event_parser.Sample)
			if err != nil {
				t.Fatalf("parse error (%s) for %s", err, event_parser.Sample)
			}
			if event == nil {
				t.Fatalf("no event detected for: %s", event_parser.Sample)
			}
			if event.Process != process {
				t.Fatalf("misdetection process %s != %s -- for: %s", event.Process, process, event_parser.Sample)
			}
			if event.Type != event_type {
				t.Fatalf("misdetection type %s != %s -- for: %s", event.Type, event_type, event_parser.Sample)
			}
			// TODO: we should test the Desc field as well. meanwhile,
			// displaying the Desc field to the user.
			fmt.Printf("<< %19s >> -- [%8s] %s\n", event.Type, event.Severity, event.Desc)
		}
	}
}
<commit_msg>take cloud_events.yml into consideration during unit tests<commit_after>package events

import (
	"encoding/json"
	"fmt"
	"os/exec"
	"testing"
)

var config struct {
	Events map[string]map[string]EventParserSpec `json:"events"`
}

func TestSampleLogs(t *testing.T) {
	parser := NewStackatoParser(config.Events)
	for process, event_types := range parser.tree {
		for event_type, event_parser := range event_types {
			event, err := parser.Parse(process, event_parser.Sample)
			if err != nil {
				t.Fatalf("parse error (%s) for %s", err, event_parser.Sample)
			}
			if event == nil {
				t.Fatalf("no event detected for: %s", event_parser.Sample)
			}
			if event.Process != process {
				t.Fatalf("misdetection process %s != %s -- for: %s", event.Process, process, event_parser.Sample)
			}
			if event.Type != event_type {
				t.Fatalf("misdetection type %s != %s -- for: %s", event.Type, event_type, event_parser.Sample)
			}
			// TODO: we should test the Desc field as well. meanwhile,
			// displaying the Desc field to the user.
			fmt.Printf("<< %19s >> -- [%8s] %s\n", event.Type, event.Severity, event.Desc)
		}
	}
}

func init() {
	// XXX: I'm uncertain as to the simplest way to load
	// cloud_events.yml as JSON and json.Unmarshal into config.Events
	// .. all in Go. So, for now, I'll use ruby to do the JSON
	// converstion.
	fmt.Println("Loading etc/cloud_events.yml into test config struct")
	if output, err := exec.Command(
		"/usr/bin/ruby", "-ryaml", "-rjson", "-e",
		"puts YAML.load_file('../../etc/cloud_events.yml').to_json",
	).CombinedOutput(); err != nil {
		panic(fmt.Sprintf("Failed to run ruby: %v (output: %s)", err, output))
	} else {
		if err := json.Unmarshal(output, &config); err != nil {
			panic(err)
		}
	}

}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2016 Ivan Dejanovic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package vm

import (
	"fmt"
	"strconv"
	"strings"
)

const (
	iaddr_size int = 4096
	daddr_size int = 4096
	no_regs    int = 8
	pc_reg     int = 7

	linesize int = 121
	wordsize int = 20
)

type opclass int

const (
	opcLRR opclass = 1 + iota // reg operands r,s,t
	opclRM                    // reg r, mem d+s
	opclRA                    // reg r, int d+s
)

type opcode int

const (
	// RR instructions
	opHALT opcode = 1 + iota // RR     halt, operands are ignored
	opIN                     // RR     read into reg(r); s and t are ignored
	opOUT                    // RR     write from reg(r), s and t are ignored
	opADD                    // RR     reg(r) = reg(s)+reg(t)
	opSUB                    // RR     reg(r) = reg(s)-reg(t)
	opMUL                    // RR     reg(r) = reg(s)*reg(t)
	opDIV                    // RR     reg(r) = reg(s)/reg(t)

	// RM instructions
	opLD // RM     reg(r) = mem(d+reg(s))
	opST // RM     mem(d+reg(s)) = reg(r)

	// RA instructions
	opLDA // RA     reg(r) = d+reg(s)
	opLDC // RA     reg(r) = d ; reg(s) is ignored
	opJLT // RA     if reg(r)<0 then reg(7) = d+reg(s)
	opJLE // RA     if reg(r)<=0 then reg(7) = d+reg(s)
	opJGT // RA     if reg(r)>0 then reg(7) = d+reg(s)
	opJGE // RA     if reg(r)>=0 then reg(7) = d+reg(s)
	opJEQ // RA     if reg(r)==0 then reg(7) = d+reg(s)
	opJNE // RA     if reg(r)!=0 then reg(7) = d+reg(s)
)

type stepRESULT int

const (
	srOKAY stepRESULT = 1 + iota
	srHALT
	srIMEM_ERR
	srDMEM_ERR
	srZERODIVIDE
)

type instruction struct {
	iop   opcode
	iarg1 int
	iarg2 int
	iarg3 int
}

type vmMem struct {
	iMem [iaddr_size]instruction
	dMem [daddr_size]int
	reg  [no_regs]int
}

func loadCode(vm *vmMem, code []string) bool {
	var (
		lineNo           int = 0
		loc              int
		op               opcode
		arg1, arg2, arg3 int
		err              error
		ok               bool
		opcodeMap        map[string]opcode = map[string]opcode{
			// RR opcodes
			"HALT": opHALT,
			"IN":   opIN,
			"OUT":  opOUT,
			"ADD":  opADD,
			"SUB":  opSUB,
			"MUL":  opMUL,
			"DIV":  opDIV,

			// RM instructions
			"LD": opLD,
			"ST": opST,

			// RA instructions
			"LDA": opLDA,
			"LDC": opLDC,
			"JLT": opJLT,
			"JLE": opJLE,
			"JGT": opJGT,
			"JGE": opJGE,
			"JEQ": opJEQ,
			"JNE": opJNE,
		}
	)

	for _, inst := range code {
		lineNo++

		instSlice := strings.Split(strings.Trim(inst, " "), ":")
		if len(instSlice) < 2 {
			fmt.Printf("Missing colon on line: %d\n", lineNo)
			return false
		}

		loc, err = strconv.Atoi(strings.Trim(instSlice[0], " "))
		if err != nil {
			fmt.Printf("Invalid location %s on line: %d\n", instSlice[0], lineNo)
			return false
		}
		if loc > iaddr_size {
			fmt.Printf("To large location %d on line: %d\n", loc, lineNo)
			return false
		}

		opValue := strings.Trim(instSlice[1], " ")
		opIndex := strings.Index(opValue, " ")
		if opIndex == -1 {
			fmt.Printf("Missing opcode on location %d and line: %d\n", loc, lineNo)
			return false
		}

		opCodeKey := opValue[0:opIndex]
		args := strings.Trim(opValue[opIndex+1:len(opValue)], " ")
		op, ok = opcodeMap[opCodeKey]
		if !ok {
			fmt.Printf("Invalid opcode on location %d and line: %d\n", loc, lineNo)
			return false
		}

		switch op {
		case opHALT, opIN, opOUT, opADD, opSUB, opMUL, opDIV:
			argsSlice := strings.Split(args, ",")
			if len(argsSlice) != 3 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg1, err = strconv.Atoi(strings.Trim(argsSlice[0], " "))
			if err != nil {
				fmt.Printf("Invalid first argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg2, err = strconv.Atoi(strings.Trim(argsSlice[1], " "))
			if err != nil {
				fmt.Printf("Invalid second argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg3, err = strconv.Atoi(strings.Trim(argsSlice[2], " "))
			if err != nil {
				fmt.Printf("Invalid third argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			vm.iMem[loc].iop = op
			vm.iMem[loc].iarg1 = arg1
			vm.iMem[loc].iarg2 = arg2
			vm.iMem[loc].iarg3 = arg3
		case opLD, opST, opLDA, opLDC, opJLT, opJLE, opJGT, opJGE, opJEQ, opJNE:
			argsSlice1 := strings.Split(args, ",")
			if len(argsSlice1) != 2 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			argsSlice2 := strings.Split(argsSlice1[1], "(")
			if len(argsSlice2) != 2 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg1, err = strconv.Atoi(strings.Trim(argsSlice1[0], " "))
			if err != nil {
				fmt.Printf("Invalid first argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg2, err = strconv.Atoi(strings.Trim(argsSlice2[0], " "))
			if err != nil {
				fmt.Printf("Invalid second argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg3, err = strconv.Atoi(strings.Trim(argsSlice2[1], ")"))
			if err != nil {
				fmt.Printf("Invalid third argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			vm.iMem[loc].iop = op
			vm.iMem[loc].iarg1 = arg1
			vm.iMem[loc].iarg2 = arg2
			vm.iMem[loc].iarg3 = arg3
		}
	}

	return true
}

func executeCode(vm *vmMem) {

}

func Execute(code []string) {
	vm := vmMem{}

	if !loadCode(&vm, code) {
		return
	}

	executeCode(&vm)
}
<commit_msg>Implemented code execution functionality.<commit_after>/*
The MIT License (MIT)

Copyright (c) 2016 Ivan Dejanovic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package vm

import (
	"fmt"
	"strconv"
	"strings"
)

const (
	iaddr_size int = 4096
	daddr_size int = 4096
	no_regs    int = 8
	pc_reg     int = 7

	linesize int = 121
	wordsize int = 20
)

type opclass int

const (
	opcLRR opclass = 1 + iota // reg operands r,s,t
	opclRM                    // reg r, mem d+s
	opclRA                    // reg r, int d+s
)

type opcode int

const (
	// RR instructions
	opHALT opcode = 1 + iota // RR     halt, operands are ignored
	opIN                     // RR     read into reg(r); s and t are ignored
	opOUT                    // RR     write from reg(r), s and t are ignored
	opADD                    // RR     reg(r) = reg(s)+reg(t)
	opSUB                    // RR     reg(r) = reg(s)-reg(t)
	opMUL                    // RR     reg(r) = reg(s)*reg(t)
	opDIV                    // RR     reg(r) = reg(s)/reg(t)

	// RM instructions
	opLD // RM     reg(r) = mem(d+reg(s))
	opST // RM     mem(d+reg(s)) = reg(r)

	// RA instructions
	opLDA // RA     reg(r) = d+reg(s)
	opLDC // RA     reg(r) = d ; reg(s) is ignored
	opJLT // RA     if reg(r)<0 then reg(7) = d+reg(s)
	opJLE // RA     if reg(r)<=0 then reg(7) = d+reg(s)
	opJGT // RA     if reg(r)>0 then reg(7) = d+reg(s)
	opJGE // RA     if reg(r)>=0 then reg(7) = d+reg(s)
	opJEQ // RA     if reg(r)==0 then reg(7) = d+reg(s)
	opJNE // RA     if reg(r)!=0 then reg(7) = d+reg(s)
)

type stepRESULT int

const (
	srOKAY stepRESULT = 1 + iota
	srHALT
	srIMEM_ERR
	srDMEM_ERR
	srZERODIVIDE
)

type instruction struct {
	iop   opcode
	iarg1 int
	iarg2 int
	iarg3 int
}

type vmMem struct {
	iMem [iaddr_size]instruction
	dMem [daddr_size]int
	reg  [no_regs]int
}

func loadCode(vm *vmMem, code []string) bool {
	var (
		lineNo           int = 0
		loc              int
		op               opcode
		arg1, arg2, arg3 int
		err              error
		ok               bool
		opcodeMap        map[string]opcode = map[string]opcode{
			// RR opcodes
			"HALT": opHALT,
			"IN":   opIN,
			"OUT":  opOUT,
			"ADD":  opADD,
			"SUB":  opSUB,
			"MUL":  opMUL,
			"DIV":  opDIV,

			// RM instructions
			"LD": opLD,
			"ST": opST,

			// RA instructions
			"LDA": opLDA,
			"LDC": opLDC,
			"JLT": opJLT,
			"JLE": opJLE,
			"JGT": opJGT,
			"JGE": opJGE,
			"JEQ": opJEQ,
			"JNE": opJNE,
		}
	)

	for _, inst := range code {
		lineNo++

		instSlice := strings.Split(strings.Trim(inst, " "), ":")
		if len(instSlice) < 2 {
			fmt.Printf("Missing colon on line: %d\n", lineNo)
			return false
		}

		loc, err = strconv.Atoi(strings.Trim(instSlice[0], " "))
		if err != nil {
			fmt.Printf("Invalid location %s on line: %d\n", instSlice[0], lineNo)
			return false
		}
		if loc > iaddr_size {
			fmt.Printf("To large location %d on line: %d\n", loc, lineNo)
			return false
		}

		opValue := strings.Trim(instSlice[1], " ")
		opIndex := strings.Index(opValue, " ")
		if opIndex == -1 {
			fmt.Printf("Missing opcode on location %d and line: %d\n", loc, lineNo)
			return false
		}

		opCodeKey := opValue[0:opIndex]
		args := strings.Trim(opValue[opIndex+1:len(opValue)], " ")
		op, ok = opcodeMap[opCodeKey]
		if !ok {
			fmt.Printf("Invalid opcode on location %d and line: %d\n", loc, lineNo)
			return false
		}

		switch op {
		case opHALT, opIN, opOUT, opADD, opSUB, opMUL, opDIV:
			argsSlice := strings.Split(args, ",")
			if len(argsSlice) != 3 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg1, err = strconv.Atoi(strings.Trim(argsSlice[0], " "))
			if err != nil {
				fmt.Printf("Invalid first argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg2, err = strconv.Atoi(strings.Trim(argsSlice[1], " "))
			if err != nil {
				fmt.Printf("Invalid second argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg3, err = strconv.Atoi(strings.Trim(argsSlice[2], " "))
			if err != nil {
				fmt.Printf("Invalid third argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			vm.iMem[loc].iop = op
			vm.iMem[loc].iarg1 = arg1
			vm.iMem[loc].iarg2 = arg2
			vm.iMem[loc].iarg3 = arg3
		case opLD, opST, opLDA, opLDC, opJLT, opJLE, opJGT, opJGE, opJEQ, opJNE:
			argsSlice1 := strings.Split(args, ",")
			if len(argsSlice1) != 2 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			argsSlice2 := strings.Split(argsSlice1[1], "(")
			if len(argsSlice2) != 2 {
				fmt.Printf("Invalid number of arguments on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg1, err = strconv.Atoi(strings.Trim(argsSlice1[0], " "))
			if err != nil {
				fmt.Printf("Invalid first argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg2, err = strconv.Atoi(strings.Trim(argsSlice2[0], " "))
			if err != nil {
				fmt.Printf("Invalid second argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			arg3, err = strconv.Atoi(strings.Trim(argsSlice2[1], ")"))
			if err != nil {
				fmt.Printf("Invalid third argument on location %d and line: %d\n", loc, lineNo)
				return false
			}

			vm.iMem[loc].iop = op
			vm.iMem[loc].iarg1 = arg1
			vm.iMem[loc].iarg2 = arg2
			vm.iMem[loc].iarg3 = arg3
		}
	}
	return true
}

func executeCode(vm *vmMem) {
	var execute bool = true

	for execute {
		var r, s, t, m = 0, 0, 0, 0
		pc := vm.reg[pc_reg]
		if pc < 0 || pc > iaddr_size {
			fmt.Printf("Invalid program counter value: %d\n", pc)
			return
		}

		vm.reg[pc_reg] = pc + 1
		inst := vm.iMem[pc]

		//Setup instruction arguments
		switch inst.iop {
		case opHALT, opIN, opOUT, opADD, opSUB, opMUL, opDIV:
			r = inst.iarg1
			s = inst.iarg2
			t = inst.iarg3
		case opLD, opST:
			r = inst.iarg1
			s = inst.iarg3
			m = inst.iarg2 + vm.reg[s]

			if m < 0 || m > daddr_size {
				fmt.Printf("Invalid memory address value: %d\n", m)
				return
			}
		case opLDA, opLDC, opJLT, opJLE, opJGT, opJGE, opJEQ, opJNE:
			r = inst.iarg1
			s = inst.iarg3
			m = inst.iarg2 + vm.reg[s]
		}

		//Execute instruction
		switch inst.iop {
		case opHALT:
			fmt.Println("Program halting.")
			return
		case opIN:
			var num int = 0
			_, err := fmt.Scanf("%d", &num)
			if err != nil {
				fmt.Println("Non integer entered.")
				return
			}
			vm.reg[r] = num
		case opOUT:
			fmt.Println(vm.reg[r])
		case opADD:
			vm.reg[r] = vm.reg[s] + vm.reg[t]
		case opSUB:
			vm.reg[r] = vm.reg[s] - vm.reg[t]
		case opMUL:
			vm.reg[r] = vm.reg[s] * vm.reg[t]
		case opDIV:
			if vm.reg[t] == 0 {
				fmt.Println("Division with zero.")
				return
			}
			vm.reg[r] = vm.reg[s] / vm.reg[t]
		case opLD:
			vm.reg[r] = vm.dMem[m]
		case opST:
			vm.dMem[m] = vm.reg[r]
		case opLDA:
			vm.reg[r] = m
		case opLDC:
			vm.reg[r] = inst.iarg2
		case opJLT:
			if vm.reg[r] < 0 {
				vm.reg[pc_reg] = m
			}
		case opJLE:
			if vm.reg[r] <= 0 {
				vm.reg[pc_reg] = m
			}
		case opJGT:
			if vm.reg[r] > 0 {
				vm.reg[pc_reg] = m
			}
		case opJGE:
			if vm.reg[r] >= 0 {
				vm.reg[pc_reg] = m
			}
		case opJEQ:
			if vm.reg[r] == 0 {
				vm.reg[pc_reg] = m
			}
		case opJNE:
			if vm.reg[r] != 0 {
				vm.reg[pc_reg] = m
			}
		}
	}
}

func Execute(code []string) {
	vm := vmMem{}
	vm.dMem[0] = daddr_size - 1

	if !loadCode(&vm, code) {
		return
	}

	executeCode(&vm)
}
<|endoftext|>


<commit_before>package hoverfly

import (
	"fmt"
	"io"
	"net/http"

	// static assets
	_ "github.com/SpectoLabs/hoverfly/core/statik"
	"github.com/rakyll/statik/fs"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"github.com/meatballhat/negroni-logrus"

	handlers "github.com/SpectoLabs/hoverfly/core/handlers"
	"github.com/SpectoLabs/hoverfly/core/handlers/v1"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
)

type AdminApi struct{}

// StartAdminInterface - starts admin interface web server
func (this *AdminApi) StartAdminInterface(hoverfly *Hoverfly) {

	// starting admin interface
	mux := this.getBoneRouter(hoverfly)
	n := negroni.Classic()

	logLevel := log.ErrorLevel

	if hoverfly.Cfg.Verbose {
		logLevel = log.DebugLevel
	}

	n.Use(negronilogrus.NewCustomMiddleware(logLevel, &log.JSONFormatter{}, "admin"))
	n.UseHandler(mux)

	// admin interface starting message
	log.WithFields(log.Fields{
		"AdminPort": hoverfly.Cfg.AdminPort,
	}).Info("Admin interface is starting...")

	n.Run(fmt.Sprintf(":%s", hoverfly.Cfg.AdminPort))
}

// getBoneRouter returns mux for admin interface
func (this *AdminApi) getBoneRouter(d *Hoverfly) *bone.Mux {
	mux := bone.New()

	authHandler := &handlers.AuthHandler{
		d.Authentication,
		d.Cfg.SecretKey,
		d.Cfg.JWTExpirationDelta,
		d.Cfg.AuthEnabled,
	}

	authHandler.RegisterRoutes(mux)

	handlers := GetAllHandlers(d)
	for _, handler := range handlers {
		handler.RegisterRoutes(mux, authHandler)
	}

	if d.Cfg.Development {
		// since hoverfly is not started from cmd/hoverfly/hoverfly
		// we have to target to that directory
		log.Warn("Hoverfly is serving files from /static/admin/dist instead of statik binary!")
		mux.Handle("/js/*", http.StripPrefix("/js/", http.FileServer(http.Dir("../../static/admin/dist/js"))))

		mux.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
			http.ServeFile(w, r, "../../static/admin/dist/index.html")
		})

	} else {
		// preparing static assets for embedded admin
		statikFS, err := fs.New()

		if err != nil {
			log.WithFields(log.Fields{
				"Error": err.Error(),
			}).Error("Failed to load statikFS, admin UI might not work :(")
		}
		mux.Handle("/js/*", http.FileServer(statikFS))
		mux.Handle("/app.32dc9945fd902da8ed2cccdc8703129f.css", http.FileServer(statikFS))
		mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
			file, err := statikFS.Open("/index.html")
			if err != nil {
				w.WriteHeader(500)
				log.WithFields(log.Fields{
					"error": err,
				}).Error("got error while opening index file")
				return
			}
			io.Copy(w, file)
			w.WriteHeader(200)
		})
	}
	return mux
}

func GetAllHandlers(hoverfly *Hoverfly) []handlers.AdminHandler {
	var list []handlers.AdminHandler

	list = append(list, &v1.AddHandler{Hoverfly: hoverfly})
	list = append(list, &v1.CountHandler{Hoverfly: hoverfly})
	list = append(list, &v1.DelaysHandler{Hoverfly: hoverfly})
	list = append(list, &v1.HealthHandler{})
	list = append(list, &v1.MetadataHandler{Hoverfly: hoverfly})
	list = append(list, &v1.MiddlewareHandler{Hoverfly: hoverfly})
	list = append(list, &v1.RecordsHandler{Hoverfly: hoverfly})
	list = append(list, &v1.StateHandler{Hoverfly: hoverfly})
	list = append(list, &v1.StatsHandler{Hoverfly: hoverfly})
	list = append(list, &v1.TemplatesHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyDestinationHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyModeHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyMiddlewareHandler{Hoverfly: hoverfly})

	return list
}<commit_msg>Adding the new HoverflyUsageHandler to admin API<commit_after>package hoverfly

import (
	"fmt"
	"io"
	"net/http"

	// static assets
	_ "github.com/SpectoLabs/hoverfly/core/statik"
	"github.com/rakyll/statik/fs"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"github.com/meatballhat/negroni-logrus"

	handlers "github.com/SpectoLabs/hoverfly/core/handlers"
	"github.com/SpectoLabs/hoverfly/core/handlers/v1"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
)

type AdminApi struct{}

// StartAdminInterface - starts admin interface web server
func (this *AdminApi) StartAdminInterface(hoverfly *Hoverfly) {

	// starting admin interface
	mux := this.getBoneRouter(hoverfly)
	n := negroni.Classic()

	logLevel := log.ErrorLevel

	if hoverfly.Cfg.Verbose {
		logLevel = log.DebugLevel
	}

	n.Use(negronilogrus.NewCustomMiddleware(logLevel, &log.JSONFormatter{}, "admin"))
	n.UseHandler(mux)

	// admin interface starting message
	log.WithFields(log.Fields{
		"AdminPort": hoverfly.Cfg.AdminPort,
	}).Info("Admin interface is starting...")

	n.Run(fmt.Sprintf(":%s", hoverfly.Cfg.AdminPort))
}

// getBoneRouter returns mux for admin interface
func (this *AdminApi) getBoneRouter(d *Hoverfly) *bone.Mux {
	mux := bone.New()

	authHandler := &handlers.AuthHandler{
		d.Authentication,
		d.Cfg.SecretKey,
		d.Cfg.JWTExpirationDelta,
		d.Cfg.AuthEnabled,
	}

	authHandler.RegisterRoutes(mux)

	handlers := GetAllHandlers(d)
	for _, handler := range handlers {
		handler.RegisterRoutes(mux, authHandler)
	}

	if d.Cfg.Development {
		// since hoverfly is not started from cmd/hoverfly/hoverfly
		// we have to target to that directory
		log.Warn("Hoverfly is serving files from /static/admin/dist instead of statik binary!")
		mux.Handle("/js/*", http.StripPrefix("/js/", http.FileServer(http.Dir("../../static/admin/dist/js"))))

		mux.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
			http.ServeFile(w, r, "../../static/admin/dist/index.html")
		})

	} else {
		// preparing static assets for embedded admin
		statikFS, err := fs.New()

		if err != nil {
			log.WithFields(log.Fields{
				"Error": err.Error(),
			}).Error("Failed to load statikFS, admin UI might not work :(")
		}
		mux.Handle("/js/*", http.FileServer(statikFS))
		mux.Handle("/app.32dc9945fd902da8ed2cccdc8703129f.css", http.FileServer(statikFS))
		mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
			file, err := statikFS.Open("/index.html")
			if err != nil {
				w.WriteHeader(500)
				log.WithFields(log.Fields{
					"error": err,
				}).Error("got error while opening index file")
				return
			}
			io.Copy(w, file)
			w.WriteHeader(200)
		})
	}
	return mux
}

func GetAllHandlers(hoverfly *Hoverfly) []handlers.AdminHandler {
	var list []handlers.AdminHandler

	list = append(list, &v1.AddHandler{Hoverfly: hoverfly})
	list = append(list, &v1.CountHandler{Hoverfly: hoverfly})
	list = append(list, &v1.DelaysHandler{Hoverfly: hoverfly})
	list = append(list, &v1.HealthHandler{})
	list = append(list, &v1.MetadataHandler{Hoverfly: hoverfly})
	list = append(list, &v1.MiddlewareHandler{Hoverfly: hoverfly})
	list = append(list, &v1.RecordsHandler{Hoverfly: hoverfly})
	list = append(list, &v1.StateHandler{Hoverfly: hoverfly})
	list = append(list, &v1.StatsHandler{Hoverfly: hoverfly})
	list = append(list, &v1.TemplatesHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyDestinationHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyModeHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyMiddlewareHandler{Hoverfly: hoverfly})
	list = append(list, &v2.HoverflyUsageHandler{Hoverfly: hoverfly})

	return list
}<|endoftext|>


<commit_before>package hypervisor

import (
	"net"
	"time"

	"github.com/Symantec/Dominator/lib/tags"
)

const (
	StateStarting      = 0
	StateRunning       = 1
	StateFailedToStart = 2
	StateStopping      = 3
	StateStopped       = 4
	StateDestroying    = 5

	VolumeFormatRaw   = 0
	VolumeFormatQCOW2 = 1
)

type AcknowledgeVmRequest struct {
	IpAddress net.IP
}

type AcknowledgeVmResponse struct {
	Error string
}

type AddAddressesToPoolRequest struct {
	Addresses []Address
}

type AddAddressesToPoolResponse struct {
	Error string
}

type Address struct {
	IpAddress  net.IP `json:",omitempty"`
	MacAddress string
}

type AddSubnetsRequest struct {
	Subnets []Subnet
}

type AddSubnetsResponse struct {
	Error string
}

type BecomePrimaryVmOwnerRequest struct {
	IpAddress net.IP
}

type BecomePrimaryVmOwnerResponse struct {
	Error string
}

type ChangeVmOwnerUsersRequest struct {
	IpAddress  net.IP
	OwnerUsers []string
}

type ChangeVmOwnerUsersResponse struct {
	Error string
}

type ChangeVmTagsRequest struct {
	IpAddress net.IP
	Tags      tags.Tags
}

type ChangeVmTagsResponse struct {
	Error string
}

type CommitImportedVmRequest struct {
	IpAddress net.IP
}

type CommitImportedVmResponse struct {
	Error string
}

type CreateVmRequest struct {
	DhcpTimeout      time.Duration
	ImageDataSize    uint64
	ImageTimeout     time.Duration
	MinimumFreeBytes uint64
	RoundupPower     uint64
	SecondaryVolumes []Volume
	UserDataSize     uint64
	VmInfo
} // RAW image data (length=ImageDataSize) and user data (length=UserDataSize)
// are streamed afterwards.

type CreateVmResponse struct { // Multiple responses are sent.
	DhcpTimedOut    bool
	Final           bool // If true, this is the final response.
	IpAddress       net.IP
	ProgressMessage string
	Error           string
}

type DestroyVmRequest struct {
	IpAddress net.IP
}

type DestroyVmResponse struct {
	Error string
}

type DiscardVmOldImageRequest struct {
	IpAddress net.IP
}

type DiscardVmOldImageResponse struct {
	Error string
}

type DiscardVmOldUserDataRequest struct {
	IpAddress net.IP
}

type DiscardVmOldUserDataResponse struct {
	Error string
}

type DiscardVmSnapshotRequest struct {
	IpAddress net.IP
}

type DiscardVmSnapshotResponse struct {
	Error string
}

// The GetUpdates() RPC is fully streamed.
// The client sends no information to the server.
// The server sends a stream of Update messages.

type Update struct {
	HaveAddressPool  bool               `json:",omitempty"`
	AddressPool      []Address          `json:",omitempty"` // Used & free.
	HaveNumFree      bool               `json:",omitempty"`
	NumFreeAddresses uint               `json:",omitempty"`
	HaveSubnets      bool               `json:",omitempty"`
	Subnets          []Subnet           `json:",omitempty"`
	HaveVMs          bool               `json:",omitempty"`
	VMs              map[string]*VmInfo `json:",omitempty"` // Key: IP address.
}

type GetVmInfoRequest struct {
	IpAddress net.IP
}

type GetVmInfoResponse struct {
	VmInfo VmInfo
	Error  string
}

type ImportLocalVmRequest struct {
	VerificationCookie []byte
	VmInfo
	VolumeFilenames []string
}

type ImportLocalVmResponse struct {
	Error string
}

type ListVMsRequest struct {
	Sort bool
}

type ListVMsResponse struct {
	IpAddresses []net.IP
}

type ListVolumeDirectoriesRequest struct{}

type ListVolumeDirectoriesResponse struct {
	Directories []string
	Error       string
}

type ProbeVmPortRequest struct {
	IpAddress  net.IP
	PortNumber uint
	Timeout    time.Duration
}

type ProbeVmPortResponse struct {
	PortIsOpen bool
	Error      string
}

type RemoveExcessAddressesFromPoolRequest struct {
	MaximumFreeAddresses uint
}

type RemoveExcessAddressesFromPoolResponse struct {
	Error string
}

type ReplaceVmImageRequest struct {
	DhcpTimeout      time.Duration
	ImageDataSize    uint64
	ImageName        string `json:",omitempty"`
	ImageTimeout     time.Duration
	ImageURL         string `json:",omitempty"`
	IpAddress        net.IP
	MinimumFreeBytes uint64
	RoundupPower     uint64
} // RAW image data (length=ImageDataSize) is streamed afterwards.

type ReplaceVmImageResponse struct { // Multiple responses are sent.
	DhcpTimedOut    bool
	Final           bool // If true, this is the final response.
	ProgressMessage string
	Error           string
}

type ReplaceVmUserDataRequest struct {
	IpAddress net.IP
	Size      uint64
} // User data (length=Size) are streamed afterwards.

type ReplaceVmUserDataResponse struct {
	Error string
}

type RestoreVmFromSnapshotRequest struct {
	IpAddress         net.IP
	ForceIfNotStopped bool
}

type RestoreVmFromSnapshotResponse struct {
	Error string
}

type RestoreVmImageRequest struct {
	IpAddress net.IP
}

type RestoreVmImageResponse struct {
	Error string
}

type RestoreVmUserDataRequest struct {
	IpAddress net.IP
}

type RestoreVmUserDataResponse struct {
	Error string
}

type SnapshotVmRequest struct {
	IpAddress         net.IP
	ForceIfNotStopped bool
	RootOnly          bool
}

type SnapshotVmResponse struct {
	Error string
}

type StartVmRequest struct {
	DhcpTimeout time.Duration
	IpAddress   net.IP
}

type StartVmResponse struct {
	DhcpTimedOut bool
	Error        string
}

type StopVmRequest struct {
	IpAddress net.IP
}

type StopVmResponse struct {
	Error string
}

type State uint

type Subnet struct {
	Id                string
	IpGateway         net.IP
	IpMask            net.IP // net.IPMask can't be JSON {en,de}coded.
	DomainName        string `json:",omitempty"`
	DomainNameServers []net.IP
}

type TraceVmMetadataRequest struct {
	IpAddress net.IP
}

type TraceVmMetadataResponse struct {
	Error string
} // A stream of strings (trace paths) follow.

type VmInfo struct {
	Address       Address
	Hostname      string `json:",omitempty"`
	ImageName     string `json:",omitempty"`
	ImageURL      string `json:",omitempty"`
	MemoryInMiB   uint64
	MilliCPUs     uint
	OwnerGroups   []string `json:",omitempty"`
	OwnerUsers    []string `json:",omitempty"`
	SpreadVolumes bool     `json:",omitempty"`
	State         State
	Tags          tags.Tags `json:",omitempty"`
	SubnetId      string    `json:",omitempty"`
	Uncommitted   bool      `json:",omitempty"`
	Volumes       []Volume  `json:",omitempty"`
}

type Volume struct {
	Size   uint64
	Format VolumeFormat
}

type VolumeFormat uint
<commit_msg>Add proto/hypervisor.Subnet.VlanId field.<commit_after>package hypervisor

import (
	"net"
	"time"

	"github.com/Symantec/Dominator/lib/tags"
)

const (
	StateStarting      = 0
	StateRunning       = 1
	StateFailedToStart = 2
	StateStopping      = 3
	StateStopped       = 4
	StateDestroying    = 5

	VolumeFormatRaw   = 0
	VolumeFormatQCOW2 = 1
)

type AcknowledgeVmRequest struct {
	IpAddress net.IP
}

type AcknowledgeVmResponse struct {
	Error string
}

type AddAddressesToPoolRequest struct {
	Addresses []Address
}

type AddAddressesToPoolResponse struct {
	Error string
}

type Address struct {
	IpAddress  net.IP `json:",omitempty"`
	MacAddress string
}

type AddSubnetsRequest struct {
	Subnets []Subnet
}

type AddSubnetsResponse struct {
	Error string
}

type BecomePrimaryVmOwnerRequest struct {
	IpAddress net.IP
}

type BecomePrimaryVmOwnerResponse struct {
	Error string
}

type ChangeVmOwnerUsersRequest struct {
	IpAddress  net.IP
	OwnerUsers []string
}

type ChangeVmOwnerUsersResponse struct {
	Error string
}

type ChangeVmTagsRequest struct {
	IpAddress net.IP
	Tags      tags.Tags
}

type ChangeVmTagsResponse struct {
	Error string
}

type CommitImportedVmRequest struct {
	IpAddress net.IP
}

type CommitImportedVmResponse struct {
	Error string
}

type CreateVmRequest struct {
	DhcpTimeout      time.Duration
	ImageDataSize    uint64
	ImageTimeout     time.Duration
	MinimumFreeBytes uint64
	RoundupPower     uint64
	SecondaryVolumes []Volume
	UserDataSize     uint64
	VmInfo
} // RAW image data (length=ImageDataSize) and user data (length=UserDataSize)
// are streamed afterwards.

type CreateVmResponse struct { // Multiple responses are sent.
	DhcpTimedOut    bool
	Final           bool // If true, this is the final response.
	IpAddress       net.IP
	ProgressMessage string
	Error           string
}

type DestroyVmRequest struct {
	IpAddress net.IP
}

type DestroyVmResponse struct {
	Error string
}

type DiscardVmOldImageRequest struct {
	IpAddress net.IP
}

type DiscardVmOldImageResponse struct {
	Error string
}

type DiscardVmOldUserDataRequest struct {
	IpAddress net.IP
}

type DiscardVmOldUserDataResponse struct {
	Error string
}

type DiscardVmSnapshotRequest struct {
	IpAddress net.IP
}

type DiscardVmSnapshotResponse struct {
	Error string
}

// The GetUpdates() RPC is fully streamed.
// The client sends no information to the server.
// The server sends a stream of Update messages.

type Update struct {
	HaveAddressPool  bool               `json:",omitempty"`
	AddressPool      []Address          `json:",omitempty"` // Used & free.
	HaveNumFree      bool               `json:",omitempty"`
	NumFreeAddresses uint               `json:",omitempty"`
	HaveSubnets      bool               `json:",omitempty"`
	Subnets          []Subnet           `json:",omitempty"`
	HaveVMs          bool               `json:",omitempty"`
	VMs              map[string]*VmInfo `json:",omitempty"` // Key: IP address.
}

type GetVmInfoRequest struct {
	IpAddress net.IP
}

type GetVmInfoResponse struct {
	VmInfo VmInfo
	Error  string
}

type ImportLocalVmRequest struct {
	VerificationCookie []byte
	VmInfo
	VolumeFilenames []string
}

type ImportLocalVmResponse struct {
	Error string
}

type ListVMsRequest struct {
	Sort bool
}

type ListVMsResponse struct {
	IpAddresses []net.IP
}

type ListVolumeDirectoriesRequest struct{}

type ListVolumeDirectoriesResponse struct {
	Directories []string
	Error       string
}

type ProbeVmPortRequest struct {
	IpAddress  net.IP
	PortNumber uint
	Timeout    time.Duration
}

type ProbeVmPortResponse struct {
	PortIsOpen bool
	Error      string
}

type RemoveExcessAddressesFromPoolRequest struct {
	MaximumFreeAddresses uint
}

type RemoveExcessAddressesFromPoolResponse struct {
	Error string
}

type ReplaceVmImageRequest struct {
	DhcpTimeout      time.Duration
	ImageDataSize    uint64
	ImageName        string `json:",omitempty"`
	ImageTimeout     time.Duration
	ImageURL         string `json:",omitempty"`
	IpAddress        net.IP
	MinimumFreeBytes uint64
	RoundupPower     uint64
} // RAW image data (length=ImageDataSize) is streamed afterwards.

type ReplaceVmImageResponse struct { // Multiple responses are sent.
	DhcpTimedOut    bool
	Final           bool // If true, this is the final response.
	ProgressMessage string
	Error           string
}

type ReplaceVmUserDataRequest struct {
	IpAddress net.IP
	Size      uint64
} // User data (length=Size) are streamed afterwards.

type ReplaceVmUserDataResponse struct {
	Error string
}

type RestoreVmFromSnapshotRequest struct {
	IpAddress         net.IP
	ForceIfNotStopped bool
}

type RestoreVmFromSnapshotResponse struct {
	Error string
}

type RestoreVmImageRequest struct {
	IpAddress net.IP
}

type RestoreVmImageResponse struct {
	Error string
}

type RestoreVmUserDataRequest struct {
	IpAddress net.IP
}

type RestoreVmUserDataResponse struct {
	Error string
}

type SnapshotVmRequest struct {
	IpAddress         net.IP
	ForceIfNotStopped bool
	RootOnly          bool
}

type SnapshotVmResponse struct {
	Error string
}

type StartVmRequest struct {
	DhcpTimeout time.Duration
	IpAddress   net.IP
}

type StartVmResponse struct {
	DhcpTimedOut bool
	Error        string
}

type StopVmRequest struct {
	IpAddress net.IP
}

type StopVmResponse struct {
	Error string
}

type State uint

type Subnet struct {
	Id                string
	IpGateway         net.IP
	IpMask            net.IP // net.IPMask can't be JSON {en,de}coded.
	DomainName        string `json:",omitempty"`
	DomainNameServers []net.IP
	VlanId            uint `json:",omitempty"`
}

type TraceVmMetadataRequest struct {
	IpAddress net.IP
}

type TraceVmMetadataResponse struct {
	Error string
} // A stream of strings (trace paths) follow.

type VmInfo struct {
	Address       Address
	Hostname      string `json:",omitempty"`
	ImageName     string `json:",omitempty"`
	ImageURL      string `json:",omitempty"`
	MemoryInMiB   uint64
	MilliCPUs     uint
	OwnerGroups   []string `json:",omitempty"`
	OwnerUsers    []string `json:",omitempty"`
	SpreadVolumes bool     `json:",omitempty"`
	State         State
	Tags          tags.Tags `json:",omitempty"`
	SubnetId      string    `json:",omitempty"`
	Uncommitted   bool      `json:",omitempty"`
	Volumes       []Volume  `json:",omitempty"`
}

type Volume struct {
	Size   uint64
	Format VolumeFormat
}

type VolumeFormat uint
<|endoftext|>


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

package juju

var collectOutput = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  97:
    agent-state: running
    dns-name: 10.10.10.189
    instance-id: i-0000040b
    instance-state: running
  100:
    agent-state: running
    dns-name: 10.10.10.208
    instance-id: i-00000422
    instance-state: running
  102:
    agent-state: running
    dns-name: 10.10.10.131
    instance-id: i-00000424
    instance-state: running
  105:
    agent-state: running
    dns-name: 10.10.10.163
    instance-id: i-00000439
    instance-state: running
  107:
    agent-state: running
    dns-name: 10.10.10.168
    instance-id: i-0000043e
    instance-state: running
services:
  as_i_rise:
    charm: local:centos/django-13
    exposed: false
    relations: {}
    units:
      as_i_rise/0:
        agent-state: started
        machine: 105
        public-address: server-1081.novalocal
  the_infanta:
    charm: local:centos/gunicorn-14
    exposed: false
    relations: {}
    units:
      the_infanta/0:
        agent-state: pending
        machine: 107
        public-address: server-1086.novalocal`

var dirtyCollectOutput = `2012-12-14 17:19:28,235 INFO Connecting to environment...
2012-12-14 17:19:29,455 INFO Connected to environment.
machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  97:
    agent-state: running
    dns-name: 10.10.10.189
    instance-id: i-0000040b
    instance-state: running
  100:
    agent-state: running
    dns-name: 10.10.10.208
    instance-id: i-00000422
    instance-state: running
  102:
    agent-state: running
    dns-name: 10.10.10.131
    instance-id: i-00000424
    instance-state: running
  105:
    agent-state: running
    dns-name: 10.10.10.163
    instance-id: i-00000439
    instance-state: running
  107:
    agent-state: running
    dns-name: 10.10.10.168
    instance-id: i-0000043e
    instance-state: running
services:
  as_i_rise:
    charm: local:centos/django-13
    exposed: false
    relations: {}
    units:
      as_i_rise/0:
        agent-state: started
        machine: 105
        public-address: server-1081.novalocal
  the_infanta:
    charm: local:centos/gunicorn-14
    exposed: false
    relations: {}
    units:
      the_infanta/1:
        agent-state: pending
        machine: 107
        public-address: server-1086.novalocal
2012-12-14 17:19:29,665 INFO 'status' command finished successfully`

var simpleCollectOutput = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    agent-state: running
    dns-name: 10.10.1.58
    instance-id: i-00004444
    instance-state: running
  2:
    agent-state: pending
    dns-name: 10.10.1.59
    instance-id: i-00004445
    instance-state: running
  3:
    agent-state: pending
    dns-name: 10.10.2.59
    instance-id: i-00004450
    instance-state: running
services:
  symfonia:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      symfonia/0:
        agent-state: pending
        machine: 1
        public-address: server-1086.novalocal
      symfonia/1:
        agent-state: pending
        machine: 2
        public-address: server-1085.novalocal
      symfonia/2:
        agent-state: pending
        machine: 3
        public-address: server-1087.novalocal`

var collectOutputNoInstanceId = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    agent-state: running
    dns-name: 10.10.1.58
    instance-id: i-00004444
    instance-state: running
  2:
    instance-id: pending
services:
  2112:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      2112/0:
        agent-state: pending
        machine: 1
        public-address: server-1086.novalocal
      2112/1:
        agent-state: pending
        machine: 2
        public-address: null`

var collectOutputAllPending = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    instance-id: pending
  2:
    instance-id: pending
services:
  2112:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      2112/0:
        agent-state: pending
        machine: 1
        public-address: null
      2112/1:
        agent-state: pending
        machine: 2
        public-address: null`

var addUnitsOutput = `2012-12-19 14:05:21,275 INFO Connecting to environment...
2012-12-19 14:05:22,681 INFO Connected to environment.
2012-12-19 11:57:31,361 INFO Unit 'resist/3' added to service 'resist'
2012-12-19 11:57:31,550 INFO Unit 'resist/4' added to service 'resist'
2012-12-19 11:57:31,785 INFO Unit 'resist/5' added to service 'resist'
2012-12-19 11:57:31,785 INFO Unit 'resist/6' added to service 'resist'
2012-12-19 14:05:23,251 INFO 'add_unit' command finished successfully`
<commit_msg>provision/juju: update copyright header in stubs_test.go<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package juju

var collectOutput = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  97:
    agent-state: running
    dns-name: 10.10.10.189
    instance-id: i-0000040b
    instance-state: running
  100:
    agent-state: running
    dns-name: 10.10.10.208
    instance-id: i-00000422
    instance-state: running
  102:
    agent-state: running
    dns-name: 10.10.10.131
    instance-id: i-00000424
    instance-state: running
  105:
    agent-state: running
    dns-name: 10.10.10.163
    instance-id: i-00000439
    instance-state: running
  107:
    agent-state: running
    dns-name: 10.10.10.168
    instance-id: i-0000043e
    instance-state: running
services:
  as_i_rise:
    charm: local:centos/django-13
    exposed: false
    relations: {}
    units:
      as_i_rise/0:
        agent-state: started
        machine: 105
        public-address: server-1081.novalocal
  the_infanta:
    charm: local:centos/gunicorn-14
    exposed: false
    relations: {}
    units:
      the_infanta/0:
        agent-state: pending
        machine: 107
        public-address: server-1086.novalocal`

var dirtyCollectOutput = `2012-12-14 17:19:28,235 INFO Connecting to environment...
2012-12-14 17:19:29,455 INFO Connected to environment.
machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  97:
    agent-state: running
    dns-name: 10.10.10.189
    instance-id: i-0000040b
    instance-state: running
  100:
    agent-state: running
    dns-name: 10.10.10.208
    instance-id: i-00000422
    instance-state: running
  102:
    agent-state: running
    dns-name: 10.10.10.131
    instance-id: i-00000424
    instance-state: running
  105:
    agent-state: running
    dns-name: 10.10.10.163
    instance-id: i-00000439
    instance-state: running
  107:
    agent-state: running
    dns-name: 10.10.10.168
    instance-id: i-0000043e
    instance-state: running
services:
  as_i_rise:
    charm: local:centos/django-13
    exposed: false
    relations: {}
    units:
      as_i_rise/0:
        agent-state: started
        machine: 105
        public-address: server-1081.novalocal
  the_infanta:
    charm: local:centos/gunicorn-14
    exposed: false
    relations: {}
    units:
      the_infanta/1:
        agent-state: pending
        machine: 107
        public-address: server-1086.novalocal
2012-12-14 17:19:29,665 INFO 'status' command finished successfully`

var simpleCollectOutput = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    agent-state: running
    dns-name: 10.10.1.58
    instance-id: i-00004444
    instance-state: running
  2:
    agent-state: pending
    dns-name: 10.10.1.59
    instance-id: i-00004445
    instance-state: running
  3:
    agent-state: pending
    dns-name: 10.10.2.59
    instance-id: i-00004450
    instance-state: running
services:
  symfonia:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      symfonia/0:
        agent-state: pending
        machine: 1
        public-address: server-1086.novalocal
      symfonia/1:
        agent-state: pending
        machine: 2
        public-address: server-1085.novalocal
      symfonia/2:
        agent-state: pending
        machine: 3
        public-address: server-1087.novalocal`

var collectOutputNoInstanceId = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    agent-state: running
    dns-name: 10.10.1.58
    instance-id: i-00004444
    instance-state: running
  2:
    instance-id: pending
services:
  2112:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      2112/0:
        agent-state: pending
        machine: 1
        public-address: server-1086.novalocal
      2112/1:
        agent-state: pending
        machine: 2
        public-address: null`

var collectOutputAllPending = `machines:
  0:
    agent-state: running
    dns-name: 10.10.10.96
    instance-id: i-00000376
    instance-state: running
  1:
    instance-id: pending
  2:
    instance-id: pending
services:
  2112:
    charm: local:precise/python-1
    exposed: false
    relations: {}
    units:
      2112/0:
        agent-state: pending
        machine: 1
        public-address: null
      2112/1:
        agent-state: pending
        machine: 2
        public-address: null`

var addUnitsOutput = `2012-12-19 14:05:21,275 INFO Connecting to environment...
2012-12-19 14:05:22,681 INFO Connected to environment.
2012-12-19 11:57:31,361 INFO Unit 'resist/3' added to service 'resist'
2012-12-19 11:57:31,550 INFO Unit 'resist/4' added to service 'resist'
2012-12-19 11:57:31,785 INFO Unit 'resist/5' added to service 'resist'
2012-12-19 11:57:31,785 INFO Unit 'resist/6' added to service 'resist'
2012-12-19 14:05:23,251 INFO 'add_unit' command finished successfully`
<|endoftext|>


<commit_before>package main

func rotate(nums []int, k int) {
	visited := make(map[int]bool)
	for i := 0; i < len(nums); i++ {
		if visited[i] {
			continue
		}
		prev := nums[i]
		j := (i + k) % len(nums)
		for !visited[j] {

			nums[j], prev = prev, nums[j]

			visited[j] = true
			j = (j + k) % len(nums)
		}
	}
}
<commit_msg>improved rotate<commit_after>package main

func rotate(nums []int, k int) {
	visited := make(map[int]bool)
	for i := 0; i < len(nums); i++ {
		if visited[i] {
			continue
		}
		prev := nums[i]
		j := (i + k) % len(nums)
		for !visited[j] {

			nums[j], prev = prev, nums[j]

			visited[j] = true
			j = (j + k) % len(nums)
		}
	}
}

func rotate2(nums []int, k int) {
	visited := 0
	// visit each position
	for i := 0; visited < len(nums); i++ {
		//store the first move
		prev := nums[i]
		// find where it should move
		j := (i + k) % len(nums)
		// while we haven't moved the one we are on continue
		for i != j {
			//do the swap, storing what was moved to
			nums[j], prev = prev, nums[j]
			//update what we've swapped
			visited++
			//calculate the next position
			j = (j + k) % len(nums)
		}
		// move the last umoved item back to i
		nums[i] = prev
		// update visited count
		visited++
	}
}
<|endoftext|>


<commit_before>package core

import (
	"bufio"
	"context"
	"fmt"
	"github.com/grandcat/zeroconf"
	"gopkg.in/cheggaaa/pb.v1"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"time"
)

func LookupZeroconf(id string, entries chan *zeroconf.ServiceEntry, stop chan bool) {
	resolver, err := zeroconf.NewResolver(nil)
	if err != nil {
		log.Fatalln("Failed to initialize resolver:", err.Error())
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// err = resolver.Lookup(ctx, id, "_figo._http._tcp", "local.", entries)
	err = resolver.Lookup(ctx, id, "_figo._http._tcp", "local.", entries)
	if err != nil {
		panic(err)
	}

	<-stop

	<-ctx.Done()
	return
}

func Figor(name string, out string) {
	log.SetOutput(ioutil.Discard)

	var entry *zeroconf.ServiceEntry

	{
		entries := make(chan *zeroconf.ServiceEntry)

		stopLookup := make(chan bool)
		go LookupZeroconf(GetHash(name), entries, stopLookup)

		{
			timer := time.NewTimer(time.Millisecond * 500)
			for i := 0; i < 2; i++ {
				loopDone := false
				select {
				case <-timer.C:
					fmt.Println("couldn't find anything!")
					fmt.Println("figos "+name, "or", "figos <filename> "+name)
				case entry = <-entries:
					timer.Stop()
					stopLookup <- true
					loopDone = true
				}
				if loopDone {
					break
				}
			}
		}
	}

	addr := entry.AddrIPv4[0]
	port := entry.Port

	urlPath := fmt.Sprintf("http://%v.%v.%v.%v:%d/%s", addr[0], addr[1], addr[2], addr[3], port, name)
	if resp, err := http.Get(urlPath); err != nil {
		panic(err)
	} else if resp.StatusCode != 200 {
		fmt.Println("Not correct file/code")
		os.Exit(1)
	} else {
		if out == "" {
			rgx := regexp.MustCompile("inline; filename=\"(.*)\"")
			out = rgx.FindStringSubmatch(resp.Header.Get("Content-Disposition"))[1]
		}
		if of, err := os.Create(out); err != nil {
			panic(err)
		} else {
			var datalen int
			fmt.Sscanf(resp.Header.Get("Content-Length"), "%d", &datalen)

			resp_buf := bufio.NewReader(resp.Body)
			of_buf := bufio.NewWriter(of)

			bar := pb.New(datalen).SetUnits(pb.U_BYTES).Prefix(out)
			bar.Start()
			bar_writer := io.MultiWriter(of_buf, bar)
			io.Copy(bar_writer, resp_buf)
			bar.Finish()
		}
	}
}
<commit_msg>cleaned prints<commit_after>package core

import (
	"bufio"
	"context"
	"fmt"
	"github.com/grandcat/zeroconf"
	"gopkg.in/cheggaaa/pb.v1"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"time"
)

func LookupZeroconf(id string, entries chan *zeroconf.ServiceEntry, stop chan bool) {
	resolver, err := zeroconf.NewResolver(nil)
	if err != nil {
		log.Fatalln("Failed to initialize resolver:", err.Error())
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// err = resolver.Lookup(ctx, id, "_figo._http._tcp", "local.", entries)
	err = resolver.Lookup(ctx, id, "_figo._http._tcp", "local.", entries)
	if err != nil {
		panic(err)
	}

	<-stop

	<-ctx.Done()
	return
}

func Figor(name string, out string) {
	log.SetOutput(ioutil.Discard)

	var entry *zeroconf.ServiceEntry

	{
		entries := make(chan *zeroconf.ServiceEntry)

		stopLookup := make(chan bool)
		go LookupZeroconf(GetHash(name), entries, stopLookup)

		{
			timer := time.NewTimer(time.Millisecond * 500)
			for i := 0; i < 2; i++ {
				loopDone := false
				select {
				case <-timer.C:
					fmt.Println("figos "+name, "or", "figos <filename> "+name)
				case entry = <-entries:
					timer.Stop()
					stopLookup <- true
					loopDone = true
				}
				if loopDone {
					break
				}
			}
		}
	}

	addr := entry.AddrIPv4[0]
	port := entry.Port

	urlPath := fmt.Sprintf("http://%v.%v.%v.%v:%d/%s", addr[0], addr[1], addr[2], addr[3], port, name)
	if resp, err := http.Get(urlPath); err != nil {
		panic(err)
	} else if resp.StatusCode != 200 {
		fmt.Println("Not correct file/code")
		os.Exit(1)
	} else {
		if out == "" {
			rgx := regexp.MustCompile("inline; filename=\"(.*)\"")
			out = rgx.FindStringSubmatch(resp.Header.Get("Content-Disposition"))[1]
		}
		if of, err := os.Create(out); err != nil {
			panic(err)
		} else {
			var datalen int
			fmt.Sscanf(resp.Header.Get("Content-Length"), "%d", &datalen)

			resp_buf := bufio.NewReader(resp.Body)
			of_buf := bufio.NewWriter(of)

			bar := pb.New(datalen).SetUnits(pb.U_BYTES).Prefix(out)
			bar.Start()
			bar_writer := io.MultiWriter(of_buf, bar)
			io.Copy(bar_writer, resp_buf)
			bar.Finish()
		}
	}
}
<|endoftext|>