<commit_before>package vm

import (
	"context"
	"errors"
	"fmt"

	"github.com/hashicorp/hcl/v2/hcldec"
	vboxcommon "github.com/hashicorp/packer/builder/virtualbox/common"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config *Config
	runner multistep.Runner
}

func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }

func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
	warnings, errs := b.config.Prepare(raws...)
	if errs != nil {
		return nil, warnings, errs
	}

	return nil, warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	// Create the driver that we'll use to communicate with VirtualBox
	driver, err := vboxcommon.NewDriver()
	if err != nil {
		return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err)
	}

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("debug", b.config.PackerDebug)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{
		new(vboxcommon.StepSuppressMessages),
		&common.StepCreateFloppy{
			Files:       b.config.FloppyConfig.FloppyFiles,
			Directories: b.config.FloppyConfig.FloppyDirectories,
		},
		&StepSetSnapshot{
			Name:           b.config.VMName,
			AttachSnapshot: b.config.AttachSnapshot,
			KeepRegistered: b.config.KeepRegistered,
		},
		&common.StepHTTPServer{
			HTTPDir:     b.config.HTTPDir,
			HTTPPortMin: b.config.HTTPPortMin,
			HTTPPortMax: b.config.HTTPPortMax,
		},
		&vboxcommon.StepDownloadGuestAdditions{
			GuestAdditionsMode:   b.config.GuestAdditionsMode,
			GuestAdditionsURL:    b.config.GuestAdditionsURL,
			GuestAdditionsSHA256: b.config.GuestAdditionsSHA256,
			Ctx:                  b.config.ctx,
		},
		&StepImport{
			Name: b.config.VMName,
		},
		&vboxcommon.StepAttachGuestAdditions{
			GuestAdditionsMode: b.config.GuestAdditionsMode,
		},
		&vboxcommon.StepConfigureVRDP{
			VRDPBindAddress: b.config.VRDPBindAddress,
			VRDPPortMin:     b.config.VRDPPortMin,
			VRDPPortMax:     b.config.VRDPPortMax,
		},
		new(vboxcommon.StepAttachFloppy),
		&vboxcommon.StepForwardSSH{
			CommConfig:     &b.config.SSHConfig.Comm,
			HostPortMin:    b.config.SSHHostPortMin,
			HostPortMax:    b.config.SSHHostPortMax,
			SkipNatMapping: b.config.SSHSkipNatMapping,
		},
		&vboxcommon.StepVBoxManage{
			Commands: b.config.VBoxManage,
			Ctx:      b.config.ctx,
		},
		&vboxcommon.StepRun{
			Headless: b.config.Headless,
		},
		&vboxcommon.StepTypeBootCommand{
			BootWait:      b.config.BootWait,
			BootCommand:   b.config.FlatBootCommand(),
			VMName:        b.config.VMName,
			Ctx:           b.config.ctx,
			GroupInterval: b.config.BootConfig.BootGroupInterval,
			Comm:          &b.config.Comm,
		},
		&communicator.StepConnect{
			Config:    &b.config.SSHConfig.Comm,
			Host:      vboxcommon.CommHost(b.config.SSHConfig.Comm.SSHHost),
			SSHConfig: b.config.SSHConfig.Comm.SSHConfigFunc(),
			SSHPort:   vboxcommon.SSHPort,
			WinRMPort: vboxcommon.SSHPort,
		},
		&vboxcommon.StepUploadVersion{
			Path: *b.config.VBoxVersionFile,
		},
		&vboxcommon.StepUploadGuestAdditions{
			GuestAdditionsMode: b.config.GuestAdditionsMode,
			GuestAdditionsPath: b.config.GuestAdditionsPath,
			Ctx:                b.config.ctx,
		},
		new(common.StepProvision),
		&common.StepCleanupTempKeys{
			Comm: &b.config.SSHConfig.Comm,
		},
		&vboxcommon.StepShutdown{
			Command:         b.config.ShutdownCommand,
			Timeout:         b.config.ShutdownTimeout,
			Delay:           b.config.PostShutdownDelay,
			DisableShutdown: b.config.DisableShutdown,
		},
		&vboxcommon.StepVBoxManage{
			Commands: b.config.VBoxManagePost,
			Ctx:      b.config.ctx,
		},
		&StepCreateSnapshot{
			Name:           b.config.VMName,
			TargetSnapshot: b.config.TargetSnapshot,
		},
		&vboxcommon.StepExport{
			Format:         b.config.Format,
			OutputDir:      b.config.OutputDir,
			ExportOpts:     b.config.ExportOpts,
			SkipNatMapping: b.config.SSHSkipNatMapping,
			SkipExport:     b.config.SkipExport,
		},
	}

	if !b.config.SkipExport {
		steps = append(steps, nil)
		copy(steps[1:], steps)
		steps[0] = &common.StepOutputDir{
			Force: b.config.PackerForce,
			Path:  b.config.OutputDir,
		}
	}
	// Run the steps.
	b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
	b.runner.Run(ctx, state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("build was cancelled")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("build was halted")
	}

	if b.config.SkipExport {
		return nil, nil
	}

	return vboxcommon.NewArtifact(b.config.OutputDir)
}
<commit_msg>virtualbox/vm.Builder: use config  as a non pointer to avoid a panic<commit_after>package vm

import (
	"context"
	"errors"
	"fmt"

	"github.com/hashicorp/hcl/v2/hcldec"
	vboxcommon "github.com/hashicorp/packer/builder/virtualbox/common"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config Config
	runner multistep.Runner
}

func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }

func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
	warnings, errs := b.config.Prepare(raws...)
	if errs != nil {
		return nil, warnings, errs
	}

	return nil, warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	// Create the driver that we'll use to communicate with VirtualBox
	driver, err := vboxcommon.NewDriver()
	if err != nil {
		return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err)
	}

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("debug", b.config.PackerDebug)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{
		new(vboxcommon.StepSuppressMessages),
		&common.StepCreateFloppy{
			Files:       b.config.FloppyConfig.FloppyFiles,
			Directories: b.config.FloppyConfig.FloppyDirectories,
		},
		&StepSetSnapshot{
			Name:           b.config.VMName,
			AttachSnapshot: b.config.AttachSnapshot,
			KeepRegistered: b.config.KeepRegistered,
		},
		&common.StepHTTPServer{
			HTTPDir:     b.config.HTTPDir,
			HTTPPortMin: b.config.HTTPPortMin,
			HTTPPortMax: b.config.HTTPPortMax,
		},
		&vboxcommon.StepDownloadGuestAdditions{
			GuestAdditionsMode:   b.config.GuestAdditionsMode,
			GuestAdditionsURL:    b.config.GuestAdditionsURL,
			GuestAdditionsSHA256: b.config.GuestAdditionsSHA256,
			Ctx:                  b.config.ctx,
		},
		&StepImport{
			Name: b.config.VMName,
		},
		&vboxcommon.StepAttachGuestAdditions{
			GuestAdditionsMode: b.config.GuestAdditionsMode,
		},
		&vboxcommon.StepConfigureVRDP{
			VRDPBindAddress: b.config.VRDPBindAddress,
			VRDPPortMin:     b.config.VRDPPortMin,
			VRDPPortMax:     b.config.VRDPPortMax,
		},
		new(vboxcommon.StepAttachFloppy),
		&vboxcommon.StepForwardSSH{
			CommConfig:     &b.config.SSHConfig.Comm,
			HostPortMin:    b.config.SSHHostPortMin,
			HostPortMax:    b.config.SSHHostPortMax,
			SkipNatMapping: b.config.SSHSkipNatMapping,
		},
		&vboxcommon.StepVBoxManage{
			Commands: b.config.VBoxManage,
			Ctx:      b.config.ctx,
		},
		&vboxcommon.StepRun{
			Headless: b.config.Headless,
		},
		&vboxcommon.StepTypeBootCommand{
			BootWait:      b.config.BootWait,
			BootCommand:   b.config.FlatBootCommand(),
			VMName:        b.config.VMName,
			Ctx:           b.config.ctx,
			GroupInterval: b.config.BootConfig.BootGroupInterval,
			Comm:          &b.config.Comm,
		},
		&communicator.StepConnect{
			Config:    &b.config.SSHConfig.Comm,
			Host:      vboxcommon.CommHost(b.config.SSHConfig.Comm.SSHHost),
			SSHConfig: b.config.SSHConfig.Comm.SSHConfigFunc(),
			SSHPort:   vboxcommon.SSHPort,
			WinRMPort: vboxcommon.SSHPort,
		},
		&vboxcommon.StepUploadVersion{
			Path: *b.config.VBoxVersionFile,
		},
		&vboxcommon.StepUploadGuestAdditions{
			GuestAdditionsMode: b.config.GuestAdditionsMode,
			GuestAdditionsPath: b.config.GuestAdditionsPath,
			Ctx:                b.config.ctx,
		},
		new(common.StepProvision),
		&common.StepCleanupTempKeys{
			Comm: &b.config.SSHConfig.Comm,
		},
		&vboxcommon.StepShutdown{
			Command:         b.config.ShutdownCommand,
			Timeout:         b.config.ShutdownTimeout,
			Delay:           b.config.PostShutdownDelay,
			DisableShutdown: b.config.DisableShutdown,
		},
		&vboxcommon.StepVBoxManage{
			Commands: b.config.VBoxManagePost,
			Ctx:      b.config.ctx,
		},
		&StepCreateSnapshot{
			Name:           b.config.VMName,
			TargetSnapshot: b.config.TargetSnapshot,
		},
		&vboxcommon.StepExport{
			Format:         b.config.Format,
			OutputDir:      b.config.OutputDir,
			ExportOpts:     b.config.ExportOpts,
			SkipNatMapping: b.config.SSHSkipNatMapping,
			SkipExport:     b.config.SkipExport,
		},
	}

	if !b.config.SkipExport {
		steps = append(steps, nil)
		copy(steps[1:], steps)
		steps[0] = &common.StepOutputDir{
			Force: b.config.PackerForce,
			Path:  b.config.OutputDir,
		}
	}
	// Run the steps.
	b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
	b.runner.Run(ctx, state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("build was cancelled")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("build was halted")
	}

	if b.config.SkipExport {
		return nil, nil
	}

	return vboxcommon.NewArtifact(b.config.OutputDir)
}
<|endoftext|>


<commit_before>// Implement a genetic algorithm with D genes that range over [0, 1).
//
// Mutation is a clipped Gaussian that decreases in magnitude when the
// population starts to stagnate.
//
// The population always includes N% of the best-ever individuals and
// M% new individuals.

package optbench

import (
	"math/rand"
	"math"
	"sort"
	"fmt"
)

type Individual struct {
	Fitness float64
	Genes []float64
}

func NewIndividual(d int) *Individual {
	ind := new(Individual)
	ind.Genes = make([]float64, d)
	for i := range ind.Genes {
		ind.Genes[i] = rand.Float64()
	}
	return ind
}

func Breed(p1, p2 *Individual) *Individual {
	g := len(p1.Genes)
	child := new(Individual)
	child.Genes = make([]float64, g)
	// Single crossover (for now).
	cx := rand.Intn(g)
	for i := range child.Genes {
		if i < cx {
			child.Genes[i] = p1.Genes[i]
		} else {
			child.Genes[i] = p2.Genes[i]
		}
	}
	return child
}

func (gs *Individual) Mutate(stddev float64) {
	for i, g := range gs.Genes {
		g += rand.NormFloat64() * stddev
		gs.Genes[i] = math.Min(1.0, math.Max(0.0, g))
	}
}

type Population struct {
	Members []*Individual
	Fittest float64
	sigma float64
	age int
}

func NewPopulation(d, k int) *Population {
	pop := new(Population)
	pop.Members = make([]*Individual, k)
	for i := range pop.Members {
		pop.Members[i] = NewIndividual(d)
	}
	pop.sigma = 0.25
	return pop
}

type EvalFn func ([]float64) float64

func (pop *Population) Evaluate(f EvalFn) {
	pop.age += 1
	fittest := f(pop.Members[len(pop.Members) - 1].Genes)
	for _, m := range pop.Members {
		m.Fitness = f(m.Genes)
		if m.Fitness < fittest {
			fittest = m.Fitness
			pop.Fittest = fittest
			pop.age = 0
		}
	}
	delta := 1 - fittest
	total := 0.0
	for _, m := range pop.Members {
		m.Fitness = 1 / (m.Fitness + delta)
		total += m.Fitness
	}
	for _, m := range pop.Members {
		m.Fitness /= total
	}
	sort.Sort(pop)
}

func (p *Population) Len() int {
	return len(p.Members)
}

func (p *Population) Swap(i, j int) {
	p.Members[i], p.Members[j] = p.Members[j], p.Members[i]
}

func (p *Population) Less(i, j int) bool {
	return p.Members[i].Fitness < p.Members[j].Fitness
}

func (p *Population) PrintOut() {
	for _, m := range p.Members {
		fmt.Println(m)
	}
}

type CumulativeDistribution []float64

func (p *Population) FitnessCurve() CumulativeDistribution {
	cum := 0.0
	var curve CumulativeDistribution
	for _, m := range p.Members {
		cum += m.Fitness
		curve = append(curve, cum)
	}
	return curve
}

func (c CumulativeDistribution) RouletteSelection() int {
	return sort.SearchFloat64s(c, rand.Float64())
}

func Epoch(pop *Population) {
	ms := pop.Members
	bred := int(0.6 * float64(len(ms)))
	novel := int(0.9 * float64(len(ms)))
	curve := pop.FitnessCurve()
	var children Population
	if (pop.age > 10) {
		pop.sigma *= 0.99
		pop.age = 0
	}
	for i := 0; i < bred; i++ {
		a, b := curve.RouletteSelection(), curve.RouletteSelection()
		child := Breed(ms[a], ms[b])
		child.Mutate(pop.sigma)
		children.Members = append(children.Members, child)
	}
	for i, c := range children.Members {
		ms[i] = c
	}
	d := len(ms[0].Genes)
	for i := bred; i < novel; i++ {
		ms[i] = NewIndividual(d)
	}
}
<commit_msg>Better genes for science.<commit_after>// Implement a genetic algorithm with D genes that range over [0, 1).
//
// Mutation is a clipped Gaussian that decreases in magnitude when the
// population starts to stagnate.
//
// The population always includes N% of the best-ever individuals and
// M% new individuals.

package optbench

import (
	"math/rand"
	"math"
	"sort"
	"fmt"
)

type Individual struct {
	Fitness float64
	Genes []float64
}

func NewIndividual(d int) *Individual {
	ind := new(Individual)
	ind.Genes = make([]float64, d)
	for i := range ind.Genes {
		ind.Genes[i] = rand.Float64()
	}
	return ind
}

func Breed(p1, p2 *Individual) *Individual {
	g := len(p1.Genes)
	child := new(Individual)
	child.Genes = make([]float64, g)
	// Single crossover (for now).
	cx := rand.Intn(g)
	for i := range child.Genes {
		if i < cx {
			child.Genes[i] = p1.Genes[i]
		} else {
			child.Genes[i] = p2.Genes[i]
		}
	}
	return child
}

func (gs *Individual) Mutate(stddev float64) {
	for i, g := range gs.Genes {
		g += rand.NormFloat64() * stddev
		gs.Genes[i] = math.Min(1.0, math.Max(0.0, g))
	}
}

type Population struct {
	Members []*Individual
	Fittest float64
	sigma float64
	age int
}

func NewPopulation(d, k int) *Population {
	pop := new(Population)
	pop.Members = make([]*Individual, k)
	for i := range pop.Members {
		pop.Members[i] = NewIndividual(d)
	}
	pop.Fittest = 10000000.0
	pop.sigma = 0.1
	return pop
}

type EvalFn func ([]float64) float64

func (pop *Population) Evaluate(f EvalFn) float64 {
	pop.age += 1
	fittest := f(pop.Members[0].Genes)
	for _, m := range pop.Members {
		m.Fitness = f(m.Genes)
		if m.Fitness < fittest {
			fittest = m.Fitness
			if m.Fitness < pop.Fittest {
				pop.Fittest = m.Fitness
				pop.age = 0
			}
		}
	}
	delta := 1 - fittest
	total := 0.0
	for _, m := range pop.Members {
		m.Fitness = 1 / (m.Fitness + delta)
		total += m.Fitness
	}
	for _, m := range pop.Members {
		m.Fitness /= total
	}
	sort.Sort(pop)
	return fittest
}

func (p *Population) Len() int {
	return len(p.Members)
}

func (p *Population) Swap(i, j int) {
	p.Members[i], p.Members[j] = p.Members[j], p.Members[i]
}

func (p *Population) Less(i, j int) bool {
	return p.Members[i].Fitness < p.Members[j].Fitness
}

func (p *Population) PrintOut() {
	for _, m := range p.Members {
		fmt.Println(m)
	}
}

type CumulativeDistribution []float64

func (p *Population) FitnessCurve() CumulativeDistribution {
	cum := 0.0
	var curve CumulativeDistribution
	for _, m := range p.Members {
		cum += m.Fitness
		curve = append(curve, cum)
	}
	return curve
}

func (c CumulativeDistribution) RouletteSelection() int {
	return sort.SearchFloat64s(c, rand.Float64())
}

func Epoch(pop *Population) {
	ms := pop.Members
	bred := int(0.6 * float64(len(ms)))
	novel := int(0.9 * float64(len(ms)))
	curve := pop.FitnessCurve()
	var children Population
	if (pop.age > 3) {
		pop.sigma *= 0.99
		pop.age = 0
		fmt.Println("Reducing sigma to", pop.sigma)
	}
	for i := 0; i < bred; i++ {
		a, b := curve.RouletteSelection(), curve.RouletteSelection()
		child := Breed(ms[a], ms[b])
		child.Mutate(pop.sigma)
		children.Members = append(children.Members, child)
	}
	for i, c := range children.Members {
		ms[i] = c
	}
	d := len(ms[0].Genes)
	for i := bred; i < novel; i++ {
		ms[i] = NewIndividual(d)
	}
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/garyburd/redigo/redis"

	_ "github.com/lib/pq"
)

type PostgresDB struct {
	c          *sql.DB
	Host       string
	Port       int
	User       string
	Password   string
	DBName     string
	SchemaName string
	TableName  string
}

func NewPostgresDB() db.ShortenBackend {
	pgHost := db.GetOrDefault("PG_HOST", "localhost")
	pgPort := db.GetOrDefault("PG_HOST", "5432")
	pgUser := db.GetOrDefault("PG_USER", "shortener")
	pgPass := db.GetOrDefault("PG_PASS", "NOPE")
	pgDatabase := db.GetOrDefault("PG_DB", "shortener")
	pgSSLMode := db.GetOrDefault("PG_SSL", "disable")

	connString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", pgHost, pgPort, pgUser, pgPass, pgDatabase, pgSSLMode)
	db, err := sql.Open("postgres", connString)
	if err != nil {
		log.Fatal(err)
	}
	return &PostgresDB{c: db}
}

func (pgDB *PostgresDB) DeleteURL(slug string) error {
	_, err := pgDB.c.Query("DELETE FROM shortener.shortener WHERE slug=$1", slug)
	if err != nil {
		return err
	}
	log.Printf("Successfully deleted slug: %s", slug)
	return nil

}
func (pgDB *PostgresDB) ShortenURL(slug, longURL, owner string, tags []string, expires time.Time) error {
	// postgres & redshift don't have an upsert method yet
	existingLong, err := pgDB.GetLongURL(slug)
	if existingLong == "" || err != nil { // TODO figure out what happens on nothing, err?
		//q := fmt.Sprintf("INSERT INTO shortener.shortener(slug, long_url, expires, modified) VALUES($1, $2, $3, $4)")
		q := fmt.Sprintf("INSERT INTO shortener.shortener(slug, long_url, owner) VALUES($1, $2, $3)")
		_, err := pgDB.c.Query(q, slug, longURL, owner)
		if err != nil {
			return fmt.Errorf("Issue inserting new row for slug: %s, err is: %s", slug, err)
		}
		return nil
	}
	// Otherwise, upsert
	q := fmt.Sprintf("UPDATE shortener.shortener SET long_url=$2, owner=$3 WHERE slug=$1")
	_, err = pgDB.c.Query(q, slug, longURL, owner)
	if err != nil {
		return err
	}
	log.Printf("Successfully updated slug: %s", slug)
	return nil
}

func (pgDB *PostgresDB) GetLongURL(slug string) (string, error) {
	//var retObj ShortenObject
	q := fmt.Sprintf("SELECT long_url FROM shortener.shortener WHERE slug = $1")
	var long_url string
	err := pgDB.c.QueryRow(q, slug).Scan(&long_url)
	if err != nil {
		return "", err
	}
	log.Println("long: ", long_url)
	return long_url, nil

}

func (pgDB *PostgresDB) GetList() ([]db.ShortenObject, error) {
	rows, err := pgDB.c.Query(`SELECT slug, long_url, owner FROM shortener.shortener`)
	if err != nil {
		return nil, err
	}
	var retObjs []db.ShortenObject
	var slug string
	var long_url string
	var owner string
	//tags :=  []string{}
	//var expires time.Time
	//var modified time.Time
	for rows.Next() {
		err = rows.Scan(&slug, &long_url, &owner) //, &modified, &expires)
		if err != nil {
			return nil, fmt.Errorf("issue scanning row for list: %s", err)
		}
		retObjs = append(retObjs, db.ShortenObject{
			Slug:    slug,
			LongURL: long_url,
			Owner:   owner,
			//Expires:  expires,
			//Modified: modified,
		})
	}
	return retObjs, nil
}
<commit_msg>parameterize schema and table names for postgres<commit_after>package db

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/garyburd/redigo/redis"

	_ "github.com/lib/pq"
)

type PostgresDB struct {
	c          *sql.DB
	SchemaName string
	TableName  string
}

func NewPostgresDB() db.ShortenBackend {
	pgHost := db.GetOrDefault("PG_HOST", "localhost")
	pgPort := db.GetOrDefault("PG_HOST", "5432")
	pgUser := db.GetOrDefault("PG_USER", "shortener")
	pgPass := db.GetOrDefault("PG_PASS", "NOPE")
	pgDatabase := db.GetOrDefault("PG_DB", "shortener")
	pgSchema := db.GetOrDefault("PG_SCHEMA", "shortener")
	pgTable := db.GetOrDefault("PG_TABLE", "shortener")
	pgSSLMode := db.GetOrDefault("PG_SSL", "disable")

	connString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", pgHost, pgPort, pgUser, pgPass, pgDatabase, pgSSLMode)
	db, err := sql.Open("postgres", connString)
	if err != nil {
		log.Fatal(err)
	}
	return &PostgresDB{
		c:          db,
		SchemaName: pgSchema,
		TableName:  pgTable,
	}
}

func (pgDB *PostgresDB) DeleteURL(slug string) error {
	_, err := pgDB.c.Query(fmt.Sprintf("DELETE FROM %s.%s WHERE slug=$1", pgDB.SchemaName, pgDB.TableName), slug)
	if err != nil {
		return err
	}
	log.Printf("Successfully deleted slug: %s", slug)
	return nil

}
func (pgDB *PostgresDB) ShortenURL(slug, longURL, owner string, tags []string, expires time.Time) error {
	// postgres & redshift don't have an upsert method yet
	existingLong, err := pgDB.GetLongURL(slug)
	if existingLong == "" || err != nil { // TODO figure out what happens on nothing, err?
		//q := fmt.Sprintf("INSERT INTO %s.%s(slug, long_url, expires, modified) VALUES($1, $2, $3, $4)")
		q := fmt.Sprintf("INSERT INTO %s.%s(slug, long_url, owner) VALUES($1, $2, $3)", pgDB.SchemaName, pgDB.TableName)
		_, err := pgDB.c.Query(q, slug, longURL, owner)
		if err != nil {
			return fmt.Errorf("Issue inserting new row for slug: %s, err is: %s", slug, err)
		}
		return nil
	}
	// Otherwise, upsert
	q := fmt.Sprintf("UPDATE %s.%s SET long_url=$2, owner=$3 WHERE slug=$1", pgDB.SchemaName, pgDB.TableName)
	_, err = pgDB.c.Query(q, slug, longURL, owner)
	if err != nil {
		return err
	}
	log.Printf("Successfully updated slug: %s", slug)
	return nil
}

func (pgDB *PostgresDB) GetLongURL(slug string) (string, error) {
	//var retObj ShortenObject
	q := fmt.Sprintf("SELECT long_url FROM %s.%s WHERE slug = $1", pgDB.SchemaName, pgDB.TableName)
	var long_url string
	err := pgDB.c.QueryRow(q, slug).Scan(&long_url)
	if err != nil {
		return "", err
	}
	log.Println("long: ", long_url)
	return long_url, nil

}

func (pgDB *PostgresDB) GetList() ([]db.ShortenObject, error) {
	rows, err := pgDB.c.Query(fmt.Sprintf("SELECT slug, long_url, owner FROM %s.%s", pgDB.SchemaName, pgDB.TableName))
	if err != nil {
		return nil, err
	}
	var retObjs []db.ShortenObject
	var slug string
	var long_url string
	var owner string
	//tags :=  []string{}
	//var expires time.Time
	//var modified time.Time
	for rows.Next() {
		err = rows.Scan(&slug, &long_url, &owner) //, &modified, &expires)
		if err != nil {
			return nil, fmt.Errorf("issue scanning row for list: %s", err)
		}
		retObjs = append(retObjs, db.ShortenObject{
			Slug:    slug,
			LongURL: long_url,
			Owner:   owner,
			//Expires:  expires,
			//Modified: modified,
		})
	}
	return retObjs, nil
}
<|endoftext|>


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

package gg

import (
	"fmt"
	"log"
	"os"

	"github.com/aclements/go-gg/table"
)

// TODO: Split transforms, scalers, and layers into their own packages
// to clean up the name spaces and un-prefix their names?

// Warning is a logger for reporting conditions that don't prevent the
// production of a plot, but may lead to unexpected results.
var Warning = log.New(os.Stderr, "[gg] ", log.Lshortfile)

type Plot struct {
	//facet  facet

	env    *plotEnv
	scales map[string]scalerTree

	scaledData map[scaledDataKey]*scaledData
	scaleSet   map[scaleKey]bool
	marks      []plotMark

	axisLabels     map[string]string
	autoAxisLabels map[string][]string

	constNonce int
}

func NewPlot(data table.Grouping) *Plot {
	p := &Plot{
		env: &plotEnv{
			data: data,
		},
		scales:         make(map[string]scalerTree),
		scaledData:     make(map[scaledDataKey]*scaledData),
		scaleSet:       make(map[scaleKey]bool),
		axisLabels:     make(map[string]string),
		autoAxisLabels: make(map[string][]string),
	}
	return p
}

type plotEnv struct {
	parent *plotEnv
	data   table.Grouping
}

type scaleKey struct {
	gid   table.GroupID
	aes   string
	scale Scaler
}

// SetData sets p's current data table. The caller must not modify
// data in this table after this point.
func (p *Plot) SetData(data table.Grouping) *Plot {
	p.env.data = data
	return p
}

// Data returns p's current data table.
func (p *Plot) Data() table.Grouping {
	return p.env.data
}

// Const creates a new constant column bound to val in all groups and
// returns the generated column name. This is a convenient way to pass
// constant values to layers as columns.
//
// TODO: Typically this should be used with PreScaled or physical types.
func (p *Plot) Const(val interface{}) string {
	tab := p.Data()

retry:
	col := fmt.Sprintf("[gg-const-%d]", p.constNonce)
	p.constNonce++
	for _, col2 := range tab.Columns() {
		if col == col2 {
			goto retry
		}
	}

	p.SetData(table.MapTables(func(_ table.GroupID, t *table.Table) *table.Table {
		return table.NewBuilder(t).AddConst(col, val).Done()
	}, tab))

	return col
}

type scalerTree struct {
	scales map[table.GroupID]Scaler
}

func newScalerTree() scalerTree {
	return scalerTree{map[table.GroupID]Scaler{
		table.RootGroupID: &defaultScale{},
	}}
}

func (t scalerTree) bind(gid table.GroupID, s Scaler) {
	// Unbind scales under gid.
	for ogid := range t.scales {
		if gid == table.RootGroupID {
			// Optimize binding the root GID.
			delete(t.scales, ogid)
			continue
		}

		for p := ogid; ; p = p.Parent() {
			if p == gid {
				delete(t.scales, ogid)
				break
			}
			if p == table.RootGroupID {
				break
			}
		}
	}
	t.scales[gid] = s
}

func (t scalerTree) find(gid table.GroupID) Scaler {
	for {
		if s, ok := t.scales[gid]; ok {
			return s
		}
		if gid == table.RootGroupID {
			// This should never happen.
			panic("no scale for group " + gid.String())
		}
		gid = gid.Parent()
	}
}

func (p *Plot) getScales(aes string) scalerTree {
	st, ok := p.scales[aes]
	if !ok {
		st = newScalerTree()
		p.scales[aes] = st
	}
	return st
}

// SetScale binds a scale to the given visual aesthetic. SetScale is
// shorthand for SetScaleAt(aes, s, table.RootGroupID).
//
// SetScale returns p for ease of chaining.
func (p *Plot) SetScale(aes string, s Scaler) *Plot {
	return p.SetScaleAt(aes, s, table.RootGroupID)
}

// SetScaleAt binds a scale to the given visual aesthetic for all data
// in group gid or descendants of gid.
func (p *Plot) SetScaleAt(aes string, s Scaler, gid table.GroupID) *Plot {
	// TODO: Should aes be an enum so you can't mix up aesthetics
	// and column names?
	p.getScales(aes).bind(gid, s)
	return p
}

// GetScale returns the scale for the given visual aesthetic used for
// data in group gid.
func (p *Plot) GetScale(aes string, gid table.GroupID) Scaler {
	return p.getScales(aes).find(gid)
}

type scaledDataKey struct {
	aes  string
	data table.Grouping
	col  string
}

// use binds a column of data to an aesthetic. It expands the domain
// of the aesthetic's scale to include the data in col, and returns
// the scaled data.
//
// col may be "", in which case it simply returns nil.
//
// TODO: Should aes be an enum?
func (p *Plot) use(aes string, col string) *scaledData {
	if col == "" {
		return nil
	}

	// TODO: This is wrong. If the scale tree for aes changes,
	// this may return a stale scaledData bound to the wrong
	// scalers. If I got rid of scale trees, I could just put the
	// scaler in the key. Or I could clean up the cache when the
	// scale tree changes.

	sd := p.scaledData[scaledDataKey{aes, p.Data(), col}]
	if sd == nil {
		// Construct the scaledData.
		sd = &scaledData{
			seqs: make(map[table.GroupID]scaledSeq),
		}

		// Get the scale tree.
		st := p.getScales(aes)

		for _, gid := range p.Data().Tables() {
			table := p.Data().Table(gid)

			// Get the data.
			seq := table.MustColumn(col)

			// Find the scale.
			scaler := st.find(gid)

			// Add the scale to the scale set.
			p.scaleSet[scaleKey{gid, aes, scaler}] = true

			// Train the scale.
			scaler.ExpandDomain(seq)

			// Add it to the scaledData.
			sd.seqs[gid] = scaledSeq{seq, scaler}
		}

		p.scaledData[scaledDataKey{aes, p.Data(), col}] = sd
	}

	// Update axis labels.
	if aes == "x" || aes == "y" {
		p.autoAxisLabels[aes] = append(p.autoAxisLabels[aes], col)
	}

	return sd
}

// Save saves the current data table of p to a stack.
func (p *Plot) Save() *Plot {
	p.env = &plotEnv{
		parent: p.env,
		data:   p.env.data,
	}
	return p
}

// Restore restores the data table of p from the save stack.
func (p *Plot) Restore() *Plot {
	if p.env.parent == nil {
		panic("unbalanced Save/Restore")
	}
	p.env = p.env.parent
	return p
}

type Plotter interface {
	Apply(*Plot)
}

func (p *Plot) Add(plotters ...Plotter) *Plot {
	for _, plotter := range plotters {
		plotter.Apply(p)
	}
	return p
}

// AxisLabel returns a Plotter that sets the label of an axis on a
// Plot. By default, Plot constructs automatic axis labels from column
// names, but AxisLabel lets callers override these.
//
// TODO: Should labels be attached to aesthetics, generally?
//
// TODO: Should this really be a Plotter or just a method of Plot?
func AxisLabel(axis, label string) Plotter {
	return axisLabel{axis, label}
}

type axisLabel struct {
	axis, label string
}

func (a axisLabel) Apply(p *Plot) {
	p.axisLabels[a.axis] = a.label
}

// A Stat transforms a table.Grouping.
type Stat interface {
	F(table.Grouping) table.Grouping
}

// Stat applies each of stats in order to p's data.
//
// TODO: Perform scale transforms before applying stats.
func (p *Plot) Stat(stats ...Stat) *Plot {
	data := p.Data()
	for _, stat := range stats {
		data = stat.F(data)
	}
	return p.SetData(data)
}
<commit_msg>gg: more documentation for Plot<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gg

import (
	"fmt"
	"log"
	"os"

	"github.com/aclements/go-gg/table"
)

// TODO: Split transforms, scalers, and layers into their own packages
// to clean up the name spaces and un-prefix their names?

// Warning is a logger for reporting conditions that don't prevent the
// production of a plot, but may lead to unexpected results.
var Warning = log.New(os.Stderr, "[gg] ", log.Lshortfile)

// Plot represents a single (potentially faceted) plot.
type Plot struct {
	env    *plotEnv
	scales map[string]scalerTree

	scaledData map[scaledDataKey]*scaledData
	scaleSet   map[scaleKey]bool
	marks      []plotMark

	axisLabels     map[string]string
	autoAxisLabels map[string][]string

	constNonce int
}

// NewPlot returns a new Plot backed by data. It has no layers, one
// facet, and all scales are default.
func NewPlot(data table.Grouping) *Plot {
	p := &Plot{
		env: &plotEnv{
			data: data,
		},
		scales:         make(map[string]scalerTree),
		scaledData:     make(map[scaledDataKey]*scaledData),
		scaleSet:       make(map[scaleKey]bool),
		axisLabels:     make(map[string]string),
		autoAxisLabels: make(map[string][]string),
	}
	return p
}

type plotEnv struct {
	parent *plotEnv
	data   table.Grouping
}

type scaleKey struct {
	gid   table.GroupID
	aes   string
	scale Scaler
}

// SetData sets p's current data table. The caller must not modify
// data in this table after this point.
func (p *Plot) SetData(data table.Grouping) *Plot {
	p.env.data = data
	return p
}

// Data returns p's current data table.
func (p *Plot) Data() table.Grouping {
	return p.env.data
}

// Const creates a new constant column bound to val in all groups and
// returns the generated column name. This is a convenient way to pass
// constant values to layers as columns.
//
// TODO: Typically this should be used with PreScaled or physical types.
func (p *Plot) Const(val interface{}) string {
	tab := p.Data()

retry:
	col := fmt.Sprintf("[gg-const-%d]", p.constNonce)
	p.constNonce++
	for _, col2 := range tab.Columns() {
		if col == col2 {
			goto retry
		}
	}

	p.SetData(table.MapTables(func(_ table.GroupID, t *table.Table) *table.Table {
		return table.NewBuilder(t).AddConst(col, val).Done()
	}, tab))

	return col
}

type scalerTree struct {
	scales map[table.GroupID]Scaler
}

func newScalerTree() scalerTree {
	return scalerTree{map[table.GroupID]Scaler{
		table.RootGroupID: &defaultScale{},
	}}
}

func (t scalerTree) bind(gid table.GroupID, s Scaler) {
	// Unbind scales under gid.
	for ogid := range t.scales {
		if gid == table.RootGroupID {
			// Optimize binding the root GID.
			delete(t.scales, ogid)
			continue
		}

		for p := ogid; ; p = p.Parent() {
			if p == gid {
				delete(t.scales, ogid)
				break
			}
			if p == table.RootGroupID {
				break
			}
		}
	}
	t.scales[gid] = s
}

func (t scalerTree) find(gid table.GroupID) Scaler {
	for {
		if s, ok := t.scales[gid]; ok {
			return s
		}
		if gid == table.RootGroupID {
			// This should never happen.
			panic("no scale for group " + gid.String())
		}
		gid = gid.Parent()
	}
}

func (p *Plot) getScales(aes string) scalerTree {
	st, ok := p.scales[aes]
	if !ok {
		st = newScalerTree()
		p.scales[aes] = st
	}
	return st
}

// SetScale binds a scale to the given visual aesthetic. SetScale is
// shorthand for SetScaleAt(aes, s, table.RootGroupID).
//
// SetScale returns p for ease of chaining.
func (p *Plot) SetScale(aes string, s Scaler) *Plot {
	return p.SetScaleAt(aes, s, table.RootGroupID)
}

// SetScaleAt binds a scale to the given visual aesthetic for all data
// in group gid or descendants of gid.
func (p *Plot) SetScaleAt(aes string, s Scaler, gid table.GroupID) *Plot {
	// TODO: Should aes be an enum so you can't mix up aesthetics
	// and column names?
	p.getScales(aes).bind(gid, s)
	return p
}

// GetScale returns the scale for the given visual aesthetic used for
// data in group gid.
func (p *Plot) GetScale(aes string, gid table.GroupID) Scaler {
	return p.getScales(aes).find(gid)
}

type scaledDataKey struct {
	aes  string
	data table.Grouping
	col  string
}

// use binds a column of data to an aesthetic. It expands the domain
// of the aesthetic's scale to include the data in col, and returns
// the scaled data.
//
// col may be "", in which case it simply returns nil.
//
// TODO: Should aes be an enum?
func (p *Plot) use(aes string, col string) *scaledData {
	if col == "" {
		return nil
	}

	// TODO: This is wrong. If the scale tree for aes changes,
	// this may return a stale scaledData bound to the wrong
	// scalers. If I got rid of scale trees, I could just put the
	// scaler in the key. Or I could clean up the cache when the
	// scale tree changes.

	sd := p.scaledData[scaledDataKey{aes, p.Data(), col}]
	if sd == nil {
		// Construct the scaledData.
		sd = &scaledData{
			seqs: make(map[table.GroupID]scaledSeq),
		}

		// Get the scale tree.
		st := p.getScales(aes)

		for _, gid := range p.Data().Tables() {
			table := p.Data().Table(gid)

			// Get the data.
			seq := table.MustColumn(col)

			// Find the scale.
			scaler := st.find(gid)

			// Add the scale to the scale set.
			p.scaleSet[scaleKey{gid, aes, scaler}] = true

			// Train the scale.
			scaler.ExpandDomain(seq)

			// Add it to the scaledData.
			sd.seqs[gid] = scaledSeq{seq, scaler}
		}

		p.scaledData[scaledDataKey{aes, p.Data(), col}] = sd
	}

	// Update axis labels.
	if aes == "x" || aes == "y" {
		p.autoAxisLabels[aes] = append(p.autoAxisLabels[aes], col)
	}

	return sd
}

// Save saves the current data table of p to a stack.
func (p *Plot) Save() *Plot {
	p.env = &plotEnv{
		parent: p.env,
		data:   p.env.data,
	}
	return p
}

// Restore restores the data table of p from the save stack.
func (p *Plot) Restore() *Plot {
	if p.env.parent == nil {
		panic("unbalanced Save/Restore")
	}
	p.env = p.env.parent
	return p
}

// A Plotter is an operation that can modify a Plot.
type Plotter interface {
	Apply(*Plot)
}

// Add applies each of plotters to Plot in order.
func (p *Plot) Add(plotters ...Plotter) *Plot {
	for _, plotter := range plotters {
		plotter.Apply(p)
	}
	return p
}

// AxisLabel returns a Plotter that sets the label of an axis on a
// Plot. By default, Plot constructs automatic axis labels from column
// names, but AxisLabel lets callers override these.
//
// TODO: Should labels be attached to aesthetics, generally?
//
// TODO: Should this really be a Plotter or just a method of Plot?
func AxisLabel(axis, label string) Plotter {
	return axisLabel{axis, label}
}

type axisLabel struct {
	axis, label string
}

func (a axisLabel) Apply(p *Plot) {
	p.axisLabels[a.axis] = a.label
}

// A Stat transforms a table.Grouping.
type Stat interface {
	F(table.Grouping) table.Grouping
}

// Stat applies each of stats in order to p's data.
//
// TODO: Perform scale transforms before applying stats.
func (p *Plot) Stat(stats ...Stat) *Plot {
	data := p.Data()
	for _, stat := range stats {
		data = stat.F(data)
	}
	return p.SetData(data)
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "github.com/gvalkov/golang-evdev"
)

func ReadGuitar(c chan *evdev.InputEvent){
  guit, _ := evdev.Open("/dev/input/by-id/usb-0810_Twin_USB_Joystick-event-joystick")
  for {
    ev, _ := guit.ReadOne()
    if ev.Type == evdev.EV_KEY || ev.Type == evdev.EV_ABS {
      c <- ev
    }
  }
}

func main() {
  c := make(chan *evdev.InputEvent)
  go ReadGuitar(c)
  for {
    but := <- c
    fmt.Println(but.Code, but.Value)
  }
}
<commit_msg>Added device command line option<commit_after>package main

import (
    "fmt"
    "flag"
    "github.com/gvalkov/golang-evdev"
)

func ReadGuitar(c chan *evdev.InputEvent, dev string){
  guit, _ := evdev.Open(dev)
  for {
    ev, _ := guit.ReadOne()
    if ev.Type == evdev.EV_KEY || ev.Type == evdev.EV_ABS {
      c <- ev
    }
  }
}

func main() {
  dev := flag.String("d", "/dev/input/by-id/usb-0810_Twin_USB_Joystick-event-joystick", "The event device associated with the GH controller")
  flag.Parse()

  c := make(chan *evdev.InputEvent)
  go ReadGuitar(c, *dev)
  for {
    but := <- c
    fmt.Println(but.Code, but.Value)
  }
}
<|endoftext|>


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

package gitindex

import (
	"fmt"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/google/zoekt"
	"github.com/google/zoekt/build"

	git "github.com/libgit2/git2go"
)

// RepoModTime returns the time of last fetch of a git repository.
func RepoModTime(dir string) (time.Time, error) {
	var last time.Time
	refDir := filepath.Join(dir, "refs")
	if _, err := os.Lstat(refDir); err == nil {
		if err := filepath.Walk(refDir,
			func(name string, fi os.FileInfo, err error) error {
				if !fi.IsDir() && last.Before(fi.ModTime()) {
					last = fi.ModTime()
				}
				return nil
			}); err != nil {
			return last, err
		}
	}

	// git gc compresses refs into the following file:
	for _, fn := range []string{"info/refs", "packed-refs"} {
		if fi, err := os.Lstat(filepath.Join(dir, fn)); err == nil && !fi.IsDir() && last.Before(fi.ModTime()) {
			last = fi.ModTime()
		}
	}

	return last, nil
}

// FindGitRepos finds git repositories and returns repodir => name map.
func FindGitRepos(arg string) (map[string]string, error) {
	arg, err := filepath.Abs(arg)
	if err != nil {
		return nil, err
	}
	var dirs []string
	gitDirs := map[string]string{}
	if err := filepath.Walk(arg, func(name string, fi os.FileInfo, err error) error {
		if fi, err := os.Lstat(filepath.Join(name, ".git")); err == nil && fi.IsDir() {
			dirs = append(dirs, filepath.Join(name, ".git"))
			return filepath.SkipDir
		}

		if !strings.HasSuffix(name, ".git") || !fi.IsDir() {
			return nil
		}

		fi, err = os.Lstat(filepath.Join(name, "objects"))
		if err != nil || !fi.IsDir() {
			return nil
		}

		dirs = append(dirs, name)
		return filepath.SkipDir
	}); err != nil {
		return nil, err
	}

	for _, dir := range dirs {
		name := strings.TrimSuffix(dir, ".git")
		name = strings.TrimSuffix(name, "/")
		name = strings.TrimPrefix(name, arg)
		name = strings.TrimPrefix(name, "/")
		gitDirs[dir] = name
	}

	return gitDirs, nil
}

type templates struct {
	repo, commit, file, line string
}

// guessRepoURL guesses the URL template for a repo mirrored from a
// well-known git hosting site.
func guessRepoURL(repoDir string) (*templates, error) {
	base, err := git.NewConfig()
	if err != nil {
		return nil, err
	}
	defer base.Free()
	cfg, err := git.OpenOndisk(base, filepath.Join(repoDir, "config"))
	if err != nil {
		return nil, err
	}
	defer cfg.Free()

	remoteURL, err := cfg.LookupString("remote.origin.url")
	if err != nil {
		return nil, err
	}

	parsed, err := url.Parse(remoteURL)
	if err != nil {
		return nil, err
	}

	if strings.HasSuffix(parsed.Host, "googlesource.com") {
		/// eg. https://gerrit.googlesource.com/gitiles/+/master/tools/run_dev.sh#20
		return &templates{
			repo:   remoteURL,
			commit: remoteURL + "/+/{{.Version}}",
			file:   remoteURL + "/+/{{.Branch}}/{{.Path}}",
			line:   "{{.LineNumber}}",
		}, nil
	} else if parsed.Host == "github.com" {
		// CloneURL from the JSON API has .git
		parsed.Path = strings.TrimSuffix(parsed.Path, ".git")

		// eg. https://github.com/hanwen/go-fuse/blob/notify/genversion.sh#L10
		return &templates{
			repo:   parsed.String(),
			commit: parsed.String() + "/commit/{{.Version}}",
			file:   parsed.String() + "/blob/{{.Branch}}/{{.Path}}",
			line:   "L{{.LineNumber}}",
		}, nil
	}

	return nil, fmt.Errorf("scheme unknown for URL %s", remoteURL)
}

// getCommit returns a tree object for the given reference.
func getCommit(repo *git.Repository, ref string) (*git.Commit, error) {
	obj, err := repo.RevparseSingle(ref)
	if err != nil {
		return nil, err
	}
	defer obj.Free()

	commitObj, err := obj.Peel(git.ObjectCommit)
	if err != nil {
		return nil, err
	}
	return commitObj.AsCommit()
}

// IndexGitRepo indexes the git repository as specified by the options and arguments.
func IndexGitRepo(opts build.Options, branchPrefix string, branches []string, submodules bool) error {
	repo, err := git.OpenRepository(opts.RepoDir)
	if err != nil {
		return err
	}

	if tpl, err := guessRepoURL(opts.RepoDir); err != nil {
		log.Printf("guessRepoURL(%s): %s", opts.RepoDir, err)
	} else {
		opts.RepoURL = tpl.repo
		opts.FileURLTemplate = tpl.file
		opts.CommitURLTemplate = tpl.commit
		opts.LineFragmentTemplate = tpl.line
	}

	// name => branch
	allfiles := map[string][]string{}

	var names []string

	// branch => name => sha1
	data := map[string]map[string]git.Oid{}
	repos := map[git.Oid]*git.Repository{}
	for _, b := range branches {
		commit, err := getCommit(repo, filepath.Join(branchPrefix, b))
		if err != nil {
			return err
		}
		opts.Branches = append(opts.Branches, build.Branch{
			Name:    b,
			Version: commit.Id().String(),
		})

		tree, err := commit.Tree()
		if err != nil {
			return err
		}

		fs, subRepos, err := treeToFiles(repo, tree, submodules)
		if err != nil {
			return err
		}
		for k, v := range subRepos {
			repos[k] = v
		}

		for f := range fs {
			allfiles[f] = append(allfiles[f], b)
		}
		data[b] = fs
	}

	builder, err := build.NewBuilder(opts)
	if err != nil {
		return err
	}

	for n := range allfiles {
		names = append(names, n)
	}
	sort.Strings(names)

	for _, n := range names {
		shas := map[git.Oid][]string{}
		for _, b := range allfiles[n] {
			shas[data[b][n]] = append(shas[data[b][n]], b)
		}

		for sha, branches := range shas {
			r := repos[sha]
			if r == nil {
				return fmt.Errorf("no repo found for %s (%s)", n, branches)
			}
			blob, err := r.LookupBlob(&sha)
			if err != nil {
				return err
			}

			if blob.Size() > int64(opts.SizeMax) {
				continue
			}

			builder.Add(zoekt.Document{
				Name:     n,
				Content:  blob.Contents(),
				Branches: branches,
			})
		}
	}
	builder.Finish()

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

package gitindex

import (
	"fmt"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/google/zoekt"
	"github.com/google/zoekt/build"

	git "github.com/libgit2/git2go"
)

// RepoModTime returns the time of last fetch of a git repository.
func RepoModTime(dir string) (time.Time, error) {
	var last time.Time
	refDir := filepath.Join(dir, "refs")
	if _, err := os.Lstat(refDir); err == nil {
		if err := filepath.Walk(refDir,
			func(name string, fi os.FileInfo, err error) error {
				if !fi.IsDir() && last.Before(fi.ModTime()) {
					last = fi.ModTime()
				}
				return nil
			}); err != nil {
			return last, err
		}
	}

	// git gc compresses refs into the following file:
	for _, fn := range []string{"info/refs", "packed-refs"} {
		if fi, err := os.Lstat(filepath.Join(dir, fn)); err == nil && !fi.IsDir() && last.Before(fi.ModTime()) {
			last = fi.ModTime()
		}
	}

	return last, nil
}

// FindGitRepos finds git repositories and returns repodir => name map.
func FindGitRepos(arg string) (map[string]string, error) {
	arg, err := filepath.Abs(arg)
	if err != nil {
		return nil, err
	}
	var dirs []string
	gitDirs := map[string]string{}
	if err := filepath.Walk(arg, func(name string, fi os.FileInfo, err error) error {
		if fi, err := os.Lstat(filepath.Join(name, ".git")); err == nil && fi.IsDir() {
			dirs = append(dirs, filepath.Join(name, ".git"))
			return filepath.SkipDir
		}

		if !strings.HasSuffix(name, ".git") || !fi.IsDir() {
			return nil
		}

		fi, err = os.Lstat(filepath.Join(name, "objects"))
		if err != nil || !fi.IsDir() {
			return nil
		}

		dirs = append(dirs, name)
		return filepath.SkipDir
	}); err != nil {
		return nil, err
	}

	for _, dir := range dirs {
		name := strings.TrimSuffix(dir, ".git")
		name = strings.TrimSuffix(name, "/")
		name = strings.TrimPrefix(name, arg)
		name = strings.TrimPrefix(name, "/")
		gitDirs[dir] = name
	}

	return gitDirs, nil
}

type templates struct {
	repo, commit, file, line string
}

// guessRepoURL guesses the URL template for a repo mirrored from a
// well-known git hosting site.
func guessRepoURL(repoDir string) (*templates, error) {
	base, err := git.NewConfig()
	if err != nil {
		return nil, err
	}
	defer base.Free()
	cfg, err := git.OpenOndisk(base, filepath.Join(repoDir, "config"))
	if err != nil {
		return nil, err
	}
	defer cfg.Free()

	remoteURL, err := cfg.LookupString("remote.origin.url")
	if err != nil {
		return nil, err
	}

	parsed, err := url.Parse(remoteURL)
	if err != nil {
		return nil, err
	}

	if strings.HasSuffix(parsed.Host, "googlesource.com") {
		/// eg. https://gerrit.googlesource.com/gitiles/+/master/tools/run_dev.sh#20
		return &templates{
			repo:   remoteURL,
			commit: remoteURL + "/+/{{.Version}}",
			file:   remoteURL + "/+/{{.Branch}}/{{.Path}}",
			line:   "{{.LineNumber}}",
		}, nil
	} else if parsed.Host == "github.com" {
		// CloneURL from the JSON API has .git
		parsed.Path = strings.TrimSuffix(parsed.Path, ".git")

		// eg. https://github.com/hanwen/go-fuse/blob/notify/genversion.sh#L10
		return &templates{
			repo:   parsed.String(),
			commit: parsed.String() + "/commit/{{.Version}}",
			file:   parsed.String() + "/blob/{{.Branch}}/{{.Path}}",
			line:   "L{{.LineNumber}}",
		}, nil
	}

	return nil, fmt.Errorf("scheme unknown for URL %s", remoteURL)
}

// getCommit returns a tree object for the given reference.
func getCommit(repo *git.Repository, ref string) (*git.Commit, error) {
	obj, err := repo.RevparseSingle(ref)
	if err != nil {
		return nil, err
	}
	defer obj.Free()

	commitObj, err := obj.Peel(git.ObjectCommit)
	if err != nil {
		return nil, err
	}
	return commitObj.AsCommit()
}

// IndexGitRepo indexes the git repository as specified by the options and arguments.
func IndexGitRepo(opts build.Options, branchPrefix string, branches []string, submodules bool) error {
	repo, err := git.OpenRepository(opts.RepoDir)
	if err != nil {
		return err
	}

	if tpl, err := guessRepoURL(opts.RepoDir); err != nil {
		log.Printf("guessRepoURL(%s): %s", opts.RepoDir, err)
	} else {
		opts.RepoURL = tpl.repo
		opts.FileURLTemplate = tpl.file
		opts.CommitURLTemplate = tpl.commit
		opts.LineFragmentTemplate = tpl.line
	}

	// name => branch
	allfiles := map[string][]string{}

	var names []string

	// branch => name => sha1
	data := map[string]map[string]git.Oid{}
	repos := map[git.Oid]*git.Repository{}
	for _, b := range branches {
		commit, err := getCommit(repo, filepath.Join(branchPrefix, b))
		if err != nil {
			return err
		}
		defer commit.Free()
		opts.Branches = append(opts.Branches, build.Branch{
			Name:    b,
			Version: commit.Id().String(),
		})

		tree, err := commit.Tree()
		if err != nil {
			return err
		}
		defer tree.Free()
		fs, subRepos, err := treeToFiles(repo, tree, submodules)
		if err != nil {
			return err
		}
		for k, v := range subRepos {
			repos[k] = v
		}

		for f := range fs {
			allfiles[f] = append(allfiles[f], b)
		}
		data[b] = fs
	}

	builder, err := build.NewBuilder(opts)
	if err != nil {
		return err
	}

	for n := range allfiles {
		names = append(names, n)
	}
	sort.Strings(names)

	for _, n := range names {
		shas := map[git.Oid][]string{}
		for _, b := range allfiles[n] {
			shas[data[b][n]] = append(shas[data[b][n]], b)
		}

		for sha, branches := range shas {
			r := repos[sha]
			if r == nil {
				return fmt.Errorf("no repo found for %s (%s)", n, branches)
			}
			blob, err := r.LookupBlob(&sha)
			if err != nil {
				return err
			}

			if blob.Size() > int64(opts.SizeMax) {
				continue
			}

			builder.Add(zoekt.Document{
				Name:     n,
				Content:  blob.Contents(),
				Branches: branches,
			})
		}
	}
	builder.Finish()

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

const Pi = 3.14
const (
	Big   = 1 << 100
	Small = Big >> 99
)

//var i, j int = 1,2
//var c, python, java = true, false, "no!"

func add(x int, y int) int {
	return x + y
}

func subtract(x, y int) int {
	return x - y
}

func swap(x, y string) (string, string) {
	return y, x
}

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
	return x * 0.1
}

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}

	// v is not acessible here, since it was declared
	// within the if statement's scope

	return lim
}

func Sqrt(x float64) float64 {
	// z = z - ((z^2 - x)/2z)

	z := float64(1)

	for i := 1.0; i < 10; i++ {
		z = z - ((math.Pow(z, 2) - x) / 2 * z)
		fmt.Println(i, z)
	}

	return z
}

type Vertex struct {
	X, Y int
}

func main() {

	// UT8 by default
	fmt.Println("Hello, 世界")

	// use imported packages
	fmt.Println("Now you have the %g problems.", math.Nextafter(2, 3))

	// use defined functions
	fmt.Println("2 + 2 =", add(2, 2))

	// functions with multiple arguments of same type of declare type once
	fmt.Println("5 - 3 =", subtract(5, 3))

	// functions can return 2 values
	a, b := swap("up", "down")
	fmt.Println("swapping 'up down'", a, b)

	// functions implicitly return named variables
	fmt.Println(split(17))

	// variable assignment
	var i, j int = 1, 2
	k := 3
	c, python, java := true, false, "no!"
	fmt.Println(i, j, k, c, python, java)

	// constants
	fmt.Println(Pi)
	fmt.Println(needInt(Small))
	fmt.Println(needFloat(Small))
	fmt.Println(needFloat(Big))
	// fmt.Println(needInt(Big))

	// for loop
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)

	// continue loop
	sum = 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)

	// while loop
	sum = 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)

	// if statement
	if 2 > 1 {
		fmt.Println("2 is greater than 1")
	}

	// if short statement
	fmt.Println(pow(3, 2, 10), pow(3, 3, 20))

	// build sqrt to show loops and functions
	fmt.Println(Sqrt(2))

	// instantiate a struct
	fmt.Println(Vertex{1,2})

	// struct values are mutable
	v := Vertex{1,2}
	v.X = 4
	fmt.Println(v.X)

	// struct pointers
	// pointer arithmetic not available
	// http://www.cplusplus.com/doc/tutorial/pointers/#arithmetics
	p := Vertex{1,2}
	q := &p
	q.X = 1e9
	fmt.Println(p)

	// new function
	// "allocates zero type value and returns pointer to it
	h := new(Vertex)
	fmt.Println(h)
	h.X, h.Y = 11, 9
	fmt.Println(h)

	// arrays, which cannot be resized
	var aa [2]string
	aa[0] = "Hello"
	aa[1] = "World"
	fmt.Println(aa[0], aa[1])
	fmt.Println(aa)

	// slices - these are important
	ka := []int{2,3,5,7,11,13}
	fmt.Println("ka == ", ka)
	for i := 0; i < len(ka); i++ {
		fmt.Printf("ka[%d] == %d\n", i, ka[i])
	}

	// slicing slices
	// the new slice points to the same array
	kk := ka[0:3]
	kk[0] = 100
	fmt.Println("kk has mutable access to ka, ka[0] = ",ka[0])
	// slicing actions
	fmt.Println("ka[1:4] == ", ka[1:4])

}
<commit_msg>ah, basic concepts includes more stuff i put in methods and interfaces<commit_after>package main

import (
	"fmt"
	"math"
)

const Pi = 3.14
const (
	Big   = 1 << 100
	Small = Big >> 99
)

func add(x int, y int) int {
	return x + y
}

func subtract(x, y int) int {
	return x - y
}

// return 2 values
func swap(x, y string) (string, string) {
	return y, x
}

// implicitly return all variables
func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func needInt(x int) int { return x*10 + 1 }

func needFloat(x float64) float64 {
	return x * 0.1
}

// variable availability within closures
func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}

	// v is not acessible here, since it was declared
	// within the if statement's scope

	return lim
}

func Sqrt(x float64) float64 {
	// z = z - ((z^2 - x)/2z)

	z := float64(1)

	for i := 1.0; i < 10; i++ {
		z = z - ((math.Pow(z, 2) - x) / 2 * z)
		fmt.Println(i, z)
	}

	return z
}

// creating types
type Vertex struct {
	X, Y int
}

func main() {

	// UT8 by default
	fmt.Println("Hello, 世界")

	// use imported packages
	fmt.Println("Now you have the %g problems.", math.Nextafter(2, 3))

	// use defined functions
	fmt.Println("2 + 2 =", add(2, 2))

	// functions with multiple arguments of same type of declare type once
	fmt.Println("5 - 3 =", subtract(5, 3))

	// functions can return 2 values
	a, b := swap("up", "down")
	fmt.Println("swapping 'up down'", a, b)

	// functions implicitly return named variables
	fmt.Println(split(17))

	// variable assignment
	var i, j int = 1, 2
	k := 3
	c, python, java := true, false, "no!"
	fmt.Println(i, j, k, c, python, java)

	// constants
	fmt.Println(Pi)
	fmt.Println(needInt(Small))
	fmt.Println(needFloat(Small))
	fmt.Println(needFloat(Big))
	// fmt.Println(needInt(Big))

	// for loop
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)

	// continue loop
	sum = 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)

	// while loop
	sum = 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)

	// if statement
	if 2 > 1 {
		fmt.Println("2 is greater than 1")
	}

	// if short statement
	fmt.Println(pow(3, 2, 10), pow(3, 3, 20))

	// build sqrt to show loops and functions
	fmt.Println(Sqrt(2))

	// instantiate a struct
	fmt.Println(Vertex{1,2})

	// struct values are mutable
	v := Vertex{1,2}
	v.X = 4
	fmt.Println(v.X)

	// struct pointers
	// pointer arithmetic not available
	// http://www.cplusplus.com/doc/tutorial/pointers/#arithmetics
	p := Vertex{1,2}
	q := &p
	q.X = 1e9
	fmt.Println(p)

	// new function
	// "allocates zero type value and returns pointer to it
	h := new(Vertex)
	fmt.Println(h)
	h.X, h.Y = 11, 9
	fmt.Println(h)

	// arrays, which cannot be resized
	var aa [2]string
	aa[0] = "Hello"
	aa[1] = "World"
	fmt.Println(aa[0], aa[1])
	fmt.Println(aa)

	// slices - these are important
	ka := []int{2,3,5,7,11,13}
	fmt.Println("ka == ", ka)
	for i := 0; i < len(ka); i++ {
		fmt.Printf("ka[%d] == %d\n", i, ka[i])
	}

	// slicing slices
	// the new slice points to the same array
	kk := ka[0:3]
	kk[0] = 100
	fmt.Println("kk has mutable access to ka, ka[0] = ",ka[0])
	// slicing actions
	fmt.Println("ka[1:4] == ", ka[1:4])

	// making slices
	aaa := make([]int, 5)
	printSlice("aaa", aaa)
	bbb := make([]int, 0, 5)
	printSlice("bbb", bbb)
	ccc := bbb[:2]
	printSlice("ccc", ccc)
	ddd := ccc[2:5]
	printSlice("ddd", ddd)

	// range
	var pow = []int{1,2,4,8,16,32,64,128}
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}

	for i := range pow {
		pow[i] = 1 << uint(i)
	}
	for _, value := range pow {
		fmt.Printf("%d\n", value)
	}

	// closures
	fmt.Println("-------")
	pos, neg := adder(), adder()

	for i := 0; i < 10; i++ {
		fmt.Println(i)
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}

	// fibonacci closure
	fmt.Println("-----\nfibonacci sequence via closures")
	f := fib()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}

}

func fib() func() int {

	// f(n) = fibanocci(n)
	// f(n) = f(n_1) + f(n_2)

	n_1 := 0
	n_2 := 1

	return func() int {
		n_0 := n_1
		n_1 = n_2
		n_2 = n_0 + n_1

		return n_0
	}
}

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func printSlice(s string, x []int) {
	fmt.Printf("%s len=%d cap%d %v\n", s, len(x), cap(x), x)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Tigera, Inc. All rights reserved.

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

package commands

import (
	"errors"
	"fmt"
	"reflect"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/ghodss/yaml"
	"github.com/projectcalico/calico-containers/calicoctl/commands/argutils"
	"github.com/projectcalico/calico-containers/calicoctl/commands/clientmgr"
	"github.com/projectcalico/calico-containers/calicoctl/resourcemgr"
	"github.com/projectcalico/libcalico-go/lib/api"
	"github.com/projectcalico/libcalico-go/lib/api/unversioned"
	"github.com/projectcalico/libcalico-go/lib/client"
	calicoErrors "github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/net"
	"github.com/projectcalico/libcalico-go/lib/scope"
)

type action int

const (
	actionApply action = iota
	actionCreate
	actionUpdate
	actionDelete
	actionList
)

// Convert loaded resources to a slice of resources for easier processing.
// The loaded resources may be a slice containing resources and resource lists, or
// may be a single resource or a single resource list.  This function handles the
// different possible options to convert to a single slice of resources.
func convertToSliceOfResources(loaded interface{}) []unversioned.Resource {
	r := []unversioned.Resource{}
	log.Infof("Converting resource to slice: %v", loaded)

	switch reflect.TypeOf(loaded).Kind() {
	case reflect.Slice:
		// Recursively call this to add each resource in the supplied slice to
		// return slice.
		s := reflect.ValueOf(loaded)
		for i := 0; i < s.Len(); i++ {
			r = append(r, convertToSliceOfResources(s.Index(i).Interface())...)
		}
	case reflect.Struct:
		// This is a resource or resource list.  If a resource, add to our return
		// slice.  If a resource list, add each item to our return slice.
		lr := loaded.(unversioned.Resource)
		if strings.HasSuffix(lr.GetTypeMetadata().Kind, "List") {
			items := reflect.ValueOf(loaded).Elem().FieldByName("Items")
			for i := 0; i < items.Len(); i++ {
				r = append(r, items.Index(i).Interface().(unversioned.Resource))
			}
		} else {
			r = append(r, lr)
		}
	case reflect.Ptr:
		// This is a resource or resource list.  If a resource, add to our return
		// slice.  If a resource list, add each item to our return slice.
		lr := reflect.ValueOf(loaded).Elem().Interface().(unversioned.Resource)
		if strings.HasSuffix(lr.GetTypeMetadata().Kind, "List") {
			items := reflect.ValueOf(loaded).Elem().FieldByName("Items")
			for i := 0; i < items.Len(); i++ {
				r = append(r, items.Index(i).Interface().(unversioned.Resource))
			}
		} else {
			r = append(r, lr)
		}
	default:
		panic(errors.New(fmt.Sprintf("unhandled type %v converting to resource slice",
			reflect.TypeOf(loaded).Kind())))
	}

	log.Infof("Returning slice: %v", r)
	return r
}

// getResourceFromArguments returns a resource instance from the command line arguments.
func getResourceFromArguments(args map[string]interface{}) (unversioned.Resource, error) {
	kind := args["<KIND>"].(string)
	name := argutils.ArgStringOrBlank(args, "<NAME>")
	node := argutils.ArgStringOrBlank(args, "--node")
	workload := argutils.ArgStringOrBlank(args, "--workload")
	orchestrator := argutils.ArgStringOrBlank(args, "--orchestrator")
	resScope := argutils.ArgStringOrBlank(args, "--scope")
	switch strings.ToLower(kind) {
	case "node", "nodes":
		p := api.NewNode()
		p.Metadata.Name = name
		return *p, nil
	case "hostendpoint", "hostendpoints":
		h := api.NewHostEndpoint()
		h.Metadata.Name = name
		h.Metadata.Node = node
		return *h, nil
	case "workloadendpoint", "workloadendpoints":
		h := api.NewWorkloadEndpoint()
		h.Metadata.Name = name
		h.Metadata.Orchestrator = orchestrator
		h.Metadata.Workload = workload
		h.Metadata.Node = node
		return *h, nil
	case "profile", "profiles":
		p := api.NewProfile()
		p.Metadata.Name = name
		return *p, nil
	case "policy", "policies":
		p := api.NewPolicy()
		p.Metadata.Name = name
		return *p, nil
	case "ippool", "ippools":
		p := api.NewIPPool()
		if name != "" {
			_, cidr, err := net.ParseCIDR(name)
			if err != nil {
				return nil, err
			}
			p.Metadata.CIDR = *cidr
		}
		return *p, nil
	case "bgppeer", "bgppeers":
		p := api.NewBGPPeer()
		if name != "" {
			err := p.Metadata.PeerIP.UnmarshalText([]byte(name))
			if err != nil {
				return nil, err
			}
		}
		p.Metadata.Node = node
		switch resScope {
		case "node":
			p.Metadata.Scope = scope.Node
		case "global":
			p.Metadata.Scope = scope.Global
		case "":
			p.Metadata.Scope = scope.Undefined
		default:
			return nil, fmt.Errorf("Unrecognized scope '%s', must be one of: global, node", resScope)
		}
		return *p, nil

	default:
		return nil, fmt.Errorf("Resource type '%s' is not supported", kind)
	}
}

// commandResults contains the results from executing a CLI command
type commandResults struct {
	// Whether the input file was invalid.
	fileInvalid bool

	// The number of resources that are being configured.
	numResources int

	// The number of resources that were actually configured.  This will
	// never be 0 without an associated error.
	numHandled int

	// The associated error.
	err error

	// The single type of resource that is being configured, or blank
	// if multiple resource types are being configured in a single shot.
	singleKind string

	// The results returned from each invocation
	resources []unversioned.Resource
}

// executeConfigCommand is main function called by all of the resource management commands
// in calicoctl (apply, create, replace, get and delete).  This provides common function
// for all these commands:
// 	-  Load resources from file (or if not specified determine the resource from
// 	   the command line options).
// 	-  Convert the loaded resources into a list of resources (easier to handle)
// 	-  Process each resource individually, fanning out to the appropriate methods on
//	   the client interface, collate results and exit on the first error.
func executeConfigCommand(args map[string]interface{}, action action) commandResults {
	var r interface{}
	var err error
	var resources []unversioned.Resource

	log.Info("Executing config command")

	if filename := args["--filename"]; filename != nil {
		// Filename is specified, load the resource from file and convert to a slice
		// of resources for easier handling.
		if r, err = resourcemgr.CreateResourcesFromFile(filename.(string)); err != nil {
			return commandResults{err: err, fileInvalid: true}
		}

		resources = convertToSliceOfResources(r)
	} else if r, err := getResourceFromArguments(args); err != nil {
		// Filename is not specific so extract the resource from the arguments.  This
		// is only useful for delete and get functions - but we don't need to check that
		// here since the command syntax requires a filename for the other resource
		// management commands.
		return commandResults{err: err}
	} else {
		// We extracted a single resource type with identifiers from the CLI, convert to
		// a list for simpler handling.
		resources = []unversioned.Resource{r}
	}

	if len(resources) == 0 {
		return commandResults{err: errors.New("no resources specified")}
	}

	if log.GetLevel() >= log.DebugLevel {
		log.Debugf("Resources: %v", resources)
		d, err := yaml.Marshal(resources)
		if err != nil {
			return commandResults{err: err}
		}
		log.Debugf("Data: %s", string(d))
	}

	// Load the client config and connect.
	cf := args["--config"].(string)
	client, err := clientmgr.NewClient(cf)
	if err != nil {
		return commandResults{err: err}
	}
	log.Infof("Client: %v", client)

	// Initialise the command results with the number of resources and the name of the
	// kind of resource (if only dealing with a single resource).
	var results commandResults
	var kind string
	count := make(map[string]int)
	for _, r := range resources {
		kind = r.GetTypeMetadata().Kind
		count[kind] = count[kind] + 1
		results.numResources = results.numResources + 1
	}
	if len(count) == 1 {
		results.singleKind = kind
	}

	// Now execute the command on each resource in order, exiting as soon as we hit an
	// error.
	for _, r := range resources {
		r, err = executeResourceAction(args, client, r, action)
		if err != nil {
			results.err = err
			break
		}
		results.resources = append(results.resources, r)
		results.numHandled = results.numHandled + 1
	}

	return results
}

// execureResourceAction fans out the specific resource action to the appropriate method
// on the ResourceManager for the specific resource.
func executeResourceAction(args map[string]interface{}, client *client.Client, resource unversioned.Resource, action action) (unversioned.Resource, error) {
	rm := resourcemgr.GetResourceManager(resource)
	var err error
	var resourceOut unversioned.Resource

	switch action {
	case actionApply:
		resourceOut, err = rm.Apply(client, resource)
	case actionCreate:
		resourceOut, err = rm.Create(client, resource)
	case actionUpdate:
		resourceOut, err = rm.Update(client, resource)
	case actionDelete:
		resourceOut, err = rm.Delete(client, resource)
	case actionList:
		resourceOut, err = rm.List(client, resource)
	}

	// Skip over some errors depending on command line options.
	if err != nil {
		skip := false
		switch err.(type) {
		case calicoErrors.ErrorResourceAlreadyExists:
			skip = argutils.ArgBoolOrFalse(args, "--skip-exists")
		case calicoErrors.ErrorResourceDoesNotExist:
			skip = argutils.ArgBoolOrFalse(args, "--skip-not-exists")
		}
		if skip {
			resourceOut = resource
			err = nil
		}
	}

	return resourceOut, err
}
<commit_msg>Add a selection of resource aliases<commit_after>// Copyright (c) 2016 Tigera, Inc. All rights reserved.

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

package commands

import (
	"errors"
	"fmt"
	"reflect"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/ghodss/yaml"
	"github.com/projectcalico/calico-containers/calicoctl/commands/argutils"
	"github.com/projectcalico/calico-containers/calicoctl/commands/clientmgr"
	"github.com/projectcalico/calico-containers/calicoctl/resourcemgr"
	"github.com/projectcalico/libcalico-go/lib/api"
	"github.com/projectcalico/libcalico-go/lib/api/unversioned"
	"github.com/projectcalico/libcalico-go/lib/client"
	calicoErrors "github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/net"
	"github.com/projectcalico/libcalico-go/lib/scope"
)

type action int

const (
	actionApply action = iota
	actionCreate
	actionUpdate
	actionDelete
	actionList
)

// Convert loaded resources to a slice of resources for easier processing.
// The loaded resources may be a slice containing resources and resource lists, or
// may be a single resource or a single resource list.  This function handles the
// different possible options to convert to a single slice of resources.
func convertToSliceOfResources(loaded interface{}) []unversioned.Resource {
	r := []unversioned.Resource{}
	log.Infof("Converting resource to slice: %v", loaded)

	switch reflect.TypeOf(loaded).Kind() {
	case reflect.Slice:
		// Recursively call this to add each resource in the supplied slice to
		// return slice.
		s := reflect.ValueOf(loaded)
		for i := 0; i < s.Len(); i++ {
			r = append(r, convertToSliceOfResources(s.Index(i).Interface())...)
		}
	case reflect.Struct:
		// This is a resource or resource list.  If a resource, add to our return
		// slice.  If a resource list, add each item to our return slice.
		lr := loaded.(unversioned.Resource)
		if strings.HasSuffix(lr.GetTypeMetadata().Kind, "List") {
			items := reflect.ValueOf(loaded).Elem().FieldByName("Items")
			for i := 0; i < items.Len(); i++ {
				r = append(r, items.Index(i).Interface().(unversioned.Resource))
			}
		} else {
			r = append(r, lr)
		}
	case reflect.Ptr:
		// This is a resource or resource list.  If a resource, add to our return
		// slice.  If a resource list, add each item to our return slice.
		lr := reflect.ValueOf(loaded).Elem().Interface().(unversioned.Resource)
		if strings.HasSuffix(lr.GetTypeMetadata().Kind, "List") {
			items := reflect.ValueOf(loaded).Elem().FieldByName("Items")
			for i := 0; i < items.Len(); i++ {
				r = append(r, items.Index(i).Interface().(unversioned.Resource))
			}
		} else {
			r = append(r, lr)
		}
	default:
		panic(errors.New(fmt.Sprintf("unhandled type %v converting to resource slice",
			reflect.TypeOf(loaded).Kind())))
	}

	log.Infof("Returning slice: %v", r)
	return r
}

// getResourceFromArguments returns a resource instance from the command line arguments.
func getResourceFromArguments(args map[string]interface{}) (unversioned.Resource, error) {
	kind := args["<KIND>"].(string)
	name := argutils.ArgStringOrBlank(args, "<NAME>")
	node := argutils.ArgStringOrBlank(args, "--node")
	workload := argutils.ArgStringOrBlank(args, "--workload")
	orchestrator := argutils.ArgStringOrBlank(args, "--orchestrator")
	resScope := argutils.ArgStringOrBlank(args, "--scope")
	switch strings.ToLower(kind) {
	case "node", "nodes", "no", "nos":
		p := api.NewNode()
		p.Metadata.Name = name
		return *p, nil
	case "hostendpoint", "hostendpoints", "hep", "heps":
		h := api.NewHostEndpoint()
		h.Metadata.Name = name
		h.Metadata.Node = node
		return *h, nil
	case "workloadendpoint", "workloadendpoints", "wep", "weps":
		h := api.NewWorkloadEndpoint()
		h.Metadata.Name = name
		h.Metadata.Orchestrator = orchestrator
		h.Metadata.Workload = workload
		h.Metadata.Node = node
		return *h, nil
	case "profile", "profiles", "pro", "pros":
		p := api.NewProfile()
		p.Metadata.Name = name
		return *p, nil
	case "policy", "policies", "pol", "pols":
		p := api.NewPolicy()
		p.Metadata.Name = name
		return *p, nil
	case "ippool", "ippools", "ipp", "ipps", "pool", "pools":
		p := api.NewIPPool()
		if name != "" {
			_, cidr, err := net.ParseCIDR(name)
			if err != nil {
				return nil, err
			}
			p.Metadata.CIDR = *cidr
		}
		return *p, nil
	case "bgppeer", "bgppeers", "bgpp", "bgpps", "bp", "bps":
		p := api.NewBGPPeer()
		if name != "" {
			err := p.Metadata.PeerIP.UnmarshalText([]byte(name))
			if err != nil {
				return nil, err
			}
		}
		p.Metadata.Node = node
		switch resScope {
		case "node":
			p.Metadata.Scope = scope.Node
		case "global":
			p.Metadata.Scope = scope.Global
		case "":
			p.Metadata.Scope = scope.Undefined
		default:
			return nil, fmt.Errorf("Unrecognized scope '%s', must be one of: global, node", resScope)
		}
		return *p, nil

	default:
		return nil, fmt.Errorf("Resource type '%s' is not supported", kind)
	}
}

// commandResults contains the results from executing a CLI command
type commandResults struct {
	// Whether the input file was invalid.
	fileInvalid bool

	// The number of resources that are being configured.
	numResources int

	// The number of resources that were actually configured.  This will
	// never be 0 without an associated error.
	numHandled int

	// The associated error.
	err error

	// The single type of resource that is being configured, or blank
	// if multiple resource types are being configured in a single shot.
	singleKind string

	// The results returned from each invocation
	resources []unversioned.Resource
}

// executeConfigCommand is main function called by all of the resource management commands
// in calicoctl (apply, create, replace, get and delete).  This provides common function
// for all these commands:
// 	-  Load resources from file (or if not specified determine the resource from
// 	   the command line options).
// 	-  Convert the loaded resources into a list of resources (easier to handle)
// 	-  Process each resource individually, fanning out to the appropriate methods on
//	   the client interface, collate results and exit on the first error.
func executeConfigCommand(args map[string]interface{}, action action) commandResults {
	var r interface{}
	var err error
	var resources []unversioned.Resource

	log.Info("Executing config command")

	if filename := args["--filename"]; filename != nil {
		// Filename is specified, load the resource from file and convert to a slice
		// of resources for easier handling.
		if r, err = resourcemgr.CreateResourcesFromFile(filename.(string)); err != nil {
			return commandResults{err: err, fileInvalid: true}
		}

		resources = convertToSliceOfResources(r)
	} else if r, err := getResourceFromArguments(args); err != nil {
		// Filename is not specific so extract the resource from the arguments.  This
		// is only useful for delete and get functions - but we don't need to check that
		// here since the command syntax requires a filename for the other resource
		// management commands.
		return commandResults{err: err}
	} else {
		// We extracted a single resource type with identifiers from the CLI, convert to
		// a list for simpler handling.
		resources = []unversioned.Resource{r}
	}

	if len(resources) == 0 {
		return commandResults{err: errors.New("no resources specified")}
	}

	if log.GetLevel() >= log.DebugLevel {
		log.Debugf("Resources: %v", resources)
		d, err := yaml.Marshal(resources)
		if err != nil {
			return commandResults{err: err}
		}
		log.Debugf("Data: %s", string(d))
	}

	// Load the client config and connect.
	cf := args["--config"].(string)
	client, err := clientmgr.NewClient(cf)
	if err != nil {
		return commandResults{err: err}
	}
	log.Infof("Client: %v", client)

	// Initialise the command results with the number of resources and the name of the
	// kind of resource (if only dealing with a single resource).
	var results commandResults
	var kind string
	count := make(map[string]int)
	for _, r := range resources {
		kind = r.GetTypeMetadata().Kind
		count[kind] = count[kind] + 1
		results.numResources = results.numResources + 1
	}
	if len(count) == 1 {
		results.singleKind = kind
	}

	// Now execute the command on each resource in order, exiting as soon as we hit an
	// error.
	for _, r := range resources {
		r, err = executeResourceAction(args, client, r, action)
		if err != nil {
			results.err = err
			break
		}
		results.resources = append(results.resources, r)
		results.numHandled = results.numHandled + 1
	}

	return results
}

// execureResourceAction fans out the specific resource action to the appropriate method
// on the ResourceManager for the specific resource.
func executeResourceAction(args map[string]interface{}, client *client.Client, resource unversioned.Resource, action action) (unversioned.Resource, error) {
	rm := resourcemgr.GetResourceManager(resource)
	var err error
	var resourceOut unversioned.Resource

	switch action {
	case actionApply:
		resourceOut, err = rm.Apply(client, resource)
	case actionCreate:
		resourceOut, err = rm.Create(client, resource)
	case actionUpdate:
		resourceOut, err = rm.Update(client, resource)
	case actionDelete:
		resourceOut, err = rm.Delete(client, resource)
	case actionList:
		resourceOut, err = rm.List(client, resource)
	}

	// Skip over some errors depending on command line options.
	if err != nil {
		skip := false
		switch err.(type) {
		case calicoErrors.ErrorResourceAlreadyExists:
			skip = argutils.ArgBoolOrFalse(args, "--skip-exists")
		case calicoErrors.ErrorResourceDoesNotExist:
			skip = argutils.ArgBoolOrFalse(args, "--skip-not-exists")
		}
		if skip {
			resourceOut = resource
			err = nil
		}
	}

	return resourceOut, err
}
<|endoftext|>


<commit_before>package gobp_test

import (
	"bytes"
	"log"
	"runtime"
	"sync"
	"testing"

	"github.com/karrick/gobp"
	"github.com/karrick/gopool"
)

const (
	bufSize  = 16 * 1024
	poolSize = 64
)

func newBuf() *bytes.Buffer { return bytes.NewBuffer(make([]byte, 0, bufSize)) }

func newGobp() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p := &gobp.Pool{
		BufSizeInit: bufSize,
		PoolSizeMax: poolSize,
	}
	for i := 0; i < poolSize; i++ {
		p.Put(newBuf())
	}
	return p.Get, p.Put
}

func newGopool() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p, err := gopool.New(gopool.Size(poolSize),
		gopool.Factory(func() (interface{}, error) {
			return newBuf(), nil
		}),
		gopool.Reset(func(item interface{}) {
			item.(*bytes.Buffer).Reset()
		}))
	if err != nil {
		log.Fatal(err)
	}
	setup := func() *bytes.Buffer {
		return p.Get().(*bytes.Buffer)
	}
	teardown := func(buf *bytes.Buffer) {
		p.Put(buf)
	}
	return setup, teardown
}

func newSyncPool() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p := &sync.Pool{
		New: func() interface{} { return newBuf() },
	}
	for i := 0; i < poolSize; i++ {
		p.Put(newBuf())
	}
	setup := func() *bytes.Buffer {
		return p.Get().(*bytes.Buffer)
	}
	teardown := func(buf *bytes.Buffer) {
		buf.Reset()
		p.Put(buf)
	}
	return setup, teardown
}

////////////////////////////////////////

func exercise(setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	buf := setup()
	defer teardown(buf)

	for i := 0; i < bufSize; i++ {
		buf.WriteByte(byte(i % 256))
	}
}

func benchmarkLow(b *testing.B, setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			exercise(setup, teardown)
		}
	})
}

func benchmarkHigh(b *testing.B, setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	concurrency := runtime.NumCPU() * 100
	var wg sync.WaitGroup
	wg.Add(concurrency)

	b.ResetTimer()

	for c := 0; c < concurrency; c++ {
		go func() {
			defer wg.Done()

			for n := 0; n < b.N; n++ {
				exercise(setup, teardown)
			}
		}()
	}

	wg.Wait()
}

////////////////////////////////////////
// Low Concurrency

func BenchmarkLowConcurrencyGobp(b *testing.B) {
	setup, teardown := newGobp()
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencyGopool(b *testing.B) {
	setup, teardown := newGopool()
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencyNoPool(b *testing.B) {
	setup, teardown := newBuf, func(_ *bytes.Buffer) {}
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencySyncPool(b *testing.B) {
	setup, teardown := newSyncPool()
	benchmarkLow(b, setup, teardown)
}

////////////////////////////////////////
// High Concurrency

func BenchmarkHighConcurrencyGobp(b *testing.B) {
	setup, teardown := newGobp()
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencyGopool(b *testing.B) {
	setup, teardown := newGopool()
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencyNoPool(b *testing.B) {
	setup, teardown := newBuf, func(_ *bytes.Buffer) {}
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencySyncPool(b *testing.B) {
	setup, teardown := newSyncPool()
	benchmarkHigh(b, setup, teardown)
}
<commit_msg>added benchmark against github.com/oxtoacart/bpool<commit_after>package gobp_test

import (
	"bytes"
	"log"
	"runtime"
	"sync"
	"testing"

	"github.com/karrick/gobp"
	"github.com/karrick/gopool"
	"github.com/oxtoacart/bpool"
)

const (
	bufSize  = 16 * 1024
	poolSize = 64
)

func newBuf() *bytes.Buffer { return bytes.NewBuffer(make([]byte, 0, bufSize)) }

func newBspool() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p := bpool.NewSizedBufferPool(poolSize, bufSize)
	setup := func() *bytes.Buffer {
		return p.Get()
	}
	teardown := func(buf *bytes.Buffer) {
		p.Put(buf)
	}
	return setup, teardown
}

func newGobp() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p := &gobp.Pool{
		BufSizeInit: bufSize,
		PoolSizeMax: poolSize,
	}
	for i := 0; i < poolSize; i++ {
		p.Put(newBuf())
	}
	return p.Get, p.Put
}

func newGopool() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p, err := gopool.New(gopool.Size(poolSize),
		gopool.Factory(func() (interface{}, error) {
			return newBuf(), nil
		}),
		gopool.Reset(func(item interface{}) {
			item.(*bytes.Buffer).Reset()
		}))
	if err != nil {
		log.Fatal(err)
	}
	setup := func() *bytes.Buffer {
		return p.Get().(*bytes.Buffer)
	}
	teardown := func(buf *bytes.Buffer) {
		p.Put(buf)
	}
	return setup, teardown
}

func newSyncPool() (func() *bytes.Buffer, func(*bytes.Buffer)) {
	p := &sync.Pool{
		New: func() interface{} { return newBuf() },
	}
	for i := 0; i < poolSize; i++ {
		p.Put(newBuf())
	}
	setup := func() *bytes.Buffer {
		return p.Get().(*bytes.Buffer)
	}
	teardown := func(buf *bytes.Buffer) {
		buf.Reset()
		p.Put(buf)
	}
	return setup, teardown
}

////////////////////////////////////////

func exercise(setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	buf := setup()
	defer teardown(buf)

	for i := 0; i < bufSize; i++ {
		buf.WriteByte(byte(i % 256))
	}
}

func benchmarkLow(b *testing.B, setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			exercise(setup, teardown)
		}
	})
}

func benchmarkHigh(b *testing.B, setup func() *bytes.Buffer, teardown func(*bytes.Buffer)) {
	concurrency := runtime.NumCPU() * 100
	var wg sync.WaitGroup
	wg.Add(concurrency)

	b.ResetTimer()

	for c := 0; c < concurrency; c++ {
		go func() {
			defer wg.Done()

			for n := 0; n < b.N; n++ {
				exercise(setup, teardown)
			}
		}()
	}

	wg.Wait()
}

////////////////////////////////////////
// Low Concurrency

func BenchmarkLowConcurrencyBspool(b *testing.B) {
	setup, teardown := newBspool()
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencyGobp(b *testing.B) {
	setup, teardown := newGobp()
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencyGopool(b *testing.B) {
	setup, teardown := newGopool()
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencyNoPool(b *testing.B) {
	setup, teardown := newBuf, func(_ *bytes.Buffer) {}
	benchmarkLow(b, setup, teardown)
}

func BenchmarkLowConcurrencySyncPool(b *testing.B) {
	setup, teardown := newSyncPool()
	benchmarkLow(b, setup, teardown)
}

////////////////////////////////////////
// High Concurrency

func BenchmarkHighConcurrencyBspool(b *testing.B) {
	setup, teardown := newBspool()
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencyGobp(b *testing.B) {
	setup, teardown := newGobp()
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencyGopool(b *testing.B) {
	setup, teardown := newGopool()
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencyNoPool(b *testing.B) {
	setup, teardown := newBuf, func(_ *bytes.Buffer) {}
	benchmarkHigh(b, setup, teardown)
}

func BenchmarkHighConcurrencySyncPool(b *testing.B) {
	setup, teardown := newSyncPool()
	benchmarkHigh(b, setup, teardown)
}
<|endoftext|>


<commit_before>/*-
 * Copyright 2015 Square 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 auth

import (
	"crypto/x509"
	"crypto/x509/pkix"
	"net"
	"testing"

	"github.com/spiffe/go-spiffe/uri"
	"github.com/stretchr/testify/assert"
)

var fakeChains = [][]*x509.Certificate{
	{
		{
			Subject: pkix.Name{
				CommonName:         "gopher",
				OrganizationalUnit: []string{"triangle", "circle"},
			},
			DNSNames:    []string{"circle"},
			IPAddresses: []net.IP{net.IPv4(192, 168, 99, 100)},
			Extensions: []pkix.Extension{
				{
					Id:       uri.OidExtensionSubjectAltName,
					Value:    getURISANFromString("scheme://valid/path"),
					Critical: false,
				},
			},
		},
	},
}

func getURISANFromString(s string) (uriSAN []byte) {
	uriSAN, err := uri.MarshalUriSANs([]string{s})
	if err != nil {
		panic(err)
	}

	return uriSAN
}

func TestAuthorizeNotVerified(t *testing.T) {
	testACL := Acl{
		AllowAll: true,
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, nil), "conn w/o cert should be rejected")
}

func TestAuthorizeReject(t *testing.T) {
	testACL := Acl{
		AllowedCNs:  []string{"test"},
		AllowedOUs:  []string{"test"},
		AllowedDNSs: []string{"test"},
		AllowedURIs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "should reject cert w/o matching CN/OU")
}

func TestAuthorizeAllowAll(t *testing.T) {
	testACL := Acl{
		AllowAll: true,
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-all should always allow authed clients")
}

func TestAuthorizeAllowCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"gopher"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-cn should allow clients with matching CN")
}

func TestAuthorizeAllowOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-ou should allow clients with matching OU")
}

func TestAuthorizeAllowDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-dns-san should allow clients with matching DNS SAN")
}

func TestAuthorizeAllowIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(192, 168, 99, 100)},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-ip-san should allow clients with matching IP SAN")
}

func TestAuthorizeAllowURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://valid/path"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-uri-san should allow clients with matching URI SAN")
}

func TestAuthorizeRejectURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"schema://invalid/path"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "should reject cert w/o matching URI")
}

func TestVerifyAllowCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"gopher"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-cn should allow servers with matching CN")
}

func TestVerifyAllowOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-ou should allow servers with matching OU")
}

func TestVerifyAllowDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-dns-san should allow servers with matching DNS SAN")
}

func TestVerifyAllowIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(192, 168, 99, 100)},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-ip-san should allow servers with matching IP SAN")
}

func TestVerifyRejectCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching CN")
}

func TestVerifyRejectOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching OU")
}

func TestVerifyRejectDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching DNS SAN")
}

func TestVerifyRejectIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(1, 1, 1, 1)},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching IP SAN")
}

func TestVerifyAllowURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://valid/path"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-uri-san should allow clients with matching URI SAN")
}

func TestVerifyRejectURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://invalid/path"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching URI")
}

func TestVerifyNoVerifiedChains(t *testing.T) {
	testACL := Acl{}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, nil), "should reject if no verified chains")
}
<commit_msg>Add extra test case for auth package<commit_after>/*-
 * Copyright 2015 Square 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 auth

import (
	"crypto/x509"
	"crypto/x509/pkix"
	"net"
	"testing"

	"github.com/spiffe/go-spiffe/uri"
	"github.com/stretchr/testify/assert"
)

var fakeChains = [][]*x509.Certificate{
	{
		{
			Subject: pkix.Name{
				CommonName:         "gopher",
				OrganizationalUnit: []string{"triangle", "circle"},
			},
			DNSNames:    []string{"circle"},
			IPAddresses: []net.IP{net.IPv4(192, 168, 99, 100)},
			Extensions: []pkix.Extension{
				{
					Id:       uri.OidExtensionSubjectAltName,
					Value:    getURISANFromString("scheme://valid/path"),
					Critical: false,
				},
			},
		},
	},
}

func getURISANFromString(s string) (uriSAN []byte) {
	uriSAN, err := uri.MarshalUriSANs([]string{s})
	if err != nil {
		panic(err)
	}

	return uriSAN
}

func TestAuthorizeNotVerified(t *testing.T) {
	testACL := Acl{
		AllowAll: true,
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, nil), "conn w/o cert should be rejected")
}

func TestAuthorizeReject(t *testing.T) {
	testACL := Acl{
		AllowedCNs:  []string{"test"},
		AllowedOUs:  []string{"test"},
		AllowedDNSs: []string{"test"},
		AllowedURIs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "should reject cert w/o matching CN/OU")
}

func TestAuthorizeAllowAll(t *testing.T) {
	testACL := Acl{
		AllowAll: true,
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-all should always allow authed clients")
}

func TestAuthorizeAllowCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"gopher"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-cn should allow clients with matching CN")
}

func TestAuthorizeAllowOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-ou should allow clients with matching OU")
}

func TestAuthorizeAllowDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-dns-san should allow clients with matching DNS SAN")
}

func TestAuthorizeAllowIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(192, 168, 99, 100)},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-ip-san should allow clients with matching IP SAN")
}

func TestAuthorizeAllowURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://valid/path"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "allow-uri-san should allow clients with matching URI SAN")
}

func TestAuthorizeRejectURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"schema://invalid/path"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateServer(nil, fakeChains), "should reject cert w/o matching URI")
}

func TestVerifyAllowEmpty(t *testing.T) {
	testACL := Acl{}

	// For VerifyPeerCertificateClient, we perform hostname verification
	// and skip ACLs if the ACL is empty (i.e. no flag has been set to verify
	// any attributes of the server peer certificate).
	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "empty client ACL skips extra checks")
}

func TestVerifyAllowCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"gopher"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-cn should allow servers with matching CN")
}

func TestVerifyAllowOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-ou should allow servers with matching OU")
}

func TestVerifyAllowDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"circle"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-dns-san should allow servers with matching DNS SAN")
}

func TestVerifyAllowIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(192, 168, 99, 100)},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-ip-san should allow servers with matching IP SAN")
}

func TestVerifyRejectCN(t *testing.T) {
	testACL := Acl{
		AllowedCNs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching CN")
}

func TestVerifyRejectOU(t *testing.T) {
	testACL := Acl{
		AllowedOUs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching OU")
}

func TestVerifyRejectDNS(t *testing.T) {
	testACL := Acl{
		AllowedDNSs: []string{"test"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching DNS SAN")
}

func TestVerifyRejectIP(t *testing.T) {
	testACL := Acl{
		AllowedIPs: []net.IP{net.IPv4(1, 1, 1, 1)},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching IP SAN")
}

func TestVerifyAllowURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://valid/path"},
	}

	assert.Nil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "verify-uri-san should allow clients with matching URI SAN")
}

func TestVerifyRejectURI(t *testing.T) {
	testACL := Acl{
		AllowedURIs: []string{"scheme://invalid/path"},
	}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, fakeChains), "should reject cert w/o matching URI")
}

func TestVerifyNoVerifiedChains(t *testing.T) {
	testACL := Acl{}

	assert.NotNil(t, testACL.VerifyPeerCertificateClient(nil, nil), "should reject if no verified chains")
}
<|endoftext|>


<commit_before>package dpn_test

// Common functions for dpn_test package

import (
	"github.com/APTrust/bagman/bagman"
	"github.com/APTrust/bagman/dpn"
	"github.com/crowdmob/goamz/aws"
	"testing"
)

var config bagman.Config
var fluctusUrl string = "http://localhost:3000"

func awsEnvAvailable() (envVarsOk bool) {
	_, err := aws.EnvAuth()
	return err == nil
}

func loadConfig(t *testing.T, configPath string) (*dpn.DPNConfig) {
	if dpnConfig != nil {
		return dpnConfig
	}
	var err error
	dpnConfig, err = dpn.LoadConfig(configPath)
	if err != nil {
		t.Errorf("Error loading %s: %v\n", configPath, err)
		return nil
	}
	return dpnConfig
}
<commit_msg>Don't log to stdout during tests<commit_after>package dpn_test

// Common functions for dpn_test package

import (
	"github.com/APTrust/bagman/bagman"
	"github.com/APTrust/bagman/dpn"
	"github.com/crowdmob/goamz/aws"
	"testing"
)

var config bagman.Config
var fluctusUrl string = "http://localhost:3000"

func awsEnvAvailable() (envVarsOk bool) {
	_, err := aws.EnvAuth()
	return err == nil
}

func loadConfig(t *testing.T, configPath string) (*dpn.DPNConfig) {
	if dpnConfig != nil {
		return dpnConfig
	}
	var err error
	dpnConfig, err = dpn.LoadConfig(configPath)
	if err != nil {
		t.Errorf("Error loading %s: %v\n", configPath, err)
		return nil
	}

	// Turn this off to suppress tons of debug messages.
	dpnConfig.LogLevel = 0
	dpnConfig.LogToStderr = false

	return dpnConfig
}
<|endoftext|>