<commit_before>// This package provides utilities that underlie the specific commands.
// The idea is to make the specific command files very small, e.g.:
//
//    func main() {
//      app := cmd.NewAppShell("command-name")
//      app.Action = func(c cmd.Config) {
//        // command logic
//      }
//      app.Run()
//    }
//
// All commands share the same invocation pattern.  They take a single
// parameter "-config", which is the name of a JSON file containing
// the configuration for the app.  This JSON file is unmarshalled into
// a Config object, which is provided to the app.

package cmd

import (
	"encoding/json"
	"encoding/pem"
	"errors"
	"expvar" // For DebugServer, below.
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"net"
	"net/http"
	_ "net/http/pprof" // HTTP performance profiling, added transparently to HTTP APIs
	"os"
	"os/signal"
	"path"
	"runtime"
	"syscall"
	"time"

	cfsslLog "github.com/cloudflare/cfssl/log"
	"github.com/go-sql-driver/mysql"
	"github.com/prometheus/client_golang/prometheus/promhttp"

	"github.com/letsencrypt/boulder/core"
	"github.com/letsencrypt/boulder/features"
	blog "github.com/letsencrypt/boulder/log"
	"github.com/letsencrypt/boulder/metrics"
)

// Because we don't know when this init will be called with respect to
// flag.Parse() and other flag definitions, we can't rely on the regular
// flag mechanism. But this one is fine.
func init() {
	for _, v := range os.Args {
		if v == "--version" || v == "-version" {
			fmt.Println(Version())
			os.Exit(0)
		}
	}
}

// Version returns a string representing the version of boulder running.
func Version() string {
	return fmt.Sprintf("0.1.0 [%s]", core.GetBuildID())
}

// mysqlLogger proxies blog.AuditLogger to provide a Print(...) method.
type mysqlLogger struct {
	blog.Logger
}

func (m mysqlLogger) Print(v ...interface{}) {
	m.AuditErr(fmt.Sprintf("[mysql] %s", fmt.Sprint(v...)))
}

// cfsslLogger provides two additional methods that are expected by CFSSL's
// logger but not supported by Boulder's Logger.
type cfsslLogger struct {
	blog.Logger
}

func (cl cfsslLogger) Crit(msg string) {
	cl.AuditErr(msg)
}

func (cl cfsslLogger) Emerg(msg string) {
	cl.AuditErr(msg)
}

// StatsAndLogging constructs a Statter and an AuditLogger based on its config
// parameters, and return them both. Crashes if any setup fails.
// Also sets the constructed AuditLogger as the default logger.
func StatsAndLogging(statConf StatsdConfig, logConf SyslogConfig) (metrics.Statter, blog.Logger) {
	stats, err := metrics.NewStatter(statConf.Server, statConf.Prefix)
	FailOnError(err, "Couldn't connect to statsd")

	tag := path.Base(os.Args[0])
	syslogger, err := syslog.Dial(
		"",
		"",
		syslog.LOG_INFO, // default, not actually used
		tag)
	FailOnError(err, "Could not connect to Syslog")
	syslogLevel := int(syslog.LOG_INFO)
	if logConf.SyslogLevel != 0 {
		syslogLevel = logConf.SyslogLevel
	}
	logger, err := blog.New(syslogger, logConf.StdoutLevel, syslogLevel)
	FailOnError(err, "Could not connect to Syslog")

	_ = blog.Set(logger)
	cfsslLog.SetLogger(cfsslLogger{logger})
	_ = mysql.SetLogger(mysqlLogger{logger})

	return stats, logger
}

// FailOnError exits and prints an error message if we encountered a problem
func FailOnError(err error, msg string) {
	if err != nil {
		logger := blog.Get()
		logger.AuditErr(fmt.Sprintf("%s: %s", msg, err))
		fmt.Fprintf(os.Stderr, "%s: %s\n", msg, err)
		os.Exit(1)
	}
}

// ProfileCmd runs forever, sending Go runtime statistics to StatsD.
func ProfileCmd(stats metrics.Scope) {
	stats = stats.NewScope("Gostats")
	var memoryStats runtime.MemStats
	prevNumGC := int64(0)
	c := time.Tick(1 * time.Second)
	for range c {
		runtime.ReadMemStats(&memoryStats)

		// Gather goroutine count
		stats.Gauge("Goroutines", int64(runtime.NumGoroutine()))

		// Gather various heap metrics
		stats.Gauge("Heap.Alloc", int64(memoryStats.HeapAlloc))
		stats.Gauge("Heap.Objects", int64(memoryStats.HeapObjects))
		stats.Gauge("Heap.Idle", int64(memoryStats.HeapIdle))
		stats.Gauge("Heap.InUse", int64(memoryStats.HeapInuse))
		stats.Gauge("Heap.Released", int64(memoryStats.HeapReleased))

		// Gather various GC related metrics
		if memoryStats.NumGC > 0 {
			totalRecentGC := uint64(0)
			realBufSize := uint32(256)
			if memoryStats.NumGC < 256 {
				realBufSize = memoryStats.NumGC
			}
			for _, pause := range memoryStats.PauseNs {
				totalRecentGC += pause
			}
			gcPauseAvg := totalRecentGC / uint64(realBufSize)
			lastGC := memoryStats.PauseNs[(memoryStats.NumGC+255)%256]
			stats.Timing("Gc.PauseAvg", int64(gcPauseAvg))
			stats.Gauge("Gc.LastPause", int64(lastGC))
		}
		stats.Gauge("Gc.NextAt", int64(memoryStats.NextGC))
		// Send both a counter and a gauge here we can much more easily observe
		// the GC rate (versus the raw number of GCs) in graphing tools that don't
		// like deltas
		stats.Gauge("Gc.Count", int64(memoryStats.NumGC))
		gcInc := int64(memoryStats.NumGC) - prevNumGC
		stats.Inc("Gc.Rate", gcInc)
		prevNumGC += gcInc
	}
}

// LoadCert loads a PEM-formatted certificate from the provided path, returning
// it as a byte array, or an error if it couldn't be decoded.
func LoadCert(path string) (cert []byte, err error) {
	if path == "" {
		err = errors.New("Issuer certificate was not provided in config.")
		return
	}
	pemBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	block, _ := pem.Decode(pemBytes)
	if block == nil || block.Type != "CERTIFICATE" {
		err = errors.New("Invalid certificate value returned")
		return
	}

	cert = block.Bytes
	return
}

// DebugServer starts a server to receive debug information.  Typical
// usage is to start it in a goroutine, configured with an address
// from the appropriate configuration object:
//
//   go cmd.DebugServer(c.XA.DebugAddr)
func DebugServer(addr string) {
	m := expvar.NewMap("enabled-features")
	features.Export(m)
	if addr == "" {
		log.Fatalf("unable to boot debug server because no address was given for it. Set debugAddr.")
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("unable to boot debug server on %#v", addr)
	}
	http.Handle("/metrics", promhttp.Handler())
	err = http.Serve(ln, nil)
	if err != nil {
		log.Fatalf("unable to boot debug server: %v", err)
	}
}

// ReadConfigFile takes a file path as an argument and attempts to
// unmarshal the content of the file into a struct containing a
// configuration of a boulder component.
func ReadConfigFile(filename string, out interface{}) error {
	configData, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return json.Unmarshal(configData, out)
}

// VersionString produces a friendly Application version string.
func VersionString(name string) string {
	return fmt.Sprintf("Versions: %s=(%s %s) Golang=(%s) BuildHost=(%s)", name, core.GetBuildID(), core.GetBuildTime(), runtime.Version(), core.GetBuildHost())
}

var signalToName = map[os.Signal]string{
	syscall.SIGTERM: "SIGTERM",
	syscall.SIGINT:  "SIGINT",
	syscall.SIGHUP:  "SIGHUP",
}

// CatchSignals catches SIGTERM, SIGINT, SIGHUP and executes a callback
// method before exiting
func CatchSignals(logger blog.Logger, callback func()) {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM)
	signal.Notify(sigChan, syscall.SIGINT)
	signal.Notify(sigChan, syscall.SIGHUP)

	sig := <-sigChan
	logger.Info(fmt.Sprintf("Caught %s", signalToName[sig]))

	if callback != nil {
		callback()
	}

	logger.Info("Exiting")
	os.Exit(0)
}
<commit_msg>Removes `cmd.Version()`.<commit_after>// This package provides utilities that underlie the specific commands.
// The idea is to make the specific command files very small, e.g.:
//
//    func main() {
//      app := cmd.NewAppShell("command-name")
//      app.Action = func(c cmd.Config) {
//        // command logic
//      }
//      app.Run()
//    }
//
// All commands share the same invocation pattern.  They take a single
// parameter "-config", which is the name of a JSON file containing
// the configuration for the app.  This JSON file is unmarshalled into
// a Config object, which is provided to the app.

package cmd

import (
	"encoding/json"
	"encoding/pem"
	"errors"
	"expvar" // For DebugServer, below.
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"net"
	"net/http"
	_ "net/http/pprof" // HTTP performance profiling, added transparently to HTTP APIs
	"os"
	"os/signal"
	"path"
	"runtime"
	"syscall"
	"time"

	cfsslLog "github.com/cloudflare/cfssl/log"
	"github.com/go-sql-driver/mysql"
	"github.com/prometheus/client_golang/prometheus/promhttp"

	"github.com/letsencrypt/boulder/core"
	"github.com/letsencrypt/boulder/features"
	blog "github.com/letsencrypt/boulder/log"
	"github.com/letsencrypt/boulder/metrics"
)

// Because we don't know when this init will be called with respect to
// flag.Parse() and other flag definitions, we can't rely on the regular
// flag mechanism. But this one is fine.
func init() {
	for _, v := range os.Args {
		if v == "--version" || v == "-version" {
			fmt.Println(VersionString(os.Args[0]))
			os.Exit(0)
		}
	}
}

// mysqlLogger proxies blog.AuditLogger to provide a Print(...) method.
type mysqlLogger struct {
	blog.Logger
}

func (m mysqlLogger) Print(v ...interface{}) {
	m.AuditErr(fmt.Sprintf("[mysql] %s", fmt.Sprint(v...)))
}

// cfsslLogger provides two additional methods that are expected by CFSSL's
// logger but not supported by Boulder's Logger.
type cfsslLogger struct {
	blog.Logger
}

func (cl cfsslLogger) Crit(msg string) {
	cl.AuditErr(msg)
}

func (cl cfsslLogger) Emerg(msg string) {
	cl.AuditErr(msg)
}

// StatsAndLogging constructs a Statter and an AuditLogger based on its config
// parameters, and return them both. Crashes if any setup fails.
// Also sets the constructed AuditLogger as the default logger.
func StatsAndLogging(statConf StatsdConfig, logConf SyslogConfig) (metrics.Statter, blog.Logger) {
	stats, err := metrics.NewStatter(statConf.Server, statConf.Prefix)
	FailOnError(err, "Couldn't connect to statsd")

	tag := path.Base(os.Args[0])
	syslogger, err := syslog.Dial(
		"",
		"",
		syslog.LOG_INFO, // default, not actually used
		tag)
	FailOnError(err, "Could not connect to Syslog")
	syslogLevel := int(syslog.LOG_INFO)
	if logConf.SyslogLevel != 0 {
		syslogLevel = logConf.SyslogLevel
	}
	logger, err := blog.New(syslogger, logConf.StdoutLevel, syslogLevel)
	FailOnError(err, "Could not connect to Syslog")

	_ = blog.Set(logger)
	cfsslLog.SetLogger(cfsslLogger{logger})
	_ = mysql.SetLogger(mysqlLogger{logger})

	return stats, logger
}

// FailOnError exits and prints an error message if we encountered a problem
func FailOnError(err error, msg string) {
	if err != nil {
		logger := blog.Get()
		logger.AuditErr(fmt.Sprintf("%s: %s", msg, err))
		fmt.Fprintf(os.Stderr, "%s: %s\n", msg, err)
		os.Exit(1)
	}
}

// ProfileCmd runs forever, sending Go runtime statistics to StatsD.
func ProfileCmd(stats metrics.Scope) {
	stats = stats.NewScope("Gostats")
	var memoryStats runtime.MemStats
	prevNumGC := int64(0)
	c := time.Tick(1 * time.Second)
	for range c {
		runtime.ReadMemStats(&memoryStats)

		// Gather goroutine count
		stats.Gauge("Goroutines", int64(runtime.NumGoroutine()))

		// Gather various heap metrics
		stats.Gauge("Heap.Alloc", int64(memoryStats.HeapAlloc))
		stats.Gauge("Heap.Objects", int64(memoryStats.HeapObjects))
		stats.Gauge("Heap.Idle", int64(memoryStats.HeapIdle))
		stats.Gauge("Heap.InUse", int64(memoryStats.HeapInuse))
		stats.Gauge("Heap.Released", int64(memoryStats.HeapReleased))

		// Gather various GC related metrics
		if memoryStats.NumGC > 0 {
			totalRecentGC := uint64(0)
			realBufSize := uint32(256)
			if memoryStats.NumGC < 256 {
				realBufSize = memoryStats.NumGC
			}
			for _, pause := range memoryStats.PauseNs {
				totalRecentGC += pause
			}
			gcPauseAvg := totalRecentGC / uint64(realBufSize)
			lastGC := memoryStats.PauseNs[(memoryStats.NumGC+255)%256]
			stats.Timing("Gc.PauseAvg", int64(gcPauseAvg))
			stats.Gauge("Gc.LastPause", int64(lastGC))
		}
		stats.Gauge("Gc.NextAt", int64(memoryStats.NextGC))
		// Send both a counter and a gauge here we can much more easily observe
		// the GC rate (versus the raw number of GCs) in graphing tools that don't
		// like deltas
		stats.Gauge("Gc.Count", int64(memoryStats.NumGC))
		gcInc := int64(memoryStats.NumGC) - prevNumGC
		stats.Inc("Gc.Rate", gcInc)
		prevNumGC += gcInc
	}
}

// LoadCert loads a PEM-formatted certificate from the provided path, returning
// it as a byte array, or an error if it couldn't be decoded.
func LoadCert(path string) (cert []byte, err error) {
	if path == "" {
		err = errors.New("Issuer certificate was not provided in config.")
		return
	}
	pemBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	block, _ := pem.Decode(pemBytes)
	if block == nil || block.Type != "CERTIFICATE" {
		err = errors.New("Invalid certificate value returned")
		return
	}

	cert = block.Bytes
	return
}

// DebugServer starts a server to receive debug information.  Typical
// usage is to start it in a goroutine, configured with an address
// from the appropriate configuration object:
//
//   go cmd.DebugServer(c.XA.DebugAddr)
func DebugServer(addr string) {
	m := expvar.NewMap("enabled-features")
	features.Export(m)
	if addr == "" {
		log.Fatalf("unable to boot debug server because no address was given for it. Set debugAddr.")
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("unable to boot debug server on %#v", addr)
	}
	http.Handle("/metrics", promhttp.Handler())
	err = http.Serve(ln, nil)
	if err != nil {
		log.Fatalf("unable to boot debug server: %v", err)
	}
}

// ReadConfigFile takes a file path as an argument and attempts to
// unmarshal the content of the file into a struct containing a
// configuration of a boulder component.
func ReadConfigFile(filename string, out interface{}) error {
	configData, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return json.Unmarshal(configData, out)
}

// VersionString produces a friendly Application version string.
func VersionString(name string) string {
	return fmt.Sprintf("Versions: %s=(%s %s) Golang=(%s) BuildHost=(%s)", name, core.GetBuildID(), core.GetBuildTime(), runtime.Version(), core.GetBuildHost())
}

var signalToName = map[os.Signal]string{
	syscall.SIGTERM: "SIGTERM",
	syscall.SIGINT:  "SIGINT",
	syscall.SIGHUP:  "SIGHUP",
}

// CatchSignals catches SIGTERM, SIGINT, SIGHUP and executes a callback
// method before exiting
func CatchSignals(logger blog.Logger, callback func()) {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM)
	signal.Notify(sigChan, syscall.SIGINT)
	signal.Notify(sigChan, syscall.SIGHUP)

	sig := <-sigChan
	logger.Info(fmt.Sprintf("Caught %s", signalToName[sig]))

	if callback != nil {
		callback()
	}

	logger.Info("Exiting")
	os.Exit(0)
}
<|endoftext|>


<commit_before>package cmd
<commit_msg>Initial commit<commit_after>package cmd

import (
	"strings"
	"os"
	"io"
	"fmt"
	"io/ioutil"
	"github.com/fatih/color"
)

//Check whether the given path contain a zip file
func isAZipFile(path string) bool {
	return strings.HasSuffix(path, ".zip")
}

//Check whether the given string is in the given slice
func stringIsInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

// Copies file source to destination dest.
func CopyFile(source string, dest string) (err error) {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()
	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err == nil {
		si, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, si.Mode())
			fmt.Println("Error occurred while copying:", err)
			os.Exit(1)
		}

	}
	return
}

//Recursively copies a directory tree, attempting to preserve permissions.
//Source directory must exist, destination directory must *not* exist.
func CopyDir(source string, dest string) (err error) {
	// get properties of source dir
	fi, err := os.Stat(source)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return &CustomError{"Source is not a directory"}
	}
	// ensure dest dir does not already exist
	_, err = os.Open(dest)
	if !os.IsNotExist(err) {
		return &CustomError{"Destination already exists"}
	}
	// create dest dir
	err = os.MkdirAll(dest, fi.Mode())
	if err != nil {
		return err
	}
	entries, err := ioutil.ReadDir(source)
	for _, entry := range entries {
		sfp := source + "/" + entry.Name()
		dfp := dest + "/" + entry.Name()
		if entry.IsDir() {
			err = CopyDir(sfp, dfp)
			if err != nil {
				fmt.Println("Error occurred while copying:", err)
				os.Exit(1)
			}
		} else {
			// perform copy
			err = CopyFile(sfp, dfp)
			if err != nil {
				fmt.Println("Error occurred while copying:", err)
				os.Exit(1)
			}
		}
	}
	return
}

//A struct for returning custom error messages
type CustomError struct {
	What string
}

//Returns the error message defined in What as a string
func (e *CustomError) Error() string {
	return e.What
}

//Check whether the given location points to a directory
func directoryExists(location string) bool {
	logger.Trace("Checking Location: %s", location)
	locationInfo, err := os.Stat(location)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	if locationInfo.IsDir() {
		return true
	}
	return false
}

//Check whether the given location points to a file
func fileExists(location string) bool {
	logger.Trace("Checking location: %s", location)
	locationInfo, err := os.Stat(location)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	if locationInfo.IsDir() {
		return false
	}
	return true
}

//This is used to print failure messages
func printFailure(args ...interface{}) {
	color.Set(color.FgRed)
	fmt.Println(append(append([]interface{}{"\n[FAILURE]"}, args...), "\n")...)
	color.Unset()
}
//This is used to print failure messages and exit
func printFailureAndExit(args ...interface{}) {
	printFailure(args...)
	os.Exit(1)
}

func printWarning(args ...interface{}) {
	color.Set(color.FgYellow)
	fmt.Println(append(append([]interface{}{"\n[WARNING]"}, args...), "\n")...)
	color.Unset()
}

func printInfo(args ...interface{}) {
	color.Set(color.FgYellow)
	fmt.Println(append(append([]interface{}{"\n[INFO]"}, args...), "\n")...)
	color.Unset()
}
<|endoftext|>


<commit_before>package oas

import (
	"github.com/TykTechnologies/tyk/apidef"
)

const ExtensionTykAPIGateway = "x-tyk-api-gateway"

type XTykAPIGateway struct {
	// Info contains the main metadata about the API definition.
	Info Info `bson:"info" json:"info"` // required
	// Upstream contains the configurations related to the upstream.
	Upstream Upstream `bson:"upstream" json:"upstream"` // required
	// Server contains the configurations related to the server.
	Server Server `bson:"server" json:"server"` // required
	// Middleware contains the configurations related to the proxy middleware.
	Middleware *Middleware `bson:"middleware,omitempty" json:"middleware,omitempty"`
}

func (x *XTykAPIGateway) Fill(api apidef.APIDefinition) {
	x.Info.Fill(api)
	x.Upstream.Fill(api)
	x.Server.Fill(api)

	if x.Middleware == nil {
		x.Middleware = &Middleware{}
	}

	x.Middleware.Fill(api)
	if ShouldOmit(x.Middleware) {
		x.Middleware = nil
	}
}

func (x *XTykAPIGateway) ExtractTo(api *apidef.APIDefinition) {
	x.Info.ExtractTo(api)
	x.Upstream.ExtractTo(api)
	x.Server.ExtractTo(api)

	if x.Middleware != nil {
		x.Middleware.ExtractTo(api)
	}

	// This is used to make API calls work before actual versioning implementation.
	api.VersionData.DefaultVersion = "Default"
	api.VersionData.NotVersioned = true
	api.VersionData.Versions = map[string]apidef.VersionInfo{
		"Default": {},
	}
}

type Info struct {
	// ID is the unique ID of the API.
	// Old API Definition: `api_id`
	ID string `bson:"id" json:"id,omitempty"`
	// DBID is the unique database ID of the API.
	// Old API Definition: `id`
	DBID apidef.ObjectId `bson:"dbID" json:"dbID,omitempty"`
	// OrgID is the ID of the organisation which the API belongs to.
	// Old API Definition: `org_id`
	OrgID string `bson:"orgID" json:"orgID,omitempty"`
	// Name is the name of the API.
	// Old API Definition: `name`
	Name string `bson:"name" json:"name"` // required
	// State contains the configurations related to the state of the API.
	State State `bson:"state" json:"state"` // required
}

func (i *Info) Fill(api apidef.APIDefinition) {
	i.ID = api.APIID
	i.DBID = api.Id
	i.OrgID = api.OrgID
	i.Name = api.Name
	i.State.Fill(api)
}

func (i *Info) ExtractTo(api *apidef.APIDefinition) {
	api.APIID = i.ID
	api.Id = i.DBID
	api.OrgID = i.OrgID
	api.Name = i.Name
	i.State.ExtractTo(api)
}

type State struct {
	// Active enables the API.
	// Old API Definition: `active`
	Active bool `bson:"active" json:"active"` // required
	// Internal makes the API accessible only internally.
	// Old API Definition: `internal`
	Internal bool `bson:"internal,omitempty" json:"internal,omitempty"`
}

func (s *State) Fill(api apidef.APIDefinition) {
	s.Active = api.Active
	s.Internal = api.Internal
}

func (s *State) ExtractTo(api *apidef.APIDefinition) {
	api.Active = s.Active
	api.Internal = s.Internal
}
<commit_msg>Change naming of OAS fields from ID to Id (#3742)<commit_after>package oas

import (
	"github.com/TykTechnologies/tyk/apidef"
)

const ExtensionTykAPIGateway = "x-tyk-api-gateway"

type XTykAPIGateway struct {
	// Info contains the main metadata about the API definition.
	Info Info `bson:"info" json:"info"` // required
	// Upstream contains the configurations related to the upstream.
	Upstream Upstream `bson:"upstream" json:"upstream"` // required
	// Server contains the configurations related to the server.
	Server Server `bson:"server" json:"server"` // required
	// Middleware contains the configurations related to the proxy middleware.
	Middleware *Middleware `bson:"middleware,omitempty" json:"middleware,omitempty"`
}

func (x *XTykAPIGateway) Fill(api apidef.APIDefinition) {
	x.Info.Fill(api)
	x.Upstream.Fill(api)
	x.Server.Fill(api)

	if x.Middleware == nil {
		x.Middleware = &Middleware{}
	}

	x.Middleware.Fill(api)
	if ShouldOmit(x.Middleware) {
		x.Middleware = nil
	}
}

func (x *XTykAPIGateway) ExtractTo(api *apidef.APIDefinition) {
	x.Info.ExtractTo(api)
	x.Upstream.ExtractTo(api)
	x.Server.ExtractTo(api)

	if x.Middleware != nil {
		x.Middleware.ExtractTo(api)
	}

	// This is used to make API calls work before actual versioning implementation.
	api.VersionData.DefaultVersion = "Default"
	api.VersionData.NotVersioned = true
	api.VersionData.Versions = map[string]apidef.VersionInfo{
		"Default": {},
	}
}

type Info struct {
	// ID is the unique ID of the API.
	// Old API Definition: `api_id`
	ID string `bson:"id" json:"id,omitempty"`
	// DBID is the unique database ID of the API.
	// Old API Definition: `id`
	DBID apidef.ObjectId `bson:"dbId" json:"dbId,omitempty"`
	// OrgID is the ID of the organisation which the API belongs to.
	// Old API Definition: `org_id`
	OrgID string `bson:"orgId" json:"orgId,omitempty"`
	// Name is the name of the API.
	// Old API Definition: `name`
	Name string `bson:"name" json:"name"` // required
	// State contains the configurations related to the state of the API.
	State State `bson:"state" json:"state"` // required
}

func (i *Info) Fill(api apidef.APIDefinition) {
	i.ID = api.APIID
	i.DBID = api.Id
	i.OrgID = api.OrgID
	i.Name = api.Name
	i.State.Fill(api)
}

func (i *Info) ExtractTo(api *apidef.APIDefinition) {
	api.APIID = i.ID
	api.Id = i.DBID
	api.OrgID = i.OrgID
	api.Name = i.Name
	i.State.ExtractTo(api)
}

type State struct {
	// Active enables the API.
	// Old API Definition: `active`
	Active bool `bson:"active" json:"active"` // required
	// Internal makes the API accessible only internally.
	// Old API Definition: `internal`
	Internal bool `bson:"internal,omitempty" json:"internal,omitempty"`
}

func (s *State) Fill(api apidef.APIDefinition) {
	s.Active = api.Active
	s.Internal = api.Internal
}

func (s *State) ExtractTo(api *apidef.APIDefinition) {
	api.Active = s.Active
	api.Internal = s.Internal
}
<|endoftext|>


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

// Rudimentary logging package. Defines a type, Logger, with simple
// methods for formatting output to one or two destinations. Also has
// predefined Loggers accessible through helper functions Stdout[f],
// Stderr[f], Exit[f], and Crash[f].
// Exit exits when written to.
// Crash causes a crash when written to.

package log

import (
	"fmt";
	"io";
	"os";
	"time";
)

const (
	// Flags
	Lok = iota;
	Lexit;	// terminate execution when written
	Lcrash;	// crash (panic) when written
	// Bits or'ed together to control what's printed. There is no control over the
	// order they appear (the order listed here) or the format they present (as
	// described in the comments).  A colon appears after these items:
	//	2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
	Ldate = 1 << iota;	// the date: 2009/0123
	Ltime;	// the time: 01:23:23
	Lmicroseconds;	// microsecond resolution: 01:23:23.123123.  assumes Ltime.
	Llongfile;	// full file name and line number: /a/b/c/d.go:23
	Lshortfile;	// final file name element and line number: d.go:23. overrides Llongfile
	lAllBits = Ldate | Ltime | Lmicroseconds | Llongfile | Lshortfile;
)

type Logger struct {
	out0	io.Write;
	out1	io.Write;
	prefix string;
	flag int;
}

func NewLogger(out0, out1 io.Write, prefix string, flag int) *Logger {
	return &Logger{out0, out1, prefix, flag}
}

var (
	stdout = NewLogger(os.Stdout, nil, "", Lok|Ldate|Ltime);
	stderr = NewLogger(os.Stderr, nil, "", Lok|Ldate|Ltime);
	exit = NewLogger(os.Stderr, nil, "", Lexit|Ldate|Ltime);
	crash = NewLogger(os.Stderr, nil, "", Lcrash|Ldate|Ltime);
)

var shortnames = make(map[string] string)	// cache of short names to avoid allocation.

// Cheap integer to fixed-width decimal ASCII.  Use a negative width to avoid zero-padding
func itoa(i int, wid int) string {
	var u uint = uint(i);
	if u == 0 && wid <= 1 {
		return "0"
	}

	// Assemble decimal in reverse order.
	var b [32]byte;
	bp := len(b);
	for ; u > 0 || wid > 0; u /= 10 {
		bp--;
		wid--;
		b[bp] = byte(u%10) + '0';
	}

	return string(b[bp:len(b)])
}

func (l *Logger) formatHeader(ns int64, calldepth int) string {
	h := l.prefix;
	if l.flag & (Ldate | Ltime | Lmicroseconds) != 0 {
		t := time.SecondsToLocalTime(ns/1e9);
		if l.flag & (Ldate) != 0 {
			h += itoa(int(t.Year), 4) + "/" + itoa(t.Month, 2) + itoa(t.Day, 2) + " "
		}
		if l.flag & (Ltime | Lmicroseconds) != 0 {
			h += itoa(t.Hour, 2) + ":" + itoa(t.Minute, 2) + ":" + itoa(t.Second, 2);
			if l.flag & Lmicroseconds != 0 {
				h += "." + itoa(int(ns % 1e9)/1e3, 6);
			}
			h += " ";
		}
	}
	if l.flag & (Lshortfile | Llongfile) != 0 {
		pc, file, line, ok := sys.Caller(calldepth);
		if ok {
			if l.flag & Lshortfile != 0 {
				short, ok := shortnames[file];
				if !ok {
					short = file;
					for i := len(file) - 1; i > 0; i-- {
						if file[i] == '/' {
							short = file[i+1:len(file)];
							break;
						}
					}
					shortnames[file] = short;
				}
				file = short;
			}
		} else {
			file = "???";
			line = 0;
		}
		h += file + ":" + itoa(line, -1) + ": ";
	}
	return h;
}

// The calldepth is provided for generality, although at the moment on all paths it will be 2.
func (l *Logger) Output(calldepth int, s string) {
	now := time.Nanoseconds();	// get this early.
	newline := "\n";
	if len(s) > 0 && s[len(s)-1] == '\n' {
		newline = ""
	}
	s = l.formatHeader(now, calldepth+1) + s + newline;
	io.WriteString(l.out0, s);
	if l.out1 != nil {
		io.WriteString(l.out1, s);
	}
	switch l.flag & ^lAllBits {
	case Lcrash:
		panic("log: fatal error");
	case Lexit:
		sys.Exit(1);
	}
}

// Basic methods on Logger, analogous to Printf and Print
func (l *Logger) Logf(format string, v ...) {
	l.Output(2, fmt.Sprintf(format, v))
}

func (l *Logger) Log(v ...) {
	l.Output(2, fmt.Sprintln(v))
}

// Helper functions for lightweight simple logging to predefined Loggers.
func Stdout(v ...) {
	stdout.Output(2, fmt.Sprint(v))
}

func Stderr(v ...) {
	stdout.Output(2, fmt.Sprintln(v))
}

func Stdoutf(format string, v ...) {
	stdout.Output(2, fmt.Sprintf(format, v))
}

func Stderrf(format string, v ...) {
	stderr.Output(2, fmt.Sprintf(format, v))
}

func Exit(v ...) {
	exit.Output(2, fmt.Sprintln(v))
}

func Exitf(format string, v ...) {
	exit.Output(2, fmt.Sprintf(format, v))
}

func Crash(v ...) {
	crash.Output(2, fmt.Sprintln(v))
}

func Crashf(format string, v ...) {
	crash.Output(2, fmt.Sprintf(format, v))
}
<commit_msg>log: document<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Rudimentary logging package. Defines a type, Logger, with simple
// methods for formatting output to one or two destinations. Also has
// predefined Loggers accessible through helper functions Stdout[f],
// Stderr[f], Exit[f], and Crash[f], which are easier to use than creating
// a Logger manually.
// Exit exits when written to.
// Crash causes a crash when written to.
package log

import (
	"fmt";
	"io";
	"os";
	"time";
)

// These flags define the properties of the Logger and the output they produce.
const (
	// Flags
	Lok = iota;
	Lexit;	// terminate execution when written
	Lcrash;	// crash (panic) when written
	// Bits or'ed together to control what's printed. There is no control over the
	// order they appear (the order listed here) or the format they present (as
	// described in the comments).  A colon appears after these items:
	//	2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
	Ldate = 1 << iota;	// the date: 2009/0123
	Ltime;	// the time: 01:23:23
	Lmicroseconds;	// microsecond resolution: 01:23:23.123123.  assumes Ltime.
	Llongfile;	// full file name and line number: /a/b/c/d.go:23
	Lshortfile;	// final file name element and line number: d.go:23. overrides Llongfile
	lAllBits = Ldate | Ltime | Lmicroseconds | Llongfile | Lshortfile;
)

// Logger represents an active logging object.
type Logger struct {
	out0	io.Write;	// first destination for output
	out1	io.Write;	// second destination for output; may be nil
	prefix string;	// prefix to write at beginning of each line
	flag int;	// properties
}

// NewLogger creates a new Logger.   The out0 and out1 variables set the
// destinations to which log data will be written; out1 may be nil.
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func NewLogger(out0, out1 io.Write, prefix string, flag int) *Logger {
	return &Logger{out0, out1, prefix, flag}
}

var (
	stdout = NewLogger(os.Stdout, nil, "", Lok|Ldate|Ltime);
	stderr = NewLogger(os.Stderr, nil, "", Lok|Ldate|Ltime);
	exit = NewLogger(os.Stderr, nil, "", Lexit|Ldate|Ltime);
	crash = NewLogger(os.Stderr, nil, "", Lcrash|Ldate|Ltime);
)

var shortnames = make(map[string] string)	// cache of short names to avoid allocation.

// Cheap integer to fixed-width decimal ASCII.  Use a negative width to avoid zero-padding
func itoa(i int, wid int) string {
	var u uint = uint(i);
	if u == 0 && wid <= 1 {
		return "0"
	}

	// Assemble decimal in reverse order.
	var b [32]byte;
	bp := len(b);
	for ; u > 0 || wid > 0; u /= 10 {
		bp--;
		wid--;
		b[bp] = byte(u%10) + '0';
	}

	return string(b[bp:len(b)])
}

func (l *Logger) formatHeader(ns int64, calldepth int) string {
	h := l.prefix;
	if l.flag & (Ldate | Ltime | Lmicroseconds) != 0 {
		t := time.SecondsToLocalTime(ns/1e9);
		if l.flag & (Ldate) != 0 {
			h += itoa(int(t.Year), 4) + "/" + itoa(t.Month, 2) + itoa(t.Day, 2) + " "
		}
		if l.flag & (Ltime | Lmicroseconds) != 0 {
			h += itoa(t.Hour, 2) + ":" + itoa(t.Minute, 2) + ":" + itoa(t.Second, 2);
			if l.flag & Lmicroseconds != 0 {
				h += "." + itoa(int(ns % 1e9)/1e3, 6);
			}
			h += " ";
		}
	}
	if l.flag & (Lshortfile | Llongfile) != 0 {
		pc, file, line, ok := sys.Caller(calldepth);
		if ok {
			if l.flag & Lshortfile != 0 {
				short, ok := shortnames[file];
				if !ok {
					short = file;
					for i := len(file) - 1; i > 0; i-- {
						if file[i] == '/' {
							short = file[i+1:len(file)];
							break;
						}
					}
					shortnames[file] = short;
				}
				file = short;
			}
		} else {
			file = "???";
			line = 0;
		}
		h += file + ":" + itoa(line, -1) + ": ";
	}
	return h;
}

// Output writes the output for a logging event.  The string s contains the text to print after
// the time stamp;  calldepth is used to recover the PC.  It is provided for generality, although
// at the moment on all pre-defined paths it will be 2.
func (l *Logger) Output(calldepth int, s string) {
	now := time.Nanoseconds();	// get this early.
	newline := "\n";
	if len(s) > 0 && s[len(s)-1] == '\n' {
		newline = ""
	}
	s = l.formatHeader(now, calldepth+1) + s + newline;
	io.WriteString(l.out0, s);
	if l.out1 != nil {
		io.WriteString(l.out1, s);
	}
	switch l.flag & ^lAllBits {
	case Lcrash:
		panic("log: fatal error");
	case Lexit:
		sys.Exit(1);
	}
}

// Logf is analogous to Printf() for a Logger.
func (l *Logger) Logf(format string, v ...) {
	l.Output(2, fmt.Sprintf(format, v))
}

// Log is analogouts to Print() for a Logger.
func (l *Logger) Log(v ...) {
	l.Output(2, fmt.Sprintln(v))
}

// Stdout is a helper function for easy logging to stdout. It is analogous to Print().
func Stdout(v ...) {
	stdout.Output(2, fmt.Sprint(v))
}

// Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr).
func Stderr(v ...) {
	stdout.Output(2, fmt.Sprintln(v))
}

// Stdoutf is a helper functions for easy formatted logging to stdout. It is analogous to Printf().
func Stdoutf(format string, v ...) {
	stdout.Output(2, fmt.Sprintf(format, v))
}

// Stderrf is a helper function for easy formatted logging to stderr. It is analogous to Fprintf(os.Stderr).
func Stderrf(format string, v ...) {
	stderr.Output(2, fmt.Sprintf(format, v))
}

// Exit is equivalent to Stderr() followed by a call to sys.Exit(1).
func Exit(v ...) {
	exit.Output(2, fmt.Sprintln(v))
}

// Exitf is equivalent to Stderrf() followed by a call to sys.Exit(1).
func Exitf(format string, v ...) {
	exit.Output(2, fmt.Sprintf(format, v))
}

// Crash is equivalent to Stderrf() followed by a call to panic().
func Crash(v ...) {
	crash.Output(2, fmt.Sprintln(v))
}

// Crashf is equivalent to Stderrf() followed by a call to panic().
func Crashf(format string, v ...) {
	crash.Output(2, fmt.Sprintf(format, v))
}
<|endoftext|>


<commit_before>package cache

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"testing"
)

func TestDownloadFile(t *testing.T) {
	cacheDir := createTmpDir(t)
	defer os.RemoveAll(cacheDir)

	hash := createRandomFile(cacheDir, 1024)

	e := NewEnsureSpacer(1, 1)
	h := NewHTTPCache(cacheDir, 1024, e)

	req, err := http.NewRequest("GET", "/cas/"+hash, nil)
	if err != nil {
		t.Error(err)
	}
	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(h.CacheHandler)
	handler.ServeHTTP(rr, req)

	if status := rr.Code; status != http.StatusOK {
		t.Error("Handler returned wrong status code",
			"expected", http.StatusOK,
			"got", status,
		)
	}

	rsp := rr.Result()
	if contentLen := rsp.ContentLength; contentLen != 1024 {
		t.Error("Handler returned file with wrong content length",
			"expected", 1024,
			"got", contentLen)
	}

	hasher := sha256.New()
	io.Copy(hasher, rsp.Body)
	if actualHash := hex.EncodeToString(hasher.Sum(nil)); actualHash != hash {
		t.Error("Received the wrong content.",
			"expected hash", hash,
			"actualHash", actualHash,
		)
	}
}

func TestUploadFilesConcurrently(t *testing.T) {
	cacheDir := createTmpDir(t)
	defer os.RemoveAll(cacheDir)

	const NumUploads = 1000

	var requests [NumUploads]*http.Request
	for i := 0; i < NumUploads; i++ {
		data, hash := randomDataAndHash(1024)
		r, err := http.NewRequest("PUT", "/cas/"+hash, bytes.NewReader(data))
		if err != nil {
			t.Error(err)
		}
		requests[i] = r
	}

	e := NewEnsureSpacer(0.3, 0.1)
	h := NewHTTPCache(cacheDir, 10000*1024, e)
	handler := http.HandlerFunc(h.CacheHandler)

	var wg sync.WaitGroup
	wg.Add(len(requests))
	for _, request := range requests {
		go func(request *http.Request) {
			defer wg.Done()
			rr := httptest.NewRecorder()
			handler.ServeHTTP(rr, request)

			if status := rr.Code; status != http.StatusOK {
				t.Error("Handler returned wrong status code",
					"expected", http.StatusOK,
					"got", status,
				)
			}
		}(request)
	}

	wg.Wait()
}
<commit_msg>httptest: check for purging<commit_after>package cache

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"testing"
)

func TestDownloadFile(t *testing.T) {
	cacheDir := createTmpDir(t)
	defer os.RemoveAll(cacheDir)

	hash := createRandomFile(cacheDir, 1024)

	e := NewEnsureSpacer(1, 1)
	h := NewHTTPCache(cacheDir, 1024, e)

	req, err := http.NewRequest("GET", "/cas/"+hash, nil)
	if err != nil {
		t.Error(err)
	}
	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(h.CacheHandler)
	handler.ServeHTTP(rr, req)

	if status := rr.Code; status != http.StatusOK {
		t.Error("Handler returned wrong status code",
			"expected", http.StatusOK,
			"got", status,
		)
	}

	rsp := rr.Result()
	if contentLen := rsp.ContentLength; contentLen != 1024 {
		t.Error("Handler returned file with wrong content length",
			"expected", 1024,
			"got", contentLen)
	}

	hasher := sha256.New()
	io.Copy(hasher, rsp.Body)
	if actualHash := hex.EncodeToString(hasher.Sum(nil)); actualHash != hash {
		t.Error("Received the wrong content.",
			"expected hash", hash,
			"actualHash", actualHash,
		)
	}
}

func TestUploadFilesConcurrently(t *testing.T) {
	cacheDir := createTmpDir(t)
	defer os.RemoveAll(cacheDir)

	const NumUploads = 1000

	var requests [NumUploads]*http.Request
	for i := 0; i < NumUploads; i++ {
		data, hash := randomDataAndHash(1024)
		r, err := http.NewRequest("PUT", "/cas/"+hash, bytes.NewReader(data))
		if err != nil {
			t.Error(err)
		}
		requests[i] = r
	}

	e := NewEnsureSpacer(0.8, 0.5)
	h := NewHTTPCache(cacheDir, 1000*1024, e)
	handler := http.HandlerFunc(h.CacheHandler)

	var wg sync.WaitGroup
	wg.Add(len(requests))
	for _, request := range requests {
		go func(request *http.Request) {
			defer wg.Done()
			rr := httptest.NewRecorder()
			handler.ServeHTTP(rr, request)

			if status := rr.Code; status != http.StatusOK {
				t.Error("Handler returned wrong status code",
					"expected", http.StatusOK,
					"got", status,
				)
			}
		}(request)
	}

	wg.Wait()

	f, err := os.Open(cacheDir)
	defer f.Close()
	if err != nil {
		t.Error(err)
	}
	files, err := f.Readdir(-1)
	if err != nil {
		t.Error(err)
	}
	var totalSize int64
	for _, fileinfo := range files {
		size := fileinfo.Size()
		if size != 1024 {
			t.Error("Expected all files to be 1024 bytes.", "Got", size)
		}
		totalSize += fileinfo.Size()
	}

	// Test that purging worked and kept cache size in check.
	if upperBound := int64(NumUploads) * 1024 * 1024; totalSize > upperBound {
		t.Error("Cache size too big. Expected at most", upperBound, "got",
			totalSize)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/icza/gowut/gwu"
)

type account struct {
	Id       int    `json:"id,omitempty"`
	Username string `json:"username"`
	Name     string `json:"name"`
	Email    string `json:"email"`
}

type accounts []account

func adduserform() gwu.Panel {
	addform := gwu.NewVerticalPanel()
	addform.Style().SetBorder2(1, gwu.BrdStyleSolid, gwu.ClrBlack)
	addform.SetCellPadding(10)
	addform.SetAttr("width", "800")
	addform.Add(gwu.NewLabel("Add New Accounts"))

	var usernames []gwu.TextBox
	var names []gwu.TextBox
	var emails []gwu.TextBox

	for i := 0; i < 3; i++ {
		p := gwu.NewHorizontalPanel()
		p.SetCellPadding(2)
		p.Add(gwu.NewLabel("Username:"))
		tbusername := gwu.NewTextBox("")
		p.Add(tbusername)
		p.Add(gwu.NewLabel("Name:"))
		tbname := gwu.NewTextBox("")
		p.Add(tbname)
		p.Add(gwu.NewLabel("Email:"))
		tbemail := gwu.NewTextBox("")
		p.Add(tbemail)

		usernames = append(usernames, tbusername)
		names = append(names, tbname)
		emails = append(emails, tbemail)

		addform.Add(p)
	}

	btnadd := gwu.NewButton("Add")
	btnadd.SetAttr("align", "center")
	btnadd.AddEHandler(&myBtnAdd{usernames, names, emails}, gwu.ETypeClick)
	addform.Add(btnadd)

	return addform
}

type myBtnDelete struct {
	id     int
	parent gwu.Panel
	panel  gwu.Panel
}

func (h *myBtnDelete) HandleEvent(e gwu.Event) {
	if _, isButton := e.Src().(gwu.Button); isButton {

		fmt.Println("Delete called")
		fmt.Println("Id:", h.id)
		fmt.Println("Parent:", h.parent.Id().String())
		fmt.Println("Panel:", h.panel.Id().String())

		//TODO Call Add REST API

		h.parent.Remove(h.panel)

		e.MarkDirty(h.parent)
	}
}

type myBtnAdd struct {
	usernames []gwu.TextBox
	names     []gwu.TextBox
	emails    []gwu.TextBox
}

func (h *myBtnAdd) HandleEvent(e gwu.Event) {
	if _, isButton := e.Src().(gwu.Button); isButton {

		fmt.Println("Add called")

		for i := 0; i < 3; i++ {
			fmt.Println("Username: " + h.usernames[i].Text())
			fmt.Println("Name: " + h.names[i].Text())
			fmt.Println("Email: " + h.emails[i].Text())

			if len(h.usernames[i].Text()) == 0 ||
				len(h.names[i].Text()) == 0 ||
				len(h.emails[i].Text()) == 0 {
				continue
			}

			//TODO Call Add REST API

			h.usernames[i].SetText("")
			h.names[i].SetText("")
			h.emails[i].SetText("")

			e.MarkDirty(h.usernames[i])
			e.MarkDirty(h.names[i])
			e.MarkDirty(h.emails[i])
		}
	}
}

func refresh(address string, port int, parent gwu.Panel, panels []gwu.Panel) {
	for i := 0; i < len(panels); i++ {
		parent.Remove(panels[i])
	}

	url := "http://" + address + ":" + strconv.Itoa(port) + "/user"
	fmt.Println("URL:>", url)

	req, err := http.NewRequest("GET", url, nil)
	//req.Header.Set("X-Custom-Header", "myvalue")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := resp.Body.Close(); err != nil {
		panic(err)
	}

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)
	fmt.Println("response Body:", string(body))

	var accts accounts
	err = json.Unmarshal(body, &accts)

	for i := 0; i < len(accts); i++ {
		fmt.Println("Id:", accts[i].Id)
		fmt.Println("Username:", accts[i].Username)
		fmt.Println("Name:", accts[i].Name)
		fmt.Println("Email:", accts[i].Email)

		p := gwu.NewHorizontalPanel()
		p.SetCellPadding(2)
		p.Add(gwu.NewLabel("Username: " + accts[i].Username))
		p.Add(gwu.NewLabel("Name: " + accts[i].Name))
		p.Add(gwu.NewLabel("Email: " + accts[i].Email))

		btndelete := gwu.NewButton("Delete")
		btndelete.SetAttr("align", "center")
		btndelete.AddEHandler(&myBtnDelete{accts[i].Id, parent, p}, gwu.ETypeClick)
		p.Add(btndelete)

		fmt.Println("Panel Id:", p.Id().String())

		panels = append(panels, p)

		parent.Add(p)
	}
}

type myBtnRefresh struct {
	address string
	port    int
	parent  gwu.Panel
	panels  []gwu.Panel
}

func (h *myBtnRefresh) HandleEvent(e gwu.Event) {
	if _, isButton := e.Src().(gwu.Button); isButton {

		fmt.Println("Refresh called")
		fmt.Println("address:", h.address)
		fmt.Println("port:", h.port)
		fmt.Println("parent:", h.parent.Id().String())
		for i := 0; i < len(h.panels); i++ {
			fmt.Println("panel:", h.panels[i].Id().String())
		}

		refresh(h.address, h.port, h.parent, h.panels)

		e.MarkDirty(h.parent)
	}
}

func listuserform(address string, port int) gwu.Panel {
	acctlist := gwu.NewVerticalPanel()
	acctlist.Style().SetBorder2(1, gwu.BrdStyleSolid, gwu.ClrBlack)
	acctlist.SetCellPadding(10)
	acctlist.SetAttr("width", "800")

	var panels []gwu.Panel

	title2 := gwu.NewHorizontalPanel()
	title2.SetCellPadding(2)
	title2.Add(gwu.NewLabel("Current List of Accounts"))
	btnrefresh := gwu.NewButton("Refresh")
	btnrefresh.SetAttr("align", "center")
	btnrefresh.AddEHandler(&myBtnRefresh{address, port, acctlist, panels}, gwu.ETypeClick)
	title2.Add(btnrefresh)

	acctlist.Add(title2)

	//get current list of accounts
	refresh(address, port, acctlist, panels)

	return acctlist
}

func main() {
	//define flags
	var port int
	flag.IntVar(&port, "port", 9000, "the REST server in which to bind to")
	var address string
	flag.StringVar(&address, "address", "127.0.0.1", "the REST server in which to bind to")
	//parse
	flag.Parse()

	// Create and build a window
	win := gwu.NewWindow("main", "3-Tier App Demo")
	win.Style().SetFullWidth()
	win.SetHAlign(gwu.HACenter)
	win.SetCellPadding(2)

	//Add users
	win.Add(adduserform())

	//Display users...
	win.Add(listuserform(address, port))

	// Create and start a GUI server (omitting error check)
	server := gwu.NewServer("", "127.0.0.1:8000")
	server.SetText("Test GUI App")
	server.AddWin(win)
	server.Start("") // Also opens windows list in browser
}
<commit_msg>Final version of 3 tier app<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/icza/gowut/gwu"
)

type account struct {
	Id       int    `json:"id,omitempty"`
	Username string `json:"username"`
	Name     string `json:"name"`
	Email    string `json:"email"`
}

type accounts []account

func refreshRestApi(address string, port int) accounts {
	url := "http://" + address + ":" + strconv.Itoa(port) + "/user"
	fmt.Println("URL:>", url)

	req, err := http.NewRequest("GET", url, nil)
	//req.Header.Set("X-Custom-Header", "myvalue")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := resp.Body.Close(); err != nil {
		panic(err)
	}

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)
	fmt.Println("response Body:", string(body))

	var accts accounts
	err = json.Unmarshal(body, &accts)

	for i := 0; i < len(accts); i++ {
		fmt.Println("Id:", accts[i].Id)
		fmt.Println("Username:", accts[i].Username)
		fmt.Println("Name:", accts[i].Name)
		fmt.Println("Email:", accts[i].Email)
	}

	return accts
}

func addRestApi(address string, port int, accts accounts) accounts {
	url := "http://" + address + ":" + strconv.Itoa(port) + "/user"
	fmt.Println("URL:>", url)

	response, err := json.MarshalIndent(accts, "", "  ")
	if err != nil {
		panic(err) //not expecting error... just a short cut
	}

	fmt.Println("response:", string(response))

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(response))
	//req.Header.Set("X-Custom-Header", "myvalue")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := resp.Body.Close(); err != nil {
		panic(err)
	}

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)
	fmt.Println("response Body:", string(body))

	var newaccts accounts
	err = json.Unmarshal(body, &newaccts)

	for i := 0; i < len(accts); i++ {
		fmt.Println("Id:", newaccts[i].Id)
		fmt.Println("Username:", newaccts[i].Username)
		fmt.Println("Name:", newaccts[i].Name)
		fmt.Println("Email:", newaccts[i].Email)
	}

	return newaccts
}

func deleteRestApi(address string, port int, id int) {
	url := "http://" + address + ":" + strconv.Itoa(port) + "/user/" + strconv.Itoa(id)
	fmt.Println("URL:>", url)

	req, err := http.NewRequest("DELETE", url, nil)
	//req.Header.Set("X-Custom-Header", "myvalue")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := resp.Body.Close(); err != nil {
		panic(err)
	}

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)
	fmt.Println("response Body:", string(body))
}

type myBtnDelete struct {
	address string
	port    int
	id      int
	parent  gwu.Panel
	panel   gwu.Panel
}

func (h *myBtnDelete) HandleEvent(e gwu.Event) {
	if _, isButton := e.Src().(gwu.Button); isButton {

		fmt.Println("Delete called")
		fmt.Println("Id:", h.id)
		fmt.Println("Parent:", h.parent.Id().String())
		fmt.Println("Panel:", h.panel.Id().String())

		deleteRestApi(h.address, h.port, h.id)

		h.parent.Remove(h.panel)

		e.MarkDirty(h.parent)
	}
}

type myBtnAdd struct {
	address   string
	port      int
	usernames []gwu.TextBox
	names     []gwu.TextBox
	emails    []gwu.TextBox
	acctlist  gwu.Panel
}

func (h *myBtnAdd) HandleEvent(e gwu.Event) {
	if _, isButton := e.Src().(gwu.Button); isButton {

		fmt.Println("Add called")

		var accts accounts

		for i := 0; i < 3; i++ {
			fmt.Println("Username: " + h.usernames[i].Text())
			fmt.Println("Name: " + h.names[i].Text())
			fmt.Println("Email: " + h.emails[i].Text())

			if len(h.usernames[i].Text()) == 0 ||
				len(h.names[i].Text()) == 0 ||
				len(h.emails[i].Text()) == 0 {
				continue
			}

			accts = append(accts, account{0, h.usernames[i].Text(), h.names[i].Text(), h.emails[i].Text()})

			h.usernames[i].SetText("")
			h.names[i].SetText("")
			h.emails[i].SetText("")

			e.MarkDirty(h.usernames[i])
			e.MarkDirty(h.names[i])
			e.MarkDirty(h.emails[i])
		}

		newaccts := addRestApi(h.address, h.port, accts)

		for i := 0; i < len(newaccts); i++ {
			p := gwu.NewHorizontalPanel()
			p.SetCellPadding(2)
			p.Add(gwu.NewLabel("Username: " + newaccts[i].Username))
			p.Add(gwu.NewLabel("Name: " + newaccts[i].Name))
			p.Add(gwu.NewLabel("Email: " + newaccts[i].Email))

			btndelete := gwu.NewButton("Delete")
			btndelete.SetAttr("align", "center")
			btndelete.AddEHandler(&myBtnDelete{h.address, h.port, newaccts[i].Id, h.acctlist, p}, gwu.ETypeClick)
			p.Add(btndelete)

			fmt.Println("Panel Id:", p.Id().String())

			h.acctlist.Add(p)
		}

		e.MarkDirty(h.acctlist)
	}
}

func refresh(address string, port int, parent gwu.Panel) {
	accts := refreshRestApi(address, port)

	for i := 0; i < len(accts); i++ {
		p := gwu.NewHorizontalPanel()
		p.SetCellPadding(2)
		p.Add(gwu.NewLabel("Username: " + accts[i].Username))
		p.Add(gwu.NewLabel("Name: " + accts[i].Name))
		p.Add(gwu.NewLabel("Email: " + accts[i].Email))

		btndelete := gwu.NewButton("Delete")
		btndelete.SetAttr("align", "center")
		btndelete.AddEHandler(&myBtnDelete{address, port, accts[i].Id, parent, p}, gwu.ETypeClick)
		p.Add(btndelete)

		fmt.Println("Panel Id:", p.Id().String())

		parent.Add(p)
	}
}

func adduserform(address string, port int, acctlist gwu.Panel) gwu.Panel {
	addform := gwu.NewVerticalPanel()
	addform.Style().SetBorder2(1, gwu.BrdStyleSolid, gwu.ClrBlack)
	addform.SetCellPadding(10)
	addform.SetAttr("width", "800")
	addform.Add(gwu.NewLabel("Add New Accounts"))

	var usernames []gwu.TextBox
	var names []gwu.TextBox
	var emails []gwu.TextBox

	for i := 0; i < 3; i++ {
		p := gwu.NewHorizontalPanel()
		p.SetCellPadding(2)
		p.Add(gwu.NewLabel("Username:"))
		tbusername := gwu.NewTextBox("")
		p.Add(tbusername)
		p.Add(gwu.NewLabel("Name:"))
		tbname := gwu.NewTextBox("")
		p.Add(tbname)
		p.Add(gwu.NewLabel("Email:"))
		tbemail := gwu.NewTextBox("")
		p.Add(tbemail)

		usernames = append(usernames, tbusername)
		names = append(names, tbname)
		emails = append(emails, tbemail)

		addform.Add(p)
	}

	btnadd := gwu.NewButton("Add")
	btnadd.SetAttr("align", "center")
	btnadd.AddEHandler(&myBtnAdd{address, port, usernames, names, emails, acctlist}, gwu.ETypeClick)
	addform.Add(btnadd)

	return addform
}

func listuserform(address string, port int) gwu.Panel {
	acctlist := gwu.NewVerticalPanel()
	acctlist.Style().SetBorder2(1, gwu.BrdStyleSolid, gwu.ClrBlack)
	acctlist.SetCellPadding(10)
	acctlist.SetAttr("width", "800")

	acctlist.Add(gwu.NewLabel("Current List of Accounts"))

	//get current list of accounts
	refresh(address, port, acctlist)

	return acctlist
}

func main() {
	//define flags
	var port int
	flag.IntVar(&port, "port", 9000, "the REST server in which to bind to")
	var address string
	flag.StringVar(&address, "address", "127.0.0.1", "the REST server in which to bind to")
	//parse
	flag.Parse()

	// Create and build a window
	win := gwu.NewWindow("main", "3-Tier App Demo")
	win.Style().SetFullWidth()
	win.SetHAlign(gwu.HACenter)
	win.SetCellPadding(2)

	//Display users...
	acctlist := listuserform(address, port)
	win.Add(acctlist)

	//Add users
	win.Add(adduserform(address, port, acctlist))

	// Create and start a GUI server (omitting error check)
	server := gwu.NewServer("", "127.0.0.1:8000")
	server.SetText("Test GUI App")
	server.AddWin(win)
	server.Start("") // Also opens windows list in browser
}
<|endoftext|>


<commit_before>package main

import (
	"./meizar"
	"./rule"
	"flag"
	"net/http"
	"runtime"
	"strings"
)

var dir *string = flag.String("dir", "./images/", "")
var startPage *int = flag.Int("start", 2009, "")
var userCookie *string = flag.String("cookie", "1092990552=903f5Z2FA411DxfPYORhRDmNqohZzkNsnLuvj76u; PHPSESSID=vq5be8aobr23gdt68ig0mmud31; 1092990552=0; _gat=1; jdna=596e6fb28c1bb47f949e65e1ae03f7f5#1465139210979; Hm_lvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1465130953,1465137904; Hm_lpvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1465139211; _ga=GA1.2.1645811469.1465130953", "")
var client *http.Client = &http.Client{}

func init() {
	flag.Parse()
	if !strings.HasSuffix(*dir, "/") {
		*dir = *dir + "/"
	}
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	meizar.New(*dir, *startPage, &rule.JandanRule{}, *userCookie, client).Start()
}
<commit_msg>add RuleProvider method and A new Rule<commit_after>package main

import (
	"./meizar"
	"./rule"
	"flag"
	"net/http"
	"runtime"
	"strings"
)

var dir *string = flag.String("dir", "./images/", "")
var startPage *int = flag.Int("start", 2009, "")
var userCookie *string = flag.String("cookie", "1092990552=903f5Z2FA411DxfPYORhRDmNqohZzkNsnLuvj76u; PHPSESSID=vq5be8aobr23gdt68ig0mmud31; 1092990552=0; _gat=1; jdna=596e6fb28c1bb47f949e65e1ae03f7f5#1465139210979; Hm_lvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1465130953,1465137904; Hm_lpvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1465139211; _ga=GA1.2.1645811469.1465130953", "")
var client *http.Client = &http.Client{}

func init() {
	flag.Parse()
	if !strings.HasSuffix(*dir, "/") {
		*dir = *dir + "/"
	}
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	meizar.New(*dir, *startPage, rule.RuleProvider(), *userCookie, client).Start()
}
<|endoftext|>


<commit_before>package hermes

import (
	"encoding/json"
	"io/ioutil"
	"time"
)

type (
	// Sources struct to model a Type we want to ingest into the elasticsearch index
	// and the links we want to crawl/scrape information to store in our index/type
	Sources struct {
		Links []string `json:"links"` // an array of all the URL strings we want to start our crawler at
	}

	// Settings struct to model the settings we want to run our hermes application with.
	Settings struct {
		ElasticsearchHost  string        `json:"esHost"`           // host address for the elasticsearch instance
		ElasticsearchIndex string        `json:"esIndex"`          // index name you are going to ingest data into
		ElasticsearchType  string        `json:"esType"`           // type name you are going to ingest data into
		CrawlDelay         time.Duration `json:"crawlDelay"`       // delay time for the crawler to abide to
		CancelDuration     time.Duration `json:"cancelDuration"`   // time duration for canceling the crawler (immediate cancel)
		CancelAtURL        string        `json:"cancelUrl"`        // specific URL to cancel the crawler at
		StopDuration       time.Duration `json:"stopDuration"`     // time duration for stopping the crawler (processes links on queue after duration time)
		StopAtURL          string        `json:"stopUrl"`          // specific URL to stop the crawler at for a specific "root"
		MemStatsInterval   time.Duration `json:"memStatsInterval"` // display memory statistics at a given interval
		UserAgent          string        `json:"userAgent"`        // set the user agent string for the crawler... to be polite and identify yourself
		WorkerIdleTTL      time.Duration `json:"workerTimeout"`    // time-to-live for a host URL's goroutine
	}
)

// ParseLinks will parse the local data.json file that is in the same directory as the executable.
// The json file will be a "master" list of links we are going to crawl through.
func ParseLinks() Sources {
	var s Sources
	data, errRead := ioutil.ReadFile("./data.json")
	if errRead != nil {
		panic(errRead)
	}

	errUnmarshal := json.Unmarshal(data, &s)
	if errUnmarshal != nil {
		panic(errUnmarshal)
	}

	return s
}

// ParseSettings will parse a local settings.json file that is in the same directory as the executable.
// The json file will be all the configuration set by the user for the application.
func ParseSettings() Settings {
	var s Settings
	data, errRead := ioutil.ReadFile("./settings.json")
	if errRead != nil {
		panic(errRead)
	}

	errUnmarshal := json.Unmarshal(data, &s)
	if errUnmarshal != nil {
		panic(errUnmarshal)
	}

	return s
}
<commit_msg>refactor of custom settings parser<commit_after>package hermes

import (
	"encoding/json"
	"io/ioutil"
	"time"
)

type (
	// CustomSettings struct to model custom settings we want to scrape from a specific page
	CustomSettings struct {
		RootLink string   `json:"link"`
		Tags     []string `json:"tags"`
	}

	// Sources struct to model a Type we want to ingest into the elasticsearch index
	// and the links we want to crawl/scrape information to store in our index/type
	Sources struct {
		Links []CustomSettings `json:"links"` // an array of all the URL strings we want to start our crawler at
	}

	// Settings struct to model the settings we want to run our hermes application with.
	Settings struct {
		ElasticsearchHost  string        `json:"esHost"`           // host address for the elasticsearch instance
		ElasticsearchIndex string        `json:"esIndex"`          // index name you are going to ingest data into
		ElasticsearchType  string        `json:"esType"`           // type name you are going to ingest data into
		CrawlDelay         time.Duration `json:"crawlDelay"`       // delay time for the crawler to abide to
		CancelDuration     time.Duration `json:"cancelDuration"`   // time duration for canceling the crawler (immediate cancel)
		CancelAtURL        string        `json:"cancelUrl"`        // specific URL to cancel the crawler at
		StopDuration       time.Duration `json:"stopDuration"`     // time duration for stopping the crawler (processes links on queue after duration time)
		StopAtURL          string        `json:"stopUrl"`          // specific URL to stop the crawler at for a specific "root"
		MemStatsInterval   time.Duration `json:"memStatsInterval"` // display memory statistics at a given interval
		UserAgent          string        `json:"userAgent"`        // set the user agent string for the crawler... to be polite and identify yourself
		WorkerIdleTTL      time.Duration `json:"workerTimeout"`    // time-to-live for a host URL's goroutine
	}
)

// ParseLinks will parse the local data.json file that is in the same directory as the executable.
// The json file will be a "master" list of links we are going to crawl through.
func ParseLinks() Sources {
	var s Sources
	data, errRead := ioutil.ReadFile("./data.json")
	if errRead != nil {
		panic(errRead)
	}

	errUnmarshal := json.Unmarshal(data, &s)
	if errUnmarshal != nil {
		panic(errUnmarshal)
	}

	return s
}

// ParseSettings will parse a local settings.json file that is in the same directory as the executable.
// The json file will be all the configuration set by the user for the application.
func ParseSettings() Settings {
	var s Settings
	data, errRead := ioutil.ReadFile("./settings.json")
	if errRead != nil {
		panic(errRead)
	}

	errUnmarshal := json.Unmarshal(data, &s)
	if errUnmarshal != nil {
		panic(errUnmarshal)
	}

	return s
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 Red Hat, 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 ofthe 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 specificlanguage governing permissions and
 * limitations under the License.
 *
 */

package tests

import (
	"fmt"
	"testing"

	g "github.com/skydive-project/skydive/gremlin"
)

func TestLLDP(t *testing.T) {
	test := &Test{
		setupCmds: []Cmd{
			{"ip link add lldp0 type dummy", false},
			{"ip link set lldp0 up", false},
			{"ip link set multicast on dev lldp0", false},
			{"ip addr add 10.10.20.1/24 dev lldp0", false},
			{"sleep 3", false}, // give some time to the LLDP probe to start capturing packets
		},

		tearDownCmds: []Cmd{
			{"ip link del lldp0", false},
		},

		injections: []TestInjection{{
			from: g.G.V().Has("Name", "lldp0"),
			pcap: "pcaptraces/lldp-detailed.pcap",
		}},

		mode: Replay,

		checks: []CheckFunction{func(c *CheckContext) error {
			gremlin := c.gremlin.V().Has("Name", "lldp0").Both("Type", "switchport").HasKey("LLDP")

			switchPort, err := c.gh.GetNode(gremlin)
			if err != nil {
				return fmt.Errorf("Failed to find node for port")
			}

			if mtu, _ := switchPort.GetFieldInt64("MTU"); mtu != 1522 {
				return fmt.Errorf("Expected MTU of 1522 for port switch")
			}

			portName := "Summit300-48-Port 1001"
			if name, _ := switchPort.GetFieldString("Name"); name != portName {
				return fmt.Errorf("Expected switch port to be named '%s' (%d), got '%s' (%d)", portName, len(portName), name, len(name))
			}

			gremlin = gremlin.Both("Type", "switch").Dedup()
			chassis, err := c.gh.GetNode(gremlin)
			if err != nil {
				return fmt.Errorf("Failed to find node for chassis")
			}

			id := "00:01:30:f9:ad:a0"
			if chassisID, _ := chassis.GetFieldString("LLDP.ChassisID"); chassisID != id {
				return fmt.Errorf("Expected LLDP.ChassisID to be '%s' (%d), got '%s' (%d)", id, len(id), chassisID, len(chassisID))
			}

			if name, _ := chassis.GetFieldString("Name"); name != "Summit300-48" {
				return fmt.Errorf("Expected chassis to be named 'Summit300-48'")
			}

			return nil
		}},
	}

	RunTest(t, test)
}
<commit_msg>tests: lldp make use of pcap count/interval instead of using sleep<commit_after>/*
 * Copyright (C) 2018 Red Hat, 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 ofthe 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 specificlanguage governing permissions and
 * limitations under the License.
 *
 */

package tests

import (
	"fmt"
	"testing"

	g "github.com/skydive-project/skydive/gremlin"
)

func TestLLDP(t *testing.T) {
	test := &Test{
		setupCmds: []Cmd{
			{"ip link add lldp0 type dummy", false},
			{"ip link set lldp0 up", false},
			{"ip link set multicast on dev lldp0", false},
			{"ip addr add 10.10.20.1/24 dev lldp0", false},
		},

		tearDownCmds: []Cmd{
			{"ip link del lldp0", false},
		},

		injections: []TestInjection{{
			from:  g.G.V().Has("Name", "lldp0"),
			pcap:  "pcaptraces/lldp-detailed.pcap",
			count: 20,
		}},

		mode: Replay,

		checks: []CheckFunction{func(c *CheckContext) error {
			gremlin := c.gremlin.V().Has("Name", "lldp0").Both("Type", "switchport").HasKey("LLDP")

			switchPort, err := c.gh.GetNode(gremlin)
			if err != nil {
				return fmt.Errorf("Failed to find node for port")
			}

			if mtu, _ := switchPort.GetFieldInt64("MTU"); mtu != 1522 {
				return fmt.Errorf("Expected MTU of 1522 for port switch")
			}

			portName := "Summit300-48-Port 1001"
			if name, _ := switchPort.GetFieldString("Name"); name != portName {
				return fmt.Errorf("Expected switch port to be named '%s' (%d), got '%s' (%d)", portName, len(portName), name, len(name))
			}

			gremlin = gremlin.Both("Type", "switch").Dedup()
			chassis, err := c.gh.GetNode(gremlin)
			if err != nil {
				return fmt.Errorf("Failed to find node for chassis")
			}

			id := "00:01:30:f9:ad:a0"
			if chassisID, _ := chassis.GetFieldString("LLDP.ChassisID"); chassisID != id {
				return fmt.Errorf("Expected LLDP.ChassisID to be '%s' (%d), got '%s' (%d)", id, len(id), chassisID, len(chassisID))
			}

			if name, _ := chassis.GetFieldString("Name"); name != "Summit300-48" {
				return fmt.Errorf("Expected chassis to be named 'Summit300-48'")
			}

			return nil
		}},
	}

	RunTest(t, test)
}
<|endoftext|>


<commit_before>package redis

func (c *Client) ZAdd(key, score, member string, values ...string) (int64, error) {
	resp, err := c.exec("ZADD", append([]string{key, score, member}, values...)...)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZCard(key string) (int64, error) {
	resp, err := c.exec("ZCARD", key)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZCount(key, min, max string) (int64, error) {
	resp, err := c.exec("ZCOUNT", key, min, max)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZIncryBy(key, increment, member string) (string, error) {
	resp, err := c.exec("ZINCRBY", key, increment, member)
	if err != nil {
		return "", err
	}
	return c.bulkString(resp)
}

// TODO(ttacon): put in correct/intuitive function signature
func (c *Client) ZInterStore(key string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}
<commit_msg>ZLEXCOUNT<commit_after>package redis

import "strconv"

func (c *Client) ZAdd(key, score, member string, values ...string) (int64, error) {
	resp, err := c.exec("ZADD", append([]string{key, score, member}, values...)...)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZCard(key string) (int64, error) {
	resp, err := c.exec("ZCARD", key)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZCount(key, min, max string) (int64, error) {
	resp, err := c.exec("ZCOUNT", key, min, max)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) ZIncryBy(key, increment, member string) (string, error) {
	resp, err := c.exec("ZINCRBY", key, increment, member)
	if err != nil {
		return "", err
	}
	return c.bulkString(resp)
}

// TODO(ttacon): put in correct/intuitive function signature
func (c *Client) ZInterStore(key string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) ZLexCount(key string, min, max int) (int64, error) {
	resp, err := c.exec("ZLexCount", key, strconv.Itoa(min), strconv.Itoa(max))
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}
<|endoftext|>


<commit_before>package kite

import (
	"errors"
	"fmt"
	"github.com/op/go-logging"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/protocol"
	"strconv"
	"sync"
)

// RemoteKite is the client for communicating with another Kite.
// It has Call() and Go() methods for calling methods sync/async way.
type RemoteKite struct {
	// The information about the kite that we are connecting to.
	protocol.Kite

	// A reference to the current Kite running.
	localKite *Kite

	// A reference to the Kite's logger for easy access.
	Log *logging.Logger

	// Credentials that we sent in each request.
	Authentication callAuthentication

	// dnode RPC client that processes messages.
	client *rpc.Client

	// To signal waiters of Go() on disconnect.
	disconnect chan bool
}

// NewRemoteKite returns a pointer to a new RemoteKite. The returned instance
// is not connected. You have to call Dial() or DialForever() before calling
// Call() and Go() methods.
func (k *Kite) NewRemoteKite(kite protocol.Kite, auth callAuthentication) *RemoteKite {
	r := &RemoteKite{
		Kite:           kite,
		localKite:      k,
		Log:            k.Log,
		Authentication: auth,
		client:         k.server.NewClientWithHandlers(),
		disconnect:     make(chan bool),
	}

	// We need a reference to the local kite when a method call is received.
	r.client.Properties()["localKite"] = k

	var m sync.Mutex
	r.OnDisconnect(func() {
		m.Lock()
		close(r.disconnect)
		r.disconnect = make(chan bool)
		m.Unlock()
	})

	return r
}

// newRemoteKiteWithClient returns a pointer to new RemoteKite instance.
// The client will be replaced with the given client.
// Used to give the Kite method handler a working RemoteKite to call methods
// on other side.
func (k *Kite) newRemoteKiteWithClient(kite protocol.Kite, auth callAuthentication, client *rpc.Client) *RemoteKite {
	r := k.NewRemoteKite(kite, auth)
	r.client = client
	r.client.Properties()["localKite"] = k
	return r
}

// Dial connects to the remote Kite. Returns error if it can't.
func (r *RemoteKite) Dial() (err error) {
	addr := r.Kite.Addr()
	r.Log.Info("Dialing remote kite: [%s %s]", r.Kite.Name, addr)
	return r.client.Dial("ws://" + addr + "/dnode")
}

// Dial connects to the remote Kite. If it can't connect, it retries indefinitely.
func (r *RemoteKite) DialForever() {
	addr := r.Kite.Addr()
	r.Log.Info("Dialing remote kite: [%s %s]", r.Kite.Name, addr)
	r.client.DialForever("ws://" + addr + "/dnode")
}

func (r *RemoteKite) Close() {
	r.client.Close()
}

// OnConnect registers a function to run on connect.
func (r *RemoteKite) OnConnect(handler func()) {
	r.client.OnConnect(handler)
}

// OnDisconnect registers a function to run on disconnect.
func (r *RemoteKite) OnDisconnect(handler func()) {
	r.client.OnDisconnect(handler)
}

// CallOptions is the type of first argument in the dnode message.
// Second argument is a callback function.
// It is used when unmarshalling a dnode message.
type CallOptions struct {
	// Arguments to the method
	WithArgs       *dnode.Partial     `json:"withArgs"`
	Kite           protocol.Kite      `json:"kite"`
	Authentication callAuthentication `json:"authentication"`
}

// callOptionsOut is the same structure with CallOptions.
// It is used when marshalling a dnode message.
type callOptionsOut struct {
	CallOptions
	// Override this when sending because args will not be a *dnode.Partial.
	WithArgs interface{} `json:"withArgs"`
}

// That's what we send as a first argument in dnode message.
func (r *RemoteKite) makeOptions(args interface{}) *callOptionsOut {
	return &callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite:           r.localKite.Kite,
			Authentication: r.Authentication,
		},
	}
}

type callAuthentication struct {
	// Type can be "kodingKey", "token" or "sessionID" for now.
	Type string `json:"type"`
	Key  string `json:"key"`
}

type response struct {
	Result *dnode.Partial
	Err    error
}

// Call makes a blocking method call to the server.
// Waits until the callback function is called by the other side and
// returns the result and the error.
func (r *RemoteKite) Call(method string, args interface{}) (result *dnode.Partial, err error) {
	response := <-r.Go(method, args)
	return response.Result, response.Err
}

// Go makes an unblocking method call to the server.
// It returns a channel that the caller can wait on it to get the response.
func (r *RemoteKite) Go(method string, args interface{}) chan *response {
	// We will return this channel to the caller.
	// It can wait on this channel to get the response.
	r.Log.Debug("Calling method [%s] on kite [%s]", method, r.Name)
	responseChan := make(chan *response, 1)

	r.send(method, args, responseChan)

	return responseChan
}

// send sends the method with callback to the server.
func (r *RemoteKite) send(method string, args interface{}, responseChan chan *response) {
	// To clean the sent callback after response is received.
	// Send/Receive in a channel to prevent race condition because
	// the callback is run in a separate goroutine.
	removeCallback := make(chan uint64, 1)

	// When a callback is called it will send the response to this channel.
	doneChan := make(chan *response, 1)

	opts := r.makeOptions(args)
	cb := r.makeResponseCallback(doneChan, removeCallback)

	callbacks, err := r.client.Call(method, opts, cb)
	if err != nil {
		responseChan <- &response{
			Result: nil,
			Err: fmt.Errorf("Calling method [%s] on [%s] error: %s",
				method, r.Kite.Name, err),
		}
		return
	}

	// Waits until the response has came or the connection has disconnected.
	go func() {
		select {
		case <-r.disconnect:
			responseChan <- &response{nil, errors.New("Client disconnected")}
		case resp := <-doneChan:
			responseChan <- resp
		}
	}()

	sendCallbackID(callbacks, removeCallback)
}

// sendCallbackID send the callback number to be deleted after response is received.
func sendCallbackID(callbacks map[string]dnode.Path, ch chan uint64) {
	if len(callbacks) > 0 {
		max := uint64(0)
		for id, _ := range callbacks {
			i, _ := strconv.ParseUint(id, 10, 64)
			if i > max {
				max = i
			}
		}
		ch <- max
	} else {
		close(ch)
	}
}

// makeResponseCallback prepares and returns a callback function sent to the server.
// The caller of the Call() is blocked until the server calls this callback function.
// Sets theResponse and notifies the caller by sending to done channel.
func (r *RemoteKite) makeResponseCallback(doneChan chan *response, removeCallback <-chan uint64) Callback {
	return Callback(func(request *Request) {
		var (
			// Arguments to our response callback It is a slice of length 2.
			// The first argument is the error string,
			// the second argument is the result.
			responseArgs []*dnode.Partial

			// First argument
			err error

			// Second argument
			result *dnode.Partial
		)

		// Notify that the callback is finished.
		defer func() { doneChan <- &response{result, err} }()

		// Remove the callback function from the map so we do not
		// consume memory for unused callbacks.
		if id, ok := <-removeCallback; ok {
			r.client.RemoveCallback(id)
		}

		err = request.Args.Unmarshal(&responseArgs)
		if err != nil {
			return
		}

		// We must always get an error and a result argument.
		if len(responseArgs) != 2 {
			err = fmt.Errorf("Invalid response args: %s", string(request.Args.Raw))
			return
		}

		// The second argument is our result.
		result = responseArgs[1]

		// This is error argument. Unmarshal panics if it is null.
		if responseArgs[0] == nil {
			return
		}

		// Read the error argument in response.
		var errorString string
		err = responseArgs[0].Unmarshal(&errorString)
		if err != nil {
			return
		}
		if errorString != "" {
			err = errors.New(errorString)
		}
	})
}
<commit_msg>kite: refactor response callback<commit_after>package kite

import (
	"errors"
	"fmt"
	"github.com/op/go-logging"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/protocol"
	"strconv"
	"sync"
)

// RemoteKite is the client for communicating with another Kite.
// It has Call() and Go() methods for calling methods sync/async way.
type RemoteKite struct {
	// The information about the kite that we are connecting to.
	protocol.Kite

	// A reference to the current Kite running.
	localKite *Kite

	// A reference to the Kite's logger for easy access.
	Log *logging.Logger

	// Credentials that we sent in each request.
	Authentication callAuthentication

	// dnode RPC client that processes messages.
	client *rpc.Client

	// To signal waiters of Go() on disconnect.
	disconnect chan bool
}

// NewRemoteKite returns a pointer to a new RemoteKite. The returned instance
// is not connected. You have to call Dial() or DialForever() before calling
// Call() and Go() methods.
func (k *Kite) NewRemoteKite(kite protocol.Kite, auth callAuthentication) *RemoteKite {
	r := &RemoteKite{
		Kite:           kite,
		localKite:      k,
		Log:            k.Log,
		Authentication: auth,
		client:         k.server.NewClientWithHandlers(),
		disconnect:     make(chan bool),
	}

	// We need a reference to the local kite when a method call is received.
	r.client.Properties()["localKite"] = k

	var m sync.Mutex
	r.OnDisconnect(func() {
		m.Lock()
		close(r.disconnect)
		r.disconnect = make(chan bool)
		m.Unlock()
	})

	return r
}

// newRemoteKiteWithClient returns a pointer to new RemoteKite instance.
// The client will be replaced with the given client.
// Used to give the Kite method handler a working RemoteKite to call methods
// on other side.
func (k *Kite) newRemoteKiteWithClient(kite protocol.Kite, auth callAuthentication, client *rpc.Client) *RemoteKite {
	r := k.NewRemoteKite(kite, auth)
	r.client = client
	r.client.Properties()["localKite"] = k
	return r
}

// Dial connects to the remote Kite. Returns error if it can't.
func (r *RemoteKite) Dial() (err error) {
	addr := r.Kite.Addr()
	r.Log.Info("Dialing remote kite: [%s %s]", r.Kite.Name, addr)
	return r.client.Dial("ws://" + addr + "/dnode")
}

// Dial connects to the remote Kite. If it can't connect, it retries indefinitely.
func (r *RemoteKite) DialForever() {
	addr := r.Kite.Addr()
	r.Log.Info("Dialing remote kite: [%s %s]", r.Kite.Name, addr)
	r.client.DialForever("ws://" + addr + "/dnode")
}

func (r *RemoteKite) Close() {
	r.client.Close()
}

// OnConnect registers a function to run on connect.
func (r *RemoteKite) OnConnect(handler func()) {
	r.client.OnConnect(handler)
}

// OnDisconnect registers a function to run on disconnect.
func (r *RemoteKite) OnDisconnect(handler func()) {
	r.client.OnDisconnect(handler)
}

// CallOptions is the type of first argument in the dnode message.
// Second argument is a callback function.
// It is used when unmarshalling a dnode message.
type CallOptions struct {
	// Arguments to the method
	WithArgs       *dnode.Partial     `json:"withArgs"`
	Kite           protocol.Kite      `json:"kite"`
	Authentication callAuthentication `json:"authentication"`
}

// callOptionsOut is the same structure with CallOptions.
// It is used when marshalling a dnode message.
type callOptionsOut struct {
	CallOptions
	// Override this when sending because args will not be a *dnode.Partial.
	WithArgs interface{} `json:"withArgs"`
}

// That's what we send as a first argument in dnode message.
func (r *RemoteKite) makeOptions(args interface{}) *callOptionsOut {
	return &callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite:           r.localKite.Kite,
			Authentication: r.Authentication,
		},
	}
}

type callAuthentication struct {
	// Type can be "kodingKey", "token" or "sessionID" for now.
	Type string `json:"type"`
	Key  string `json:"key"`
}

type response struct {
	Result *dnode.Partial
	Err    error
}

// Call makes a blocking method call to the server.
// Waits until the callback function is called by the other side and
// returns the result and the error.
func (r *RemoteKite) Call(method string, args interface{}) (result *dnode.Partial, err error) {
	response := <-r.Go(method, args)
	return response.Result, response.Err
}

// Go makes an unblocking method call to the server.
// It returns a channel that the caller can wait on it to get the response.
func (r *RemoteKite) Go(method string, args interface{}) chan *response {
	// We will return this channel to the caller.
	// It can wait on this channel to get the response.
	r.Log.Debug("Calling method [%s] on kite [%s]", method, r.Name)
	responseChan := make(chan *response, 1)

	r.send(method, args, responseChan)

	return responseChan
}

// send sends the method with callback to the server.
func (r *RemoteKite) send(method string, args interface{}, responseChan chan *response) {
	// To clean the sent callback after response is received.
	// Send/Receive in a channel to prevent race condition because
	// the callback is run in a separate goroutine.
	removeCallback := make(chan uint64, 1)

	// When a callback is called it will send the response to this channel.
	doneChan := make(chan *response, 1)

	opts := r.makeOptions(args)
	cb := r.makeResponseCallback(doneChan, removeCallback)

	callbacks, err := r.client.Call(method, opts, cb)
	if err != nil {
		responseChan <- &response{
			Result: nil,
			Err: fmt.Errorf("Calling method [%s] on [%s] error: %s",
				method, r.Kite.Name, err),
		}
		return
	}

	// Waits until the response has came or the connection has disconnected.
	go func() {
		select {
		case <-r.disconnect:
			responseChan <- &response{nil, errors.New("Client disconnected")}
		case resp := <-doneChan:
			responseChan <- resp
		}
	}()

	sendCallbackID(callbacks, removeCallback)
}

// sendCallbackID send the callback number to be deleted after response is received.
func sendCallbackID(callbacks map[string]dnode.Path, ch chan uint64) {
	if len(callbacks) > 0 {
		max := uint64(0)
		for id, _ := range callbacks {
			i, _ := strconv.ParseUint(id, 10, 64)
			if i > max {
				max = i
			}
		}
		ch <- max
	} else {
		close(ch)
	}
}

// makeResponseCallback prepares and returns a callback function sent to the server.
// The caller of the Call() is blocked until the server calls this callback function.
// Sets theResponse and notifies the caller by sending to done channel.
func (r *RemoteKite) makeResponseCallback(doneChan chan *response, removeCallback <-chan uint64) Callback {
	return Callback(func(request *Request) {
		var (
			// First argument
			err error

			// Second argument
			result *dnode.Partial
		)

		// Notify that the callback is finished.
		defer func() { doneChan <- &response{result, err} }()

		// Remove the callback function from the map so we do not
		// consume memory for unused callbacks.
		if id, ok := <-removeCallback; ok {
			r.client.RemoveCallback(id)
		}

		// Arguments to our response callback It is a slice of length 2.
		// The first argument is the error string,
		// the second argument is the result.
		responseArgs := request.Args.MustSliceOfLength(2)

		// The second argument is our result.
		result = responseArgs[1]

		// This is error argument. Unmarshal panics if it is null.
		if responseArgs[0] == nil {
			return
		}

		// Read the error argument in response.
		var errorString string
		err = responseArgs[0].Unmarshal(&errorString)
		if err != nil {
			return
		}
		if errorString != "" {
			err = errors.New(errorString)
		}
	})
}
<|endoftext|>