<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package lxc

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/juju/errors"
	"github.com/juju/utils/proxy"
	"github.com/juju/utils/tailer"
	"launchpad.net/golxc"

	corecloudinit "github.com/juju/juju/cloudinit"
	"github.com/juju/juju/container"
	"github.com/juju/juju/environs/cloudinit"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/juju/arch"
	"github.com/juju/juju/service"
)

var (
	TemplateLockDir = "/var/lib/juju/locks"

	TemplateStopTimeout = 5 * time.Minute
)

// templateUserData returns a minimal user data necessary for the template.
// This should have the authorized keys, base packages, the cloud archive if
// necessary,  initial apt proxy config, and it should do the apt-get
// update/upgrade initially.
func templateUserData(
	series string,
	authorizedKeys string,
	aptProxy proxy.Settings,
	aptMirror string,
	enablePackageUpdates bool,
	enableOSUpgrades bool,
) ([]byte, error) {
	config := corecloudinit.New()
	config.AddScripts(
		"set -xe", // ensure we run all the scripts or abort.
	)
	// For LTS series which need support for the cloud-tools archive,
	// we need to enable apt-get update regardless of the environ
	// setting, otherwise provisioning will fail.
	if series == "precise" && !enablePackageUpdates {
		logger.Warningf("series %q requires cloud-tools archive: enabling updates", series)
		enablePackageUpdates = true
	}

	config.AddSSHAuthorizedKeys(authorizedKeys)
	if enablePackageUpdates {
		cloudinit.MaybeAddCloudArchiveCloudTools(config, series)
	}
	cloudinit.AddAptCommands(series, aptProxy, aptMirror, config, enablePackageUpdates, enableOSUpgrades)

	initSystem := containerInitSystem()
	script, err := shutdownInitScript(initSystem)
	if err != nil {
		return nil, errors.Trace(err)
	}
	config.AddScripts(script)

	renderer, err := corecloudinit.NewRenderer(series)
	if err != nil {
		return nil, err
	}
	data, err := renderer.Render(config)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func containerInitSystem() string {
	// TODO(ericsnow) Where to find it...
	return service.InitSystemUpstart
}

func shutdownInitScript(initSystem string) (string, error) {
	name := "juju-template-restart"
	conf, err := service.ShutdownAfterConf("cloud-final")
	if err != nil {
		return "", errors.Trace(err)
	}

	svc, err := service.NewService(name, conf, initSystem)
	if err != nil {
		return "", errors.Trace(err)
	}

	cmds, err := svc.InstallCommands()
	if err != nil {
		return "", errors.Trace(err)
	}

	return strings.Join(cmds, "\n"), nil
}

func AcquireTemplateLock(name, message string) (*container.Lock, error) {
	logger.Infof("wait for flock on %v", name)
	lock, err := container.NewLock(TemplateLockDir, name)
	if err != nil {
		logger.Tracef("failed to create flock for template: %v", err)
		return nil, err
	}
	err = lock.Lock(message)
	if err != nil {
		logger.Tracef("failed to acquire lock for template: %v", err)
		return nil, err
	}
	return lock, nil
}

// Make sure a template exists that we can clone from.
func EnsureCloneTemplate(
	backingFilesystem string,
	series string,
	networkConfig *container.NetworkConfig,
	authorizedKeys string,
	aptProxy proxy.Settings,
	aptMirror string,
	enablePackageUpdates bool,
	enableOSUpgrades bool,
	imageURLGetter container.ImageURLGetter,
) (golxc.Container, error) {
	name := fmt.Sprintf("juju-%s-lxc-template", series)
	containerDirectory, err := container.NewDirectory(name)
	if err != nil {
		return nil, err
	}

	lock, err := AcquireTemplateLock(name, "ensure clone exists")
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	lxcContainer := LxcObjectFactory.New(name)
	// Early exit if the container has been constructed before.
	if lxcContainer.IsConstructed() {
		logger.Infof("template exists, continuing")
		return lxcContainer, nil
	}
	logger.Infof("template does not exist, creating")

	userData, err := templateUserData(
		series,
		authorizedKeys,
		aptProxy,
		aptMirror,
		enablePackageUpdates,
		enableOSUpgrades,
	)
	if err != nil {
		logger.Tracef("failed to create template user data for template: %v", err)
		return nil, err
	}
	userDataFilename, err := container.WriteCloudInitFile(containerDirectory, userData)
	if err != nil {
		return nil, err
	}

	templateParams := []string{
		"--debug",                      // Debug errors in the cloud image
		"--userdata", userDataFilename, // Our groovey cloud-init
		"--hostid", name, // Use the container name as the hostid
		"-r", series,
	}
	var caCert []byte
	if imageURLGetter != nil {
		arch := arch.HostArch()
		imageURL, err := imageURLGetter.ImageURL(instance.LXC, series, arch)
		if err != nil {
			return nil, errors.Annotatef(err, "cannot determine cached image URL")
		}
		templateParams = append(templateParams, "-T", imageURL)
		caCert = imageURLGetter.CACert()
	}
	var extraCreateArgs []string
	if backingFilesystem == Btrfs {
		extraCreateArgs = append(extraCreateArgs, "-B", Btrfs)
	}

	// Create the container.
	logger.Tracef("create the template container")
	err = createContainer(
		lxcContainer,
		containerDirectory,
		networkConfig,
		extraCreateArgs,
		templateParams,
		caCert,
	)
	if err != nil {
		logger.Errorf("lxc template container creation failed: %v", err)
		return nil, err
	}
	// Make sure that the mount dir has been created.
	logger.Tracef("make the mount dir for the shared logs")
	if err := os.MkdirAll(internalLogDir(name), 0755); err != nil {
		logger.Tracef("failed to create internal /var/log/juju mount dir: %v", err)
		return nil, err
	}

	// Start the lxc container with the appropriate settings for grabbing the
	// console output and a log file.
	consoleFile := filepath.Join(containerDirectory, "console.log")
	lxcContainer.SetLogFile(filepath.Join(containerDirectory, "container.log"), golxc.LogDebug)
	logger.Tracef("start the container")
	// We explicitly don't pass through the config file to the container.Start
	// method as we have passed it through at container creation time.  This
	// is necessary to get the appropriate rootfs reference without explicitly
	// setting it ourselves.
	if err = lxcContainer.Start("", consoleFile); err != nil {
		logger.Errorf("container failed to start: %v", err)
		return nil, err
	}
	logger.Infof("template container started, now wait for it to stop")
	// Perhaps we should wait for it to finish, and the question becomes "how
	// long do we wait for it to complete?"

	console, err := os.Open(consoleFile)
	if err != nil {
		// can't listen
		return nil, err
	}

	tailWriter := &logTail{tick: time.Now()}
	consoleTailer := tailer.NewTailer(console, tailWriter, nil)
	defer consoleTailer.Stop()

	// We should wait maybe 1 minute between output?
	// if no output check to see if stopped
	// If we have no output and still running, something has probably gone wrong
	for lxcContainer.IsRunning() {
		if tailWriter.lastTick().Before(time.Now().Add(-TemplateStopTimeout)) {
			logger.Infof("not heard anything from the template log for five minutes")
			return nil, fmt.Errorf("template container %q did not stop", name)
		}
		time.Sleep(time.Second)
	}

	return lxcContainer, nil
}

type logTail struct {
	tick  time.Time
	mutex sync.Mutex
}

var _ io.Writer = (*logTail)(nil)

func (t *logTail) Write(data []byte) (int, error) {
	logger.Tracef(string(data))
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.tick = time.Now()
	return len(data), nil
}

func (t *logTail) lastTick() time.Time {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	tick := t.tick
	return tick
}
<commit_msg>Derive the init system from the series.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package lxc

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/juju/errors"
	"github.com/juju/utils/proxy"
	"github.com/juju/utils/tailer"
	"launchpad.net/golxc"

	corecloudinit "github.com/juju/juju/cloudinit"
	"github.com/juju/juju/container"
	"github.com/juju/juju/environs/cloudinit"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/juju/arch"
	"github.com/juju/juju/service"
	"github.com/juju/juju/version"
)

var (
	TemplateLockDir = "/var/lib/juju/locks"

	TemplateStopTimeout = 5 * time.Minute
)

// templateUserData returns a minimal user data necessary for the template.
// This should have the authorized keys, base packages, the cloud archive if
// necessary,  initial apt proxy config, and it should do the apt-get
// update/upgrade initially.
func templateUserData(
	series string,
	authorizedKeys string,
	aptProxy proxy.Settings,
	aptMirror string,
	enablePackageUpdates bool,
	enableOSUpgrades bool,
) ([]byte, error) {
	config := corecloudinit.New()
	config.AddScripts(
		"set -xe", // ensure we run all the scripts or abort.
	)
	// For LTS series which need support for the cloud-tools archive,
	// we need to enable apt-get update regardless of the environ
	// setting, otherwise provisioning will fail.
	if series == "precise" && !enablePackageUpdates {
		logger.Warningf("series %q requires cloud-tools archive: enabling updates", series)
		enablePackageUpdates = true
	}

	config.AddSSHAuthorizedKeys(authorizedKeys)
	if enablePackageUpdates {
		cloudinit.MaybeAddCloudArchiveCloudTools(config, series)
	}
	cloudinit.AddAptCommands(series, aptProxy, aptMirror, config, enablePackageUpdates, enableOSUpgrades)

	initSystem, err := containerInitSystem(series)
	if err != nil {
		return nil, errors.Trace(err)
	}
	script, err := shutdownInitScript(initSystem)
	if err != nil {
		return nil, errors.Trace(err)
	}
	config.AddScripts(script)

	renderer, err := corecloudinit.NewRenderer(series)
	if err != nil {
		return nil, err
	}
	data, err := renderer.Render(config)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func containerInitSystem(series string) (string, error) {
	osName, err := version.GetOSFromSeries(series)
	if err != nil {
		return "", errors.Trace(err)
	}
	vers := version.Binary{
		OS: osName,
	}
	initSystem, ok := service.VersionInitSystem(vers)
	if !ok {
		return "", errors.NotFoundf("init system for series %q", series)
	}
	return initSystem, nil
}

func shutdownInitScript(initSystem string) (string, error) {
	name := "juju-template-restart"
	conf, err := service.ShutdownAfterConf("cloud-final")
	if err != nil {
		return "", errors.Trace(err)
	}

	svc, err := service.NewService(name, conf, initSystem)
	if err != nil {
		return "", errors.Trace(err)
	}

	cmds, err := svc.InstallCommands()
	if err != nil {
		return "", errors.Trace(err)
	}

	return strings.Join(cmds, "\n"), nil
}

func AcquireTemplateLock(name, message string) (*container.Lock, error) {
	logger.Infof("wait for flock on %v", name)
	lock, err := container.NewLock(TemplateLockDir, name)
	if err != nil {
		logger.Tracef("failed to create flock for template: %v", err)
		return nil, err
	}
	err = lock.Lock(message)
	if err != nil {
		logger.Tracef("failed to acquire lock for template: %v", err)
		return nil, err
	}
	return lock, nil
}

// Make sure a template exists that we can clone from.
func EnsureCloneTemplate(
	backingFilesystem string,
	series string,
	networkConfig *container.NetworkConfig,
	authorizedKeys string,
	aptProxy proxy.Settings,
	aptMirror string,
	enablePackageUpdates bool,
	enableOSUpgrades bool,
	imageURLGetter container.ImageURLGetter,
) (golxc.Container, error) {
	name := fmt.Sprintf("juju-%s-lxc-template", series)
	containerDirectory, err := container.NewDirectory(name)
	if err != nil {
		return nil, err
	}

	lock, err := AcquireTemplateLock(name, "ensure clone exists")
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	lxcContainer := LxcObjectFactory.New(name)
	// Early exit if the container has been constructed before.
	if lxcContainer.IsConstructed() {
		logger.Infof("template exists, continuing")
		return lxcContainer, nil
	}
	logger.Infof("template does not exist, creating")

	userData, err := templateUserData(
		series,
		authorizedKeys,
		aptProxy,
		aptMirror,
		enablePackageUpdates,
		enableOSUpgrades,
	)
	if err != nil {
		logger.Tracef("failed to create template user data for template: %v", err)
		return nil, err
	}
	userDataFilename, err := container.WriteCloudInitFile(containerDirectory, userData)
	if err != nil {
		return nil, err
	}

	templateParams := []string{
		"--debug",                      // Debug errors in the cloud image
		"--userdata", userDataFilename, // Our groovey cloud-init
		"--hostid", name, // Use the container name as the hostid
		"-r", series,
	}
	var caCert []byte
	if imageURLGetter != nil {
		arch := arch.HostArch()
		imageURL, err := imageURLGetter.ImageURL(instance.LXC, series, arch)
		if err != nil {
			return nil, errors.Annotatef(err, "cannot determine cached image URL")
		}
		templateParams = append(templateParams, "-T", imageURL)
		caCert = imageURLGetter.CACert()
	}
	var extraCreateArgs []string
	if backingFilesystem == Btrfs {
		extraCreateArgs = append(extraCreateArgs, "-B", Btrfs)
	}

	// Create the container.
	logger.Tracef("create the template container")
	err = createContainer(
		lxcContainer,
		containerDirectory,
		networkConfig,
		extraCreateArgs,
		templateParams,
		caCert,
	)
	if err != nil {
		logger.Errorf("lxc template container creation failed: %v", err)
		return nil, err
	}
	// Make sure that the mount dir has been created.
	logger.Tracef("make the mount dir for the shared logs")
	if err := os.MkdirAll(internalLogDir(name), 0755); err != nil {
		logger.Tracef("failed to create internal /var/log/juju mount dir: %v", err)
		return nil, err
	}

	// Start the lxc container with the appropriate settings for grabbing the
	// console output and a log file.
	consoleFile := filepath.Join(containerDirectory, "console.log")
	lxcContainer.SetLogFile(filepath.Join(containerDirectory, "container.log"), golxc.LogDebug)
	logger.Tracef("start the container")
	// We explicitly don't pass through the config file to the container.Start
	// method as we have passed it through at container creation time.  This
	// is necessary to get the appropriate rootfs reference without explicitly
	// setting it ourselves.
	if err = lxcContainer.Start("", consoleFile); err != nil {
		logger.Errorf("container failed to start: %v", err)
		return nil, err
	}
	logger.Infof("template container started, now wait for it to stop")
	// Perhaps we should wait for it to finish, and the question becomes "how
	// long do we wait for it to complete?"

	console, err := os.Open(consoleFile)
	if err != nil {
		// can't listen
		return nil, err
	}

	tailWriter := &logTail{tick: time.Now()}
	consoleTailer := tailer.NewTailer(console, tailWriter, nil)
	defer consoleTailer.Stop()

	// We should wait maybe 1 minute between output?
	// if no output check to see if stopped
	// If we have no output and still running, something has probably gone wrong
	for lxcContainer.IsRunning() {
		if tailWriter.lastTick().Before(time.Now().Add(-TemplateStopTimeout)) {
			logger.Infof("not heard anything from the template log for five minutes")
			return nil, fmt.Errorf("template container %q did not stop", name)
		}
		time.Sleep(time.Second)
	}

	return lxcContainer, nil
}

type logTail struct {
	tick  time.Time
	mutex sync.Mutex
}

var _ io.Writer = (*logTail)(nil)

func (t *logTail) Write(data []byte) (int, error) {
	logger.Tracef(string(data))
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.tick = time.Now()
	return len(data), nil
}

func (t *logTail) lastTick() time.Time {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	tick := t.tick
	return tick
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	bzl "github.com/bazelbuild/buildifier/core"
	"github.com/golang/glog"
)

var kubeRoot = flag.String("root", "", "root of kubernetes source")
var dryRun = flag.Bool("dry-run", false, "run in dry mode")

func main() {
	flag.Parse()
	flag.Set("alsologtostderr", "true")
	if *kubeRoot == "" {
		glog.Fatalf("-root argument is required")
	}
	v := Venderor{
		ctx: &build.Default,
	}
	if len(flag.Args()) == 1 {
		v.updateSinglePkg(flag.Args()[0])
	} else {
		v.walkVendor()
		if err := v.walkRepo(); err != nil {
			glog.Fatalf("err: %v", err)
		}
	}
}

type Venderor struct {
	ctx *build.Context
}

func writeHeaders(file *bzl.File) {
	pkgRule := bzl.Rule{
		&bzl.CallExpr{
			X: &bzl.LiteralExpr{Token: "package"},
		},
	}
	pkgRule.SetAttr("default_visibility", asExpr([]string{"//visibility:public"}))

	file.Stmt = append(file.Stmt,
		[]bzl.Expr{
			pkgRule.Call,
			&bzl.CallExpr{
				X:    &bzl.LiteralExpr{Token: "licenses"},
				List: []bzl.Expr{asExpr([]string{"notice"})},
			},
			&bzl.CallExpr{
				X: &bzl.LiteralExpr{Token: "load"},
				List: asExpr([]string{
					"@io_bazel_rules_go//go:def.bzl",
					"go_binary",
					"go_library",
					"go_test",
					"cgo_library",
				}).(*bzl.ListExpr).List,
			},
		}...,
	)
}

func writeRules(file *bzl.File, rules []*bzl.Rule) {
	for _, rule := range rules {
		file.Stmt = append(file.Stmt, rule.Call)
	}
}

func (v *Venderor) resolve(ipath string) Label {
	if strings.HasPrefix(ipath, "k8s.io/kubernetes") {
		return Label{
			pkg: strings.TrimPrefix(ipath, "k8s.io/kubernetes/"),
			tag: "go_default_library",
		}
	}
	return Label{
		pkg: "vendor",
		tag: ipath,
	}
}

func (v *Venderor) walk(root string, f func(path, ipath string, pkg *build.Package) error) error {
	return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		ipath, err := filepath.Rel(root, path)
		if err != nil {
			return err
		}
		if !info.IsDir() {
			return nil
		}
		pkg, err := v.ctx.ImportDir(filepath.Join(*kubeRoot, path), build.ImportComment)
		if err != nil {
			if _, ok := err.(*build.NoGoError); err != nil && ok {
				return nil
			} else {
				return err
			}
		}

		return f(path, ipath, pkg)
	})
}

func (v *Venderor) walkRepo() error {
	for _, root := range []string{
		"./pkg",
		"./cmd",
		"./third_party",
		"./plugin",
		"./test",
		"./federation",
	} {
		if err := v.walk(root, v.updatePkg); err != nil {
			return err
		}
	}
	return nil
}

func (v *Venderor) updateSinglePkg(path string) error {
	pkg, err := v.ctx.ImportDir("./"+path, build.ImportComment)
	if err != nil {
		if _, ok := err.(*build.NoGoError); err != nil && ok {
			return nil
		} else {
			return err
		}
	}
	return v.updatePkg(path, "", pkg)
}

func (v *Venderor) updatePkg(path, _ string, pkg *build.Package) error {
	var rules []*bzl.Rule

	var attrs Attrs = make(Attrs)
	srcs := asExpr(merge(pkg.GoFiles, pkg.SFiles)).(*bzl.ListExpr)

	deps := v.extractDeps(pkg.Imports)

	if len(srcs.List) == 0 {
		return nil
	}
	attrs.Set("srcs", srcs)

	if len(deps.List) > 0 {
		attrs.Set("deps", deps)
	}

	if pkg.IsCommand() {
		rules = append(rules, newRule("go_binary", filepath.Base(pkg.Dir), attrs))
	} else {
		rules = append(rules, newRule("go_library", "go_default_library", attrs))
		if len(pkg.TestGoFiles) != 0 {
			rules = append(rules, newRule("go_test", "go_default_test", map[string]bzl.Expr{
				"srcs":    asExpr(pkg.TestGoFiles),
				"deps":    v.extractDeps(pkg.TestImports),
				"library": asExpr("go_default_library"),
			}))
		}
	}

	if len(pkg.XTestGoFiles) != 0 {
		rules = append(rules, newRule("go_test", "go_default_xtest", map[string]bzl.Expr{
			"srcs": asExpr(pkg.XTestGoFiles),
			"deps": v.extractDeps(pkg.XTestImports),
		}))
	}

	wrote, err := ReconcileRules(filepath.Join(path, "BUILD"), rules)
	if err != nil {
		return err
	}
	if wrote {
		fmt.Fprintf(os.Stderr, "wrote BUILD for %q\n", pkg.Dir)
	}
	return nil
}

func (v *Venderor) walkVendor() {
	var rules []*bzl.Rule
	if err := v.walk("./vendor", func(path, ipath string, pkg *build.Package) error {
		var attrs Attrs = make(Attrs)

		srcs := asExpr(
			apply(
				merge(pkg.GoFiles, pkg.SFiles),
				mapper(func(s string) string {
					return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
				}),
			),
		).(*bzl.ListExpr)

		cgoSrcs := asExpr(
			apply(
				merge(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles),
				mapper(func(s string) string {
					return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
				}),
			),
		).(*bzl.ListExpr)

		deps := v.extractDeps(pkg.Imports)
		attrs.Set("srcs", srcs)

		if len(deps.List) > 0 {
			attrs.Set("deps", deps)
		}

		if pkg.IsCommand() {
			rules = append(rules, newRule("go_binary", v.resolve(ipath).tag, attrs))
		} else {
			if len(cgoSrcs.List) != 0 {
				cgoPname := v.resolve(ipath).tag + "_cgo"
				cgoDeps := v.extractDeps(pkg.TestImports)
				cgoRule := newRule("cgo_library", cgoPname, map[string]bzl.Expr{
					"srcs":      cgoSrcs,
					"clinkopts": asExpr([]string{"-ldl", "-lz", "-lm", "-lpthread", "-ldl"}),
				})
				rules = append(rules, cgoRule)
				if len(cgoDeps.List) != 0 {
					cgoRule.SetAttr("deps", cgoDeps)
				}
				attrs["library"] = asExpr(cgoPname)
			}
			rules = append(rules, newRule("go_library", v.resolve(ipath).tag, attrs))
		}
		return nil
	}); err != nil {
		glog.Fatalf("err: %v", err)
	}
	if _, err := ReconcileRules("./vendor/BUILD", rules); err != nil {
		glog.Fatalf("err: %v", err)
	}
}

func (v *Venderor) extractDeps(deps []string) *bzl.ListExpr {
	return asExpr(
		apply(
			merge(deps),
			filterer(func(s string) bool {
				pkg, err := v.ctx.Import(s, *kubeRoot, build.ImportComment)
				if err != nil {
					if !strings.Contains(err.Error(), `cannot find package "C"`) {
						fmt.Fprintf(os.Stderr, "extract err: %v\n", err)
					}
					return false
				}
				if pkg.Goroot {
					return false
				}
				return true
			}),
			mapper(func(s string) string {
				return v.resolve(s).String()
			}),
		),
	).(*bzl.ListExpr)
}

type Attrs map[string]bzl.Expr

func (a Attrs) Set(name string, expr bzl.Expr) {
	a[name] = expr
}

type Label struct {
	pkg, tag string
}

func (l Label) String() string {
	return fmt.Sprintf("//%v:%v", l.pkg, l.tag)
}

func asExpr(e interface{}) bzl.Expr {
	rv := reflect.ValueOf(e)
	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return &bzl.LiteralExpr{Token: fmt.Sprintf("%d", e)}
	case reflect.Float32, reflect.Float64:
		return &bzl.LiteralExpr{Token: fmt.Sprintf("%f", e)}
	case reflect.String:
		return &bzl.StringExpr{Value: e.(string)}
	case reflect.Slice, reflect.Array:
		var list []bzl.Expr
		for i := 0; i < rv.Len(); i++ {
			list = append(list, asExpr(rv.Index(i).Interface()))
		}
		return &bzl.ListExpr{List: list}
	default:
		glog.Fatalf("Uh oh")
		return nil
	}
}

type Sed func(s []string) []string

func mapString(in []string, f func(string) string) []string {
	var out []string
	for _, s := range in {
		out = append(out, f(s))
	}
	return out
}

func mapper(f func(string) string) Sed {
	return func(in []string) []string {
		return mapString(in, f)
	}
}

func filterString(in []string, f func(string) bool) []string {
	var out []string
	for _, s := range in {
		if f(s) {
			out = append(out, s)
		}
	}
	return out
}

func filterer(f func(string) bool) Sed {
	return func(in []string) []string {
		return filterString(in, f)
	}
}

func apply(stream []string, seds ...Sed) []string {
	for _, sed := range seds {
		stream = sed(stream)
	}
	return stream
}

func merge(streams ...[]string) []string {
	var out []string
	for _, stream := range streams {
		out = append(out, stream...)
	}
	return out
}

func newRule(kind, name string, attrs map[string]bzl.Expr) *bzl.Rule {
	rule := &bzl.Rule{
		Call: &bzl.CallExpr{
			X: &bzl.LiteralExpr{Token: kind},
		},
	}
	rule.SetAttr("name", asExpr(name))
	for k, v := range attrs {
		rule.SetAttr(k, v)
	}
	rule.SetAttr("tags", asExpr([]string{"automanaged"}))
	return rule
}

func ReconcileRules(path string, rules []*bzl.Rule) (bool, error) {
	info, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		f := &bzl.File{}
		writeHeaders(f)
		writeRules(f, rules)
		return writeFile(path, f, false)
	} else if err != nil {
		return false, err
	}
	if info.IsDir() {
		return false, fmt.Errorf("%q cannot be a directory", path)
	}
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return false, err
	}
	f, err := bzl.Parse(path, b)
	if err != nil {
		return false, err
	}
	oldRules := make(map[string]*bzl.Rule)
	for _, r := range f.Rules("") {
		oldRules[r.Name()] = r
	}
	for _, r := range rules {
		o, ok := oldRules[r.Name()]
		if !ok {
			f.Stmt = append(f.Stmt, r.Call)
			continue
		}
		if !RuleIsManaged(o) {
			continue
		}
		reconcileAttr := func(o, n *bzl.Rule, name string) {
			if e := n.Attr(name); e != nil {
				o.SetAttr(name, e)
			} else {
				o.DelAttr(name)
			}
		}
		reconcileAttr(o, r, "srcs")
		reconcileAttr(o, r, "deps")
		reconcileAttr(o, r, "library")
		delete(oldRules, r.Name())
	}
	for _, r := range oldRules {
		if !RuleIsManaged(r) {
			continue
		}
		f.DelRules(r.Kind(), r.Name())
	}
	return writeFile(path, f, true)
}

func RuleIsManaged(r *bzl.Rule) bool {
	var automanaged bool
	for _, tag := range r.AttrStrings("tags") {
		if tag == "automanaged" {
			automanaged = true
			break
		}
	}
	return automanaged
}

func writeFile(path string, f *bzl.File, exists bool) (bool, error) {
	var info bzl.RewriteInfo
	bzl.Rewrite(f, &info)
	out := bzl.Format(f)
	if exists {
		orig, err := ioutil.ReadFile(path)
		if err != nil {
			return false, err
		}
		if bytes.Compare(out, orig) == 0 {
			return false, nil
		}
	}
	if *dryRun {
		return true, nil
	}
	return true, ioutil.WriteFile(path, out, 0644)

}
<commit_msg>only support linux_amd64 for now<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"

	bzl "github.com/bazelbuild/buildifier/core"
	"github.com/golang/glog"
)

var kubeRoot = flag.String("root", "", "root of kubernetes source")
var dryRun = flag.Bool("dry-run", false, "run in dry mode")

func main() {
	flag.Parse()
	flag.Set("alsologtostderr", "true")
	if *kubeRoot == "" {
		glog.Fatalf("-root argument is required")
	}
	v := Venderor{
		ctx: context(),
	}
	if len(flag.Args()) == 1 {
		v.updateSinglePkg(flag.Args()[0])
	} else {
		v.walkVendor()
		if err := v.walkRepo(); err != nil {
			glog.Fatalf("err: %v", err)
		}
	}
}

type Venderor struct {
	ctx *build.Context
}

func writeHeaders(file *bzl.File) {
	pkgRule := bzl.Rule{
		&bzl.CallExpr{
			X: &bzl.LiteralExpr{Token: "package"},
		},
	}
	pkgRule.SetAttr("default_visibility", asExpr([]string{"//visibility:public"}))

	file.Stmt = append(file.Stmt,
		[]bzl.Expr{
			pkgRule.Call,
			&bzl.CallExpr{
				X:    &bzl.LiteralExpr{Token: "licenses"},
				List: []bzl.Expr{asExpr([]string{"notice"})},
			},
			&bzl.CallExpr{
				X: &bzl.LiteralExpr{Token: "load"},
				List: asExpr([]string{
					"@io_bazel_rules_go//go:def.bzl",
					"go_binary",
					"go_library",
					"go_test",
					"cgo_library",
				}).(*bzl.ListExpr).List,
			},
		}...,
	)
}

func writeRules(file *bzl.File, rules []*bzl.Rule) {
	for _, rule := range rules {
		file.Stmt = append(file.Stmt, rule.Call)
	}
}

func (v *Venderor) resolve(ipath string) Label {
	if strings.HasPrefix(ipath, "k8s.io/kubernetes") {
		return Label{
			pkg: strings.TrimPrefix(ipath, "k8s.io/kubernetes/"),
			tag: "go_default_library",
		}
	}
	return Label{
		pkg: "vendor",
		tag: ipath,
	}
}

func (v *Venderor) walk(root string, f func(path, ipath string, pkg *build.Package) error) error {
	return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		ipath, err := filepath.Rel(root, path)
		if err != nil {
			return err
		}
		if !info.IsDir() {
			return nil
		}
		pkg, err := v.ctx.ImportDir(filepath.Join(*kubeRoot, path), build.ImportComment)
		if err != nil {
			if _, ok := err.(*build.NoGoError); err != nil && ok {
				return nil
			} else {
				return err
			}
		}

		return f(path, ipath, pkg)
	})
}

func (v *Venderor) walkRepo() error {
	for _, root := range []string{
		"./pkg",
		"./cmd",
		"./third_party",
		"./plugin",
		"./test",
		"./federation",
	} {
		if err := v.walk(root, v.updatePkg); err != nil {
			return err
		}
	}
	return nil
}

func (v *Venderor) updateSinglePkg(path string) error {
	pkg, err := v.ctx.ImportDir("./"+path, build.ImportComment)
	if err != nil {
		if _, ok := err.(*build.NoGoError); err != nil && ok {
			return nil
		} else {
			return err
		}
	}
	return v.updatePkg(path, "", pkg)
}

func (v *Venderor) updatePkg(path, _ string, pkg *build.Package) error {
	var rules []*bzl.Rule

	var attrs Attrs = make(Attrs)
	srcs := asExpr(merge(pkg.GoFiles, pkg.SFiles)).(*bzl.ListExpr)

	deps := v.extractDeps(pkg.Imports)

	if len(srcs.List) == 0 {
		return nil
	}
	attrs.Set("srcs", srcs)

	if len(deps.List) > 0 {
		attrs.Set("deps", deps)
	}

	if pkg.IsCommand() {
		rules = append(rules, newRule("go_binary", filepath.Base(pkg.Dir), attrs))
	} else {
		rules = append(rules, newRule("go_library", "go_default_library", attrs))
		if len(pkg.TestGoFiles) != 0 {
			rules = append(rules, newRule("go_test", "go_default_test", map[string]bzl.Expr{
				"srcs":    asExpr(pkg.TestGoFiles),
				"deps":    v.extractDeps(pkg.TestImports),
				"library": asExpr("go_default_library"),
			}))
		}
	}

	if len(pkg.XTestGoFiles) != 0 {
		rules = append(rules, newRule("go_test", "go_default_xtest", map[string]bzl.Expr{
			"srcs": asExpr(pkg.XTestGoFiles),
			"deps": v.extractDeps(pkg.XTestImports),
		}))
	}

	wrote, err := ReconcileRules(filepath.Join(path, "BUILD"), rules)
	if err != nil {
		return err
	}
	if wrote {
		fmt.Fprintf(os.Stderr, "wrote BUILD for %q\n", pkg.Dir)
	}
	return nil
}

func (v *Venderor) walkVendor() {
	var rules []*bzl.Rule
	if err := v.walk("./vendor", func(path, ipath string, pkg *build.Package) error {
		var attrs Attrs = make(Attrs)

		srcs := asExpr(
			apply(
				merge(pkg.GoFiles, pkg.SFiles),
				mapper(func(s string) string {
					return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
				}),
			),
		).(*bzl.ListExpr)

		cgoSrcs := asExpr(
			apply(
				merge(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles),
				mapper(func(s string) string {
					return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
				}),
			),
		).(*bzl.ListExpr)

		deps := v.extractDeps(pkg.Imports)
		attrs.Set("srcs", srcs)

		if len(deps.List) > 0 {
			attrs.Set("deps", deps)
		}

		if pkg.IsCommand() {
			rules = append(rules, newRule("go_binary", v.resolve(ipath).tag, attrs))
		} else {
			if len(cgoSrcs.List) != 0 {
				cgoPname := v.resolve(ipath).tag + "_cgo"
				cgoDeps := v.extractDeps(pkg.TestImports)
				cgoRule := newRule("cgo_library", cgoPname, map[string]bzl.Expr{
					"srcs":      cgoSrcs,
					"clinkopts": asExpr([]string{"-ldl", "-lz", "-lm", "-lpthread", "-ldl"}),
				})
				rules = append(rules, cgoRule)
				if len(cgoDeps.List) != 0 {
					cgoRule.SetAttr("deps", cgoDeps)
				}
				attrs["library"] = asExpr(cgoPname)
			}
			rules = append(rules, newRule("go_library", v.resolve(ipath).tag, attrs))
		}
		return nil
	}); err != nil {
		glog.Fatalf("err: %v", err)
	}
	if _, err := ReconcileRules("./vendor/BUILD", rules); err != nil {
		glog.Fatalf("err: %v", err)
	}
}

func (v *Venderor) extractDeps(deps []string) *bzl.ListExpr {
	return asExpr(
		apply(
			merge(deps),
			filterer(func(s string) bool {
				pkg, err := v.ctx.Import(s, *kubeRoot, build.ImportComment)
				if err != nil {
					if !strings.Contains(err.Error(), `cannot find package "C"`) {
						fmt.Fprintf(os.Stderr, "extract err: %v\n", err)
					}
					return false
				}
				if pkg.Goroot {
					return false
				}
				return true
			}),
			mapper(func(s string) string {
				return v.resolve(s).String()
			}),
		),
	).(*bzl.ListExpr)
}

type Attrs map[string]bzl.Expr

func (a Attrs) Set(name string, expr bzl.Expr) {
	a[name] = expr
}

type Label struct {
	pkg, tag string
}

func (l Label) String() string {
	return fmt.Sprintf("//%v:%v", l.pkg, l.tag)
}

func asExpr(e interface{}) bzl.Expr {
	rv := reflect.ValueOf(e)
	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return &bzl.LiteralExpr{Token: fmt.Sprintf("%d", e)}
	case reflect.Float32, reflect.Float64:
		return &bzl.LiteralExpr{Token: fmt.Sprintf("%f", e)}
	case reflect.String:
		return &bzl.StringExpr{Value: e.(string)}
	case reflect.Slice, reflect.Array:
		var list []bzl.Expr
		for i := 0; i < rv.Len(); i++ {
			list = append(list, asExpr(rv.Index(i).Interface()))
		}
		return &bzl.ListExpr{List: list}
	default:
		glog.Fatalf("Uh oh")
		return nil
	}
}

type Sed func(s []string) []string

func mapString(in []string, f func(string) string) []string {
	var out []string
	for _, s := range in {
		out = append(out, f(s))
	}
	return out
}

func mapper(f func(string) string) Sed {
	return func(in []string) []string {
		return mapString(in, f)
	}
}

func filterString(in []string, f func(string) bool) []string {
	var out []string
	for _, s := range in {
		if f(s) {
			out = append(out, s)
		}
	}
	return out
}

func filterer(f func(string) bool) Sed {
	return func(in []string) []string {
		return filterString(in, f)
	}
}

func apply(stream []string, seds ...Sed) []string {
	for _, sed := range seds {
		stream = sed(stream)
	}
	return stream
}

func merge(streams ...[]string) []string {
	var out []string
	for _, stream := range streams {
		out = append(out, stream...)
	}
	return out
}

func newRule(kind, name string, attrs map[string]bzl.Expr) *bzl.Rule {
	rule := &bzl.Rule{
		Call: &bzl.CallExpr{
			X: &bzl.LiteralExpr{Token: kind},
		},
	}
	rule.SetAttr("name", asExpr(name))
	for k, v := range attrs {
		rule.SetAttr(k, v)
	}
	rule.SetAttr("tags", asExpr([]string{"automanaged"}))
	return rule
}

func ReconcileRules(path string, rules []*bzl.Rule) (bool, error) {
	info, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		f := &bzl.File{}
		writeHeaders(f)
		writeRules(f, rules)
		return writeFile(path, f, false)
	} else if err != nil {
		return false, err
	}
	if info.IsDir() {
		return false, fmt.Errorf("%q cannot be a directory", path)
	}
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return false, err
	}
	f, err := bzl.Parse(path, b)
	if err != nil {
		return false, err
	}
	oldRules := make(map[string]*bzl.Rule)
	for _, r := range f.Rules("") {
		oldRules[r.Name()] = r
	}
	for _, r := range rules {
		o, ok := oldRules[r.Name()]
		if !ok {
			f.Stmt = append(f.Stmt, r.Call)
			continue
		}
		if !RuleIsManaged(o) {
			continue
		}
		reconcileAttr := func(o, n *bzl.Rule, name string) {
			if e := n.Attr(name); e != nil {
				o.SetAttr(name, e)
			} else {
				o.DelAttr(name)
			}
		}
		reconcileAttr(o, r, "srcs")
		reconcileAttr(o, r, "deps")
		reconcileAttr(o, r, "library")
		delete(oldRules, r.Name())
	}
	for _, r := range oldRules {
		if !RuleIsManaged(r) {
			continue
		}
		f.DelRules(r.Kind(), r.Name())
	}
	return writeFile(path, f, true)
}

func RuleIsManaged(r *bzl.Rule) bool {
	var automanaged bool
	for _, tag := range r.AttrStrings("tags") {
		if tag == "automanaged" {
			automanaged = true
			break
		}
	}
	return automanaged
}

func writeFile(path string, f *bzl.File, exists bool) (bool, error) {
	var info bzl.RewriteInfo
	bzl.Rewrite(f, &info)
	out := bzl.Format(f)
	if exists {
		orig, err := ioutil.ReadFile(path)
		if err != nil {
			return false, err
		}
		if bytes.Compare(out, orig) == 0 {
			return false, nil
		}
	}
	if *dryRun {
		return true, nil
	}
	return true, ioutil.WriteFile(path, out, 0644)

}

func context() *build.Context {
	return &build.Context{
		GOARCH:      "amd64",
		GOOS:        "linux",
		GOROOT:      build.Default.GOROOT,
		GOPATH:      build.Default.GOPATH,
		ReleaseTags: []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7"},
		Compiler:    runtime.Compiler,
		CgoEnabled:  true,
	}
}
<|endoftext|>


<commit_before>
package main

import (
	"errors"
	"fmt"
	"strconv"
	"time"
	"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"encoding/json"
)

type RecruitmentChainCode struct {
}

type Demand struct{
	RRDNo string `json:"RRDNo"`
	Role string `json:"Role"`
	RoleDescription string `json:"RoleDescription"`
	YearsOfExperience string `json:"YearsOfExperience"`
	Location string `json:"Location"`
	Priority string `json:"Priority"`
	Status string `json:"Status"`
}

type Certification struct{
	Name []string `json:"Name"`
}

type JobDescription struct{
	Description []string `json:"Description"`
}

type MustHave struct{
	Skill []string `json:"Skill"`
}

type GoodToHave struct{
	Skill []string `json:"Skill"`
}

type SalaryRange struct{
	Min string `json:"Min"`
	Max string `json:"Max"`
	Currency string `json:"Currency"`

}

type Status struct{
	RRDNo string `json:"RRDNo"`
	Status string `json:"Status"`
}

func (self *RecruitmentChainCode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("In Init start ")
	fmt.Println("Nothing to be initialized ")
	return nil, nil
}

func (self *RecruitmentChainCode) Invoke(stub shim.ChaincodeStubInterface,
	function string, args []string) ([]byte, error) {
	fmt.Println("In Invoke with function  " + function)

	if function == "AddDemand" {
		fmt.Println("invoking AddDemand " + function)
		testBytes,err := AddDemand(args[0],stub)
		if err != nil {
			fmt.Println("Error performing AddDemand ")
			return nil, err
		}
		fmt.Println("Processed AddDemand successfully. ")
		return testBytes, nil
	}

	fmt.Println("invoke did not find func: " + function)
	return nil, errors.New("Received unknown function invocation: " + function)
}

func (self *RecruitmentChainCode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error){
	fmt.Println("In Query with function " + function)
	//bytes, err:= query.Query(stub, function,args)
	//if err != nil {
		//fmt.Println("Error retrieving function  ")
		//return nil, err
	//}

	bytes, err:= QueryDetails(stub, function,args)
	if err != nil {
		fmt.Println("Error retrieving function  ")
		return nil, err
	}
	return bytes,nil

}

func QueryDetails(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	if function == "GetDemand" {
		fmt.Println("Invoking GetDemand " + function)
		var demand Demand
		demand,err := GetDemand(args[0], stub)
		if err != nil {
			fmt.Println("Error retrieving  the Demand")
			return nil, errors.New("Error retrieving  Demand")
		}
		fmt.Println("All success, returning demand")
		return json.Marshal(demand)
	}
	return nil, errors.New("Received unknown query function name")

}

func GetDemand(RRDNo string, stub shim.ChaincodeStubInterface)(Demand, error) {
	fmt.Println("In query.GetDemand start ")

	key := RRDNo
	var demand Demand
	demandBytes, err := stub.GetState(key)
	if err != nil {
		fmt.Println("Error retrieving demand" , RRDNo)
		return users, errors.New("Error retrieving demand" + RRDNo)
	}
	err = json.Unmarshal(demandBytes, &demand)
	fmt.Println("Demand   : " , demand);
	fmt.Println("In query.GetDemand end ")
	return demand, nil
}

func GetStatus(RRDNo string, stub shim.ChaincodeStubInterface)(Balance, error) {
	fmt.Println("In query.GetStatus start ")
	key := RRDNo
	var status Status
	demand,err := GetDemand(key, stub)
	status.RRDNo = key
	status.Status = demand.Status
	fmt.Println("Demand Status   : " , status);
	fmt.Println("In query.GetStatus end ")
	return status, nil
}

func AddDemand(demandJSON string, stub shim.ChaincodeStubInterface) ([]byte, error) {
	fmt.Println("In services.AddUser start ")
	//smartMeterId :=args[0]
	//userType 	:=args[1]

	//var user User
	res := &Demand{}
	//user := &User{}
	err := json.Unmarshal([]byte(demandJSON), res)
	if err != nil {
		fmt.Println("Failed to unmarshal Demand ")
	}
	fmt.Println("RRD Number : ",res.RRDNo)
	fmt.Println(string(body))
	body, err := json.Marshal(res)
	if err != nil {
        panic(err)
    }
    fmt.Println(string(body))
	err = stub.PutState(res.RRDNo, []byte(string(body)))
	if err != nil {
		fmt.Println("Failed to create Demand ")
	}
	err = stub.PutState(res.RRDNo + "_" + res.Status, []byte(res.Status))
	if err != nil {
		fmt.Println("Failed to set RRD Status ")
	}
	fmt.Println("Created Demand  with Key : "+ res.RRDNo)
	fmt.Println("In initialize.AddDemand end ")
	return nil,nil
}

func StatusUpdate(demandStatusJSON string, stub shim.ChaincodeStubInterface) ([]byte, error) {
	fmt.Println("In services.StatusUpdate start ")

	res := &Status{}
	err := json.Unmarshal([]byte(demandStatusJSON), res)
	if err != nil {
		fmt.Println("Failed to unmarshal Status ")
	}
	fmt.Println("Status of Demand   : ",res.Status)

	demandDet,err := GetDemand(res.RRDNo, stub)
	demandDet.Status = res.Status

	demandStatusUpdate, err := json.Marshal(demandDet)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(demandStatusUpdate))
	err = stub.PutState(res.RRDNo, []byte(string(demandStatusUpdate)))
	if err != nil {
		fmt.Println("Failed to update Demand Status ")
	}
	fmt.Println("Updated Demand Status  with Key : "+ res.RRDNo)
	fmt.Println("In initialize.StatusUpdate end ")
	return nil,nil
}

func main() {
	err := shim.Start(new(RecruitmentChainCode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}

}
<commit_msg>updated chaincode<commit_after>
package main

import (
	"errors"
	"fmt"
	//"strconv"
	//"time"
	//"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"encoding/json"
)

type RecruitmentChainCode struct {
}

type Demand struct{
	RRDNo string `json:"RRDNo"`
	Role string `json:"Role"`
	RoleDescription string `json:"RoleDescription"`
	YearsOfExperience string `json:"YearsOfExperience"`
	Location string `json:"Location"`
	Priority string `json:"Priority"`
	Status string `json:"Status"`
}

type Certification struct{
	Name []string `json:"Name"`
}

type JobDescription struct{
	Description []string `json:"Description"`
}

type MustHave struct{
	Skill []string `json:"Skill"`
}

type GoodToHave struct{
	Skill []string `json:"Skill"`
}

type SalaryRange struct{
	Min string `json:"Min"`
	Max string `json:"Max"`
	Currency string `json:"Currency"`

}

type Status struct{
	RRDNo string `json:"RRDNo"`
	Status string `json:"Status"`
}

func (self *RecruitmentChainCode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("In Init start ")
	fmt.Println("Nothing to be initialized ")
	return nil, nil
}

func (self *RecruitmentChainCode) Invoke(stub shim.ChaincodeStubInterface,
	function string, args []string) ([]byte, error) {
	fmt.Println("In Invoke with function  " + function)

	if function == "AddDemand" {
		fmt.Println("invoking AddDemand " + function)
		testBytes,err := AddDemand(args[0],stub)
		if err != nil {
			fmt.Println("Error performing AddDemand ")
			return nil, err
		}
		fmt.Println("Processed AddDemand successfully. ")
		return testBytes, nil
	}

	fmt.Println("invoke did not find func: " + function)
	return nil, errors.New("Received unknown function invocation: " + function)
}

func (self *RecruitmentChainCode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error){
	fmt.Println("In Query with function " + function)
	//bytes, err:= query.Query(stub, function,args)
	//if err != nil {
		//fmt.Println("Error retrieving function  ")
		//return nil, err
	//}

	bytes, err:= QueryDetails(stub, function,args)
	if err != nil {
		fmt.Println("Error retrieving function  ")
		return nil, err
	}
	return bytes,nil

}

func QueryDetails(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	if function == "GetDemand" {
		fmt.Println("Invoking GetDemand " + function)
		var demand Demand
		demand,err := GetDemand(args[0], stub)
		if err != nil {
			fmt.Println("Error retrieving  the Demand")
			return nil, errors.New("Error retrieving  Demand")
		}
		fmt.Println("All success, returning demand")
		return json.Marshal(demand)
	}
	return nil, errors.New("Received unknown query function name")

}

func GetDemand(RRDNo string, stub shim.ChaincodeStubInterface)(Demand, error) {
	fmt.Println("In query.GetDemand start ")

	key := RRDNo
	var demand Demand
	demandBytes, err := stub.GetState(key)
	if err != nil {
		fmt.Println("Error retrieving demand" , RRDNo)
		return demand, errors.New("Error retrieving demand" + RRDNo)
	}
	err = json.Unmarshal(demandBytes, &demand)
	fmt.Println("Demand   : " , demand);
	fmt.Println("In query.GetDemand end ")
	return demand, nil
}

func GetStatus(RRDNo string, stub shim.ChaincodeStubInterface)(Status, error) {
	fmt.Println("In query.GetStatus start ")
	key := RRDNo
	var status Status
	demand,err := GetDemand(key, stub)
	status.RRDNo = key
	status.Status = demand.Status
	fmt.Println("Demand Status   : " , status);
	fmt.Println("In query.GetStatus end ")
	return status, nil
}

func AddDemand(demandJSON string, stub shim.ChaincodeStubInterface) ([]byte, error) {
	fmt.Println("In services.AddUser start ")
	//smartMeterId :=args[0]
	//userType 	:=args[1]

	//var user User
	res := &Demand{}
	//user := &User{}
	err := json.Unmarshal([]byte(demandJSON), res)
	if err != nil {
		fmt.Println("Failed to unmarshal Demand ")
	}
	fmt.Println("RRD Number : ",res.RRDNo)

	body, err := json.Marshal(res)
	if err != nil {
        panic(err)
    }

	fmt.Println(string(body))
	body, err := json.Marshal(res)
	if err != nil {
        panic(err)
    }
    fmt.Println(string(body))
	err = stub.PutState(res.RRDNo, []byte(string(body)))
	if err != nil {
		fmt.Println("Failed to create Demand ")
	}
	err = stub.PutState(res.RRDNo + "_" + res.Status, []byte(res.Status))
	if err != nil {
		fmt.Println("Failed to set RRD Status ")
	}
	fmt.Println("Created Demand  with Key : "+ res.RRDNo)
	fmt.Println("In initialize.AddDemand end ")
	return nil,nil
}

func StatusUpdate(demandStatusJSON string, stub shim.ChaincodeStubInterface) ([]byte, error) {
	fmt.Println("In services.StatusUpdate start ")

	res := &Status{}
	err := json.Unmarshal([]byte(demandStatusJSON), res)
	if err != nil {
		fmt.Println("Failed to unmarshal Status ")
	}
	fmt.Println("Status of Demand   : ",res.Status)

	demandDet,err := GetDemand(res.RRDNo, stub)
	demandDet.Status = res.Status

	demandStatusUpdate, err := json.Marshal(demandDet)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(demandStatusUpdate))
	err = stub.PutState(res.RRDNo, []byte(string(demandStatusUpdate)))
	if err != nil {
		fmt.Println("Failed to update Demand Status ")
	}
	fmt.Println("Updated Demand Status  with Key : "+ res.RRDNo)
	fmt.Println("In initialize.StatusUpdate end ")
	return nil,nil
}

func main() {
	err := shim.Start(new(RecruitmentChainCode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}

}
<|endoftext|>


<commit_before>package api

import (
	//	"gopkg.in/mgo.v2"
	"appengine/aetest"
	"appengine/datastore"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/ErikBjare/Futarchio/src/db"
	"io/ioutil"
	"log"
	"net/http"
	"testing"
	"time"
)

func init() {
	_, err := http.Get("http://localhost:8080/api/0/init")
	if err != nil {
		log.Fatal(err)
	}

	// Required to let datastore init
	time.Sleep(time.Second)
}

func getAuthkey() (string, error) {
	client := &http.Client{}
	bodybuf := &bytes.Buffer{}
	bodybuf.Write([]byte("{\"username\": \"erb\", \"password\": \"password\"}"))
	resp, err := client.Post("http://localhost:8080/api/0/auth", "application/json", bodybuf)
	if err != nil {
		return "", err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	msg := db.Auth{}
	err = json.Unmarshal(body, &msg)
	if err != nil {
		return "", err
	}

	return msg.Key, nil
}

type UserWithKey struct {
	db.User
	Key *datastore.Key `json:"key"`
}

func TestAuth(t *testing.T) {
	authkey, err := getAuthkey()
	if err != nil {
		t.Fatal(err)
	}

	// Apparently required to allow the datastore time to be able to store Auth
	// TODO: Should probably be removed once Memcache is implemented
	time.Sleep(time.Second)

	body, err := getBody("http://localhost:8080/api/0/users", authkey)
	if err != nil {
		t.Fatal(err)
	}

	var users []db.User
	err = json.Unmarshal(body, &users)
	if err != nil {
		t.Error(err)
	}

	body, err = getBody("http://localhost:8080/api/0/users/me", authkey)
	if err != nil {
		t.Fatal(err)
	}

	var user UserWithKey
	err = json.Unmarshal(body, &user)
	if err != nil {
		t.Error(err)
	}

	body, err = getBody("http://localhost:8080/api/0/users/"+user.Key.Encode(), authkey)
	if err != nil {
		t.Fatal(err)
	}

	var user2 db.User
	err = json.Unmarshal(body, &user2)
	if err != nil {
		t.Error(err)
	}

	if user.Username != user2.Username {
		t.Error("usernames did not match")
	}
}

func getBody(url string, authkey string) ([]byte, error) {
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	if authkey != "" {
		req.Header.Add("Authorization", authkey)
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		err := errors.New(fmt.Sprintf("Status code was not 200, was %d with message: %s", resp.StatusCode, resp.Status))
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, err
}

func TestUsers(t *testing.T) {
	c, err := aetest.NewContext(nil)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	key := datastore.NewKey(c, "User", "erb", 0, nil)
	user1 := db.NewUser("erb", "secretpassword", "Erik", "erik@bjareho.lt")
	_, err = datastore.Put(c, key, &user1)
	if err != nil {
		t.Fatal(err)
	}

	var user2 db.User
	err = datastore.Get(c, key, &user2)
	if err != nil {
		t.Error(err)
	}

	var users []db.User
	q := datastore.NewQuery("User").Filter("Email =", "erik@bjareho.lt")
	keys, err := q.GetAll(c, &users)
	if err != nil {
		t.Error(err)
	}

	if len(keys) == 0 {
		t.Error("Couldn't find Erik in database")
	} else if len(keys) > 1 {
		t.Error("More than one user with email erik@bjareho.lt in database")
	}
}

func TestPolls(t *testing.T) {
	_, err := getBody("http://localhost:8080/api/0/polls", "")
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>Fixed users test<commit_after>package api

import (
	//	"gopkg.in/mgo.v2"
	"appengine/aetest"
	"appengine/datastore"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/ErikBjare/Futarchio/src/db"
	"io/ioutil"
	"log"
	"net/http"
	"testing"
	"time"
)

func init() {
	_, err := http.Get("http://localhost:8080/api/0/init")
	if err != nil {
		log.Fatal(err)
	}

	// Required to let datastore init
	time.Sleep(time.Second)
}

func getAuthkey() (string, error) {
	client := &http.Client{}
	bodybuf := &bytes.Buffer{}
	bodybuf.Write([]byte("{\"username\": \"erb\", \"password\": \"password\"}"))
	resp, err := client.Post("http://localhost:8080/api/0/auth", "application/json", bodybuf)
	if err != nil {
		return "", err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	msg := db.Auth{}
	err = json.Unmarshal(body, &msg)
	if err != nil {
		return "", err
	}

	return msg.Key, nil
}

type UserWithKey struct {
	db.User
	Key *datastore.Key `json:"key"`
}

func TestAuth(t *testing.T) {
	authkey, err := getAuthkey()
	if err != nil {
		t.Fatal(err)
	}

	// Apparently required to allow the datastore time to be able to store Auth
	// TODO: Should probably be removed once Memcache is implemented
	time.Sleep(time.Second)

	body, err := getBody("http://localhost:8080/api/0/users/me", authkey)
	if err != nil {
		t.Fatal(err)
	}

	var user UserWithKey
	err = json.Unmarshal(body, &user)
	if err != nil {
		t.Error(err)
	}

	body, err = getBody("http://localhost:8080/api/0/users?key="+user.Key.Encode(), authkey)
	if err != nil {
		t.Fatal(err)
	}

	var users []UserResponse
	err = json.Unmarshal(body, &users)
	if err != nil {
		t.Error(err)
	}

	if user.Username != users[0].Username {
		t.Error("usernames did not match")
	}
}

func getBody(url string, authkey string) ([]byte, error) {
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	if authkey != "" {
		req.Header.Add("Authorization", authkey)
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		err := errors.New(fmt.Sprintf("Status code was not 200, was %d with message: %s", resp.StatusCode, resp.Status))
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, err
}

func TestUsers(t *testing.T) {
	c, err := aetest.NewContext(nil)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	key := datastore.NewKey(c, "User", "erb", 0, nil)
	user1 := db.NewUser("erb", "secretpassword", "Erik", "erik@bjareho.lt")
	_, err = datastore.Put(c, key, &user1)
	if err != nil {
		t.Fatal(err)
	}

	var user2 db.User
	err = datastore.Get(c, key, &user2)
	if err != nil {
		t.Error(err)
	}

	var users []db.User
	q := datastore.NewQuery("User").Filter("Email =", "erik@bjareho.lt")
	keys, err := q.GetAll(c, &users)
	if err != nil {
		t.Error(err)
	}

	if len(keys) == 0 {
		t.Error("Couldn't find Erik in database")
	} else if len(keys) > 1 {
		t.Error("More than one user with email erik@bjareho.lt in database")
	}
}

func TestPolls(t *testing.T) {
	_, err := getBody("http://localhost:8080/api/0/polls", "")
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>/* Go (cgo) interface to libgeoip */
package geoip

/*
#cgo CFLAGS: -I/opt/local/include -I/usr/local/include
#cgo LDFLAGS: -lGeoIP -L/opt/local/lib -L/usr/local/lib
#include <stdio.h>
#include <errno.h>
#include <GeoIP.h>

//typedef GeoIP* GeoIP_pnt
*/
import "C"

import (
	"log"
	"os"
	"unsafe"
)

// Set Quiet to true to silence warnings when the database can't be opened
// (though libgeoip still prints to errout)
var Quiet bool = false

type GeoIP struct {
	db *C.GeoIP
}

// Open opens a GeoIP database, all formats supported by libgeoip are supported though
// there are only functions to access the country information in this API.
// The database is opened in MEMORY_CACHE mode, if you need to optimize for memory
// instead of performance you should change this.
// If you don't pass a filename, it will try opening the database from
// a list of common paths.
func Open(files ...string) *GeoIP {
	if len(files) == 0 {
		files = []string{
			"/usr/share/GeoIP/GeoIP.dat",       // Linux default
			"/usr/share/local/GeoIP/GeoIP.dat", // source install?
			"/usr/local/share/GeoIP/GeoIP.dat", // FreeBSD
			"/opt/local/share/GeoIP/GeoIP.dat", // MacPorts
		}
	}

	g := &GeoIP{}

	var err error

	for _, file := range files {

		// libgeoip prints errors if it can't open the file, so check first
		if _, err := os.Stat(file); err != nil {
			if os.IsExist(err) {
				log.Println(err)
			}
			continue
		}

		cbase := C.CString(file)
		g.db, err = C.GeoIP_open(cbase, C.GEOIP_MEMORY_CACHE)
		C.free(unsafe.Pointer(cbase))
		if g.db != nil && err != nil {
			break
		}
	}
	if err != nil && !Quiet {
		log.Println("Error opening GeoIP database", files, err)
	}

	if g.db != nil {
		C.GeoIP_set_charset(g.db, C.GEOIP_CHARSET_UTF8)
		return g
	}

	return nil
}

func (gi *GeoIP) GetOrg(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	cname := C.GeoIP_name_by_addr(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if cname != nil {
		rets := C.GoString(cname)
		return rets
	}
	return ""
}

// GetCountry takes an IPv4 address string and returns the country code for that IP.
func (gi *GeoIP) GetCountry(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	ccountry := C.GeoIP_country_code_by_addr(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if ccountry != nil {
		rets := C.GoString(ccountry)
		return rets
	}
	return ""
}

// GetCountry_v6 works the same as GetCountry except for IPv6 addresses, be sure to
// load a database with IPv6 data to get any results.
func (gi *GeoIP) GetCountry_v6(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	ccountry := C.GeoIP_country_code_by_addr_v6(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if ccountry != nil {
		rets := C.GoString(ccountry)
		return rets
	}
	return ""
}
<commit_msg>doc getorg<commit_after>/* Go (cgo) interface to libgeoip */
package geoip

/*
#cgo CFLAGS: -I/opt/local/include -I/usr/local/include
#cgo LDFLAGS: -lGeoIP -L/opt/local/lib -L/usr/local/lib
#include <stdio.h>
#include <errno.h>
#include <GeoIP.h>

//typedef GeoIP* GeoIP_pnt
*/
import "C"

import (
	"log"
	"os"
	"unsafe"
)

// Set Quiet to true to silence warnings when the database can't be opened
// (though libgeoip still prints to errout)
var Quiet bool = false

type GeoIP struct {
	db *C.GeoIP
}

// Open opens a GeoIP database, all formats supported by libgeoip are supported though
// there are only functions to access the country information in this API.
// The database is opened in MEMORY_CACHE mode, if you need to optimize for memory
// instead of performance you should change this.
// If you don't pass a filename, it will try opening the database from
// a list of common paths.
func Open(files ...string) *GeoIP {
	if len(files) == 0 {
		files = []string{
			"/usr/share/GeoIP/GeoIP.dat",       // Linux default
			"/usr/share/local/GeoIP/GeoIP.dat", // source install?
			"/usr/local/share/GeoIP/GeoIP.dat", // FreeBSD
			"/opt/local/share/GeoIP/GeoIP.dat", // MacPorts
		}
	}

	g := &GeoIP{}

	var err error

	for _, file := range files {

		// libgeoip prints errors if it can't open the file, so check first
		if _, err := os.Stat(file); err != nil {
			if os.IsExist(err) {
				log.Println(err)
			}
			continue
		}

		cbase := C.CString(file)
		g.db, err = C.GeoIP_open(cbase, C.GEOIP_MEMORY_CACHE)
		C.free(unsafe.Pointer(cbase))
		if g.db != nil && err != nil {
			break
		}
	}
	if err != nil && !Quiet {
		log.Println("Error opening GeoIP database", files, err)
	}

	if g.db != nil {
		C.GeoIP_set_charset(g.db, C.GEOIP_CHARSET_UTF8)
		return g
	}

	return nil
}

// GetOrg takes an IPv4 address string and returns the org name for that IP.
// Requires the geoip org database
func (gi *GeoIP) GetOrg(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	cname := C.GeoIP_name_by_addr(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if cname != nil {
		rets := C.GoString(cname)
		return rets
	}
	return ""
}

// GetCountry takes an IPv4 address string and returns the country code for that IP.
func (gi *GeoIP) GetCountry(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	ccountry := C.GeoIP_country_code_by_addr(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if ccountry != nil {
		rets := C.GoString(ccountry)
		return rets
	}
	return ""
}

// GetCountry_v6 works the same as GetCountry except for IPv6 addresses, be sure to
// load a database with IPv6 data to get any results.
func (gi *GeoIP) GetCountry_v6(ip string) string {
	if gi.db == nil {
		return ""
	}
	cip := C.CString(ip)
	ccountry := C.GeoIP_country_code_by_addr_v6(gi.db, cip)
	C.free(unsafe.Pointer(cip))
	if ccountry != nil {
		rets := C.GoString(ccountry)
		return rets
	}
	return ""
}
<|endoftext|>


<commit_before><commit_msg>fix(controller): avoid returning a body with a status code 304 for the space show operation (#1527)<commit_after><|endoftext|>


<commit_before>package acceptance

import (
	"log"
	"os"

	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-cf/go-pivnet"
	"github.com/pivotal-cf/go-pivnet/logshim"
	"github.com/pivotal-cf/pivnet-resource/gp"
	"github.com/robdimsdale/sanitizer"

	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var (
	inPath    string
	checkPath string
	outPath   string

	endpoint string

	productSlug        string
	pivnetAPIToken     string
	awsAccessKeyID     string
	awsSecretAccessKey string
	pivnetRegion       string
	pivnetBucketName   string
	s3FilepathPrefix   string

	pivnetClient *gp.Client
)

func TestAcceptance(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Acceptance Suite")
}

var _ = BeforeSuite(func() {
	var err error
	By("Getting product slug from environment variables")
	productSlug = os.Getenv("PRODUCT_SLUG")
	Expect(productSlug).NotTo(BeEmpty(), "$PRODUCT_SLUG must be provided")

	By("Getting API token from environment variables")
	pivnetAPIToken = os.Getenv("API_TOKEN")
	Expect(pivnetAPIToken).NotTo(BeEmpty(), "$API_TOKEN must be provided")

	By("Getting aws access key id from environment variables")
	awsAccessKeyID = os.Getenv("AWS_ACCESS_KEY_ID")
	Expect(awsAccessKeyID).NotTo(BeEmpty(), "$AWS_ACCESS_KEY_ID must be provided")

	By("Getting aws secret access key from environment variables")
	awsSecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
	Expect(awsSecretAccessKey).NotTo(BeEmpty(), "$AWS_SECRET_ACCESS_KEY must be provided")

	By("Getting pivnet region from environment variables")
	pivnetRegion = os.Getenv("PIVNET_S3_REGION")
	Expect(pivnetRegion).NotTo(BeEmpty(), "$PIVNET_S3_REGION must be provided")

	By("Getting pivnet bucket name from environment variables")
	pivnetBucketName = os.Getenv("PIVNET_BUCKET_NAME")
	Expect(pivnetBucketName).NotTo(BeEmpty(), "$PIVNET_BUCKET_NAME must be provided")

	By("Getting s3 filepath prefix from environment variables")
	s3FilepathPrefix = os.Getenv("S3_FILEPATH_PREFIX")
	Expect(s3FilepathPrefix).NotTo(BeEmpty(), "$S3_FILEPATH_PREFIX must be provided")

	By("Getting endpoint from environment variables")
	endpoint = os.Getenv("PIVNET_ENDPOINT")
	Expect(endpoint).NotTo(BeEmpty(), "$PIVNET_ENDPOINT must be provided")

	By("Compiling check binary")
	checkPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/check", "-race")
	Expect(err).NotTo(HaveOccurred())

	By("Compiling out binary")
	outPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/out", "-race")
	Expect(err).NotTo(HaveOccurred())

	By("Compiling in binary")
	inPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/in")
	Expect(err).NotTo(HaveOccurred())

	By("Sanitizing acceptance test output")
	sanitized := map[string]string{
		pivnetAPIToken:     "***sanitized-api-token***",
		awsAccessKeyID:     "***sanitized-aws-access-key-id***",
		awsSecretAccessKey: "***sanitized-aws-secret-access-key***",
	}
	sanitizedWriter := sanitizer.NewSanitizer(sanitized, GinkgoWriter)
	GinkgoWriter = sanitizedWriter

	By("Creating pivnet client (for out-of-band operations)")

	testLogger := log.New(sanitizedWriter, "", log.LstdFlags)
	verbose := true
	ls := logshim.NewLogShim(testLogger, testLogger, verbose)

	clientConfig := pivnet.ClientConfig{
		Host:      endpoint,
		Token:     pivnetAPIToken,
		UserAgent: "pivnet-resource/integration-test",
	}

	pivnetClient = gp.NewClient(clientConfig, ls)
})

var _ = AfterSuite(func() {
	gexec.CleanupBuildArtifacts()
})
<commit_msg>Re-introduce race detection into in acceptance test.<commit_after>package acceptance

import (
	"log"
	"os"

	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-cf/go-pivnet"
	"github.com/pivotal-cf/go-pivnet/logshim"
	"github.com/pivotal-cf/pivnet-resource/gp"
	"github.com/robdimsdale/sanitizer"

	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var (
	inPath    string
	checkPath string
	outPath   string

	endpoint string

	productSlug        string
	pivnetAPIToken     string
	awsAccessKeyID     string
	awsSecretAccessKey string
	pivnetRegion       string
	pivnetBucketName   string
	s3FilepathPrefix   string

	pivnetClient *gp.Client
)

func TestAcceptance(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Acceptance Suite")
}

var _ = BeforeSuite(func() {
	var err error
	By("Getting product slug from environment variables")
	productSlug = os.Getenv("PRODUCT_SLUG")
	Expect(productSlug).NotTo(BeEmpty(), "$PRODUCT_SLUG must be provided")

	By("Getting API token from environment variables")
	pivnetAPIToken = os.Getenv("API_TOKEN")
	Expect(pivnetAPIToken).NotTo(BeEmpty(), "$API_TOKEN must be provided")

	By("Getting aws access key id from environment variables")
	awsAccessKeyID = os.Getenv("AWS_ACCESS_KEY_ID")
	Expect(awsAccessKeyID).NotTo(BeEmpty(), "$AWS_ACCESS_KEY_ID must be provided")

	By("Getting aws secret access key from environment variables")
	awsSecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
	Expect(awsSecretAccessKey).NotTo(BeEmpty(), "$AWS_SECRET_ACCESS_KEY must be provided")

	By("Getting pivnet region from environment variables")
	pivnetRegion = os.Getenv("PIVNET_S3_REGION")
	Expect(pivnetRegion).NotTo(BeEmpty(), "$PIVNET_S3_REGION must be provided")

	By("Getting pivnet bucket name from environment variables")
	pivnetBucketName = os.Getenv("PIVNET_BUCKET_NAME")
	Expect(pivnetBucketName).NotTo(BeEmpty(), "$PIVNET_BUCKET_NAME must be provided")

	By("Getting s3 filepath prefix from environment variables")
	s3FilepathPrefix = os.Getenv("S3_FILEPATH_PREFIX")
	Expect(s3FilepathPrefix).NotTo(BeEmpty(), "$S3_FILEPATH_PREFIX must be provided")

	By("Getting endpoint from environment variables")
	endpoint = os.Getenv("PIVNET_ENDPOINT")
	Expect(endpoint).NotTo(BeEmpty(), "$PIVNET_ENDPOINT must be provided")

	By("Compiling check binary")
	checkPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/check", "-race")
	Expect(err).NotTo(HaveOccurred())

	By("Compiling out binary")
	outPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/out", "-race")
	Expect(err).NotTo(HaveOccurred())

	By("Compiling in binary")
	inPath, err = gexec.Build("github.com/pivotal-cf/pivnet-resource/cmd/in", "-race")
	Expect(err).NotTo(HaveOccurred())

	By("Sanitizing acceptance test output")
	sanitized := map[string]string{
		pivnetAPIToken:     "***sanitized-api-token***",
		awsAccessKeyID:     "***sanitized-aws-access-key-id***",
		awsSecretAccessKey: "***sanitized-aws-secret-access-key***",
	}
	sanitizedWriter := sanitizer.NewSanitizer(sanitized, GinkgoWriter)
	GinkgoWriter = sanitizedWriter

	By("Creating pivnet client (for out-of-band operations)")

	testLogger := log.New(sanitizedWriter, "", log.LstdFlags)
	verbose := true
	ls := logshim.NewLogShim(testLogger, testLogger, verbose)

	clientConfig := pivnet.ClientConfig{
		Host:      endpoint,
		Token:     pivnetAPIToken,
		UserAgent: "pivnet-resource/integration-test",
	}

	pivnetClient = gp.NewClient(clientConfig, ls)
})

var _ = AfterSuite(func() {
	gexec.CleanupBuildArtifacts()
})
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os/exec"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

const (
	varnishstatExe = "varnishstat"
)

var (
	ignoredLinesList = []string{
		"varnishstat",
		"field name",
		"-----",
	}
)

// varnishMetric

type varnishMetric struct {
	Name               string
	Value              float64
	Description        string
	Identifier         string
	Type, Flag, Format string
}

// varnishExporter

type varnishExporter struct {
	sync.RWMutex

	version       *varnishVersion
	metrics       []*varnishMetric
	metricsByName map[string]*varnishMetric
}

func NewVarnishExporter() *varnishExporter {
	return &varnishExporter{
		version:       NewVarnishVersion(),
		metricsByName: make(map[string]*varnishMetric),
	}
}

func (v *varnishExporter) queryVersion() error {
	buf := &bytes.Buffer{}
	cmd := exec.Command(varnishstatExe, "-V")
	cmd.Stdout = buf
	cmd.Stderr = buf
	if err := cmd.Start(); err != nil {
		return err
	}
	if err := cmd.Wait(); err != nil {
		return err
	}
	scanner := bufio.NewScanner(buf)
	for scanner.Scan() {
		return v.parseVersion(scanner.Text())

	}
	return nil
}

func (v *varnishExporter) parseVersion(version string) error {
	if v.version == nil {
		v.version = NewVarnishVersion()
	}

	r := regexp.MustCompile(`(\d)\.?(\d)?\.?(\d)?(?:.*revision\s(.*)\))?`)
	parts := r.FindStringSubmatch(version)
	if len(parts) > 1 {
		if err := v.version.set(parts[1:]); err != nil {
			return err
		}
	}
	if !v.version.isValid() {
		return fmt.Errorf("Failed to resolve version from %q", version)
	}
	return nil
}

// Initializes exporter.
func (v *varnishExporter) Initialize() error {
	v.Lock()
	defer v.Unlock()

	err := v.queryVersion()
	if err != nil {
		return err
	}
	v.metrics, err = v.queryMetrics()
	if err == nil && len(v.metrics) == 0 {
		return fmt.Errorf("No metrics found from %s output", varnishstatExe)
	}
	v.metricsByName = make(map[string]*varnishMetric)
	for _, m := range v.metrics {
		v.metricsByName[m.Name] = m
	}
	if len(v.metricsByName) != len(v.metrics) {
		return fmt.Errorf("No metrics found from %s output", varnishstatExe)
	}
	return nil
}

// Updates all metrics from varnishstat.
func (v *varnishExporter) Update() error {
	v.Lock()
	defer v.Unlock()

	// query process
	if len(v.metrics) == 0 {
		return errors.New("varnishExporter.Collect: no metrics to update")
	}
	buf, err := v.executeVarnishstat("-j")
	if err != nil {
		return err
	}

	// The output JSON annoyingly is not stuctured so that we could make a nice struct for it.
	// it has a 'timestamp' key
	// @todo slight code duplication with parseMetrics, this is a bit slimmed down impl though.
	var metricsJSON map[string]interface{}
	dec := json.NewDecoder(buf)
	if errDec := dec.Decode(&metricsJSON); errDec != nil {
		return errDec
	}

	const timestamp = "timestamp"
	for name, raw := range metricsJSON {
		if name == timestamp {
			continue
		}
		m := v.metricsByName[name]
		if m == nil {
			logWarn("Failed to find existing metric for %q", name)
			continue
		}
		// @note We can skip the reflect type check and cast validation here.
		// They were executed in parseMetrics and if failed, would never end up
		// int metricsByName.
		data := raw.(map[string]interface{})

		// We are only interested in the new value for updating existing metrics.
		// Type is float64 or there would have been a error in parseMetrics.
		if value, ok := data["value"]; ok {
			m.Value = value.(float64)
		}
	}
	return nil
}

// Returns the result of 'varnishtat' with optional command line params.
func (v *varnishExporter) executeVarnishstat(params ...string) (*bytes.Buffer, error) {
	buf := bytes.Buffer{}
	cmd := exec.Command(varnishstatExe, params...)
	cmd.Stdout = &buf
	cmd.Stderr = &buf
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	if err := cmd.Wait(); err != nil {
		return nil, err
	}
	return &buf, nil
}

// Initial query at startup to resolve available metrics.
func (v *varnishExporter) queryMetrics() ([]*varnishMetric, error) {
	buf, err := v.executeVarnishstat("-j")
	if err != nil {
		return nil, err
	}
	return v.parseMetrics(buf)
}

// Parse new metrics.
func (v *varnishExporter) parseMetrics(r io.Reader) ([]*varnishMetric, error) {
	// The output JSON annoyingly is not stuctured so that we could make a nice struct for it.
	// it has a 'timestamp' key
	var metricsJSON map[string]interface{}
	dec := json.NewDecoder(r)
	if err := dec.Decode(&metricsJSON); err != nil {
		return nil, err
	}

	const timestamp = "timestamp"
	var metrics []*varnishMetric
	for name, raw := range metricsJSON {
		if name == timestamp {
			continue
		}
		if dt := reflect.TypeOf(raw); dt.Kind() != reflect.Map {
			return nil, fmt.Errorf("Found unexpected data from json: %q = %#v", name, raw)
		}
		data, ok := raw.(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("Failed to cast to map[string]interface{}: %q = %#v", name, raw)
		}
		m := &varnishMetric{
			Name: name,
		}
		for prop, value := range data {
			switch prop {
			case "description":
				m.Description = value.(string)
			case "ident":
				m.Identifier = value.(string)
			case "type":
				m.Type = value.(string)
			case "flag":
				m.Flag = value.(string)
			case "format":
				m.Format = value.(string)
			case "value":
				m.Value, ok = value.(float64)
				if !ok {
					return nil, fmt.Errorf("Non float64 property value: %s = %#v", prop, value)
				}
			default:
				// Test mode failure only, don't break future versions that might add more stuff
				if StartParams.Test {
					return nil, fmt.Errorf("Unhandled property: %s = %#v", prop, value)
				}
			}
		}
		metrics = append(metrics, m)
	}
	return metrics, nil
}

// @note deprecated in favor of JSON queries, might make a helpful library however if exported one day
func (v *varnishExporter) queryMetricsList() ([]*varnishMetric, error) {
	buf, err := v.executeVarnishstat("-l")
	if err != nil {
		return nil, err
	}
	return v.parseMetricsList(buf)
}

// @note deprecated in favor of JSON queries, might make a helpful library however if exported one day
func (v *varnishExporter) parseMetricsList(r io.Reader) ([]*varnishMetric, error) {
	scanner := bufio.NewScanner(r)

	var metrics []*varnishMetric
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) == 0 || startsWithAny(line, ignoredLinesList, caseInsensitive) {
			continue
		}
		if parts := strings.SplitAfterN(line, " ", 2); len(parts) == 2 {
			m := &varnishMetric{
				Name:        strings.TrimSpace(parts[0]),
				Description: strings.TrimSpace(parts[1]),
			}
			metrics = append(metrics, m)
		} else {
			logWarn("Found invalid metrics line: %q", line)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return metrics, nil
}

// varnishVersion

type varnishVersion struct {
	major    int
	minor    int
	patch    int
	revision string
}

func NewVarnishVersion() *varnishVersion {
	return &varnishVersion{
		major: -1, minor: -1, patch: -1,
	}
}

func (v *varnishVersion) set(parts []string) error {
	for i, part := range parts {
		if len(part) == 0 {
			continue
		}
		if i == 3 {
			v.revision = part
			break
		}
		num, err := strconv.Atoi(part)
		if err != nil {
			return err
		}
		switch i {
		case 0:
			v.major = num
		case 1:
			v.minor = num
		case 2:
			v.patch = num
		}
	}
	return nil
}

func (v *varnishVersion) isValid() bool {
	return v.major != -1
}

func (v *varnishVersion) String() string {
	parts := []string{}
	for _, num := range []int{v.major, v.minor, v.patch} {
		if num != -1 {
			parts = append(parts, strconv.Itoa(num))
		}
	}
	version := strings.Join(parts, ".")
	if v.revision != "" {
		version += " " + v.revision
	}
	return version
}
<commit_msg>Use the generic varnishstat runner also for -V run<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os/exec"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

const (
	varnishstatExe = "varnishstat"
)

var (
	ignoredLinesList = []string{
		"varnishstat",
		"field name",
		"-----",
	}
)

// varnishMetric

type varnishMetric struct {
	Name               string
	Value              float64
	Description        string
	Identifier         string
	Type, Flag, Format string
}

// varnishExporter

type varnishExporter struct {
	sync.RWMutex

	version       *varnishVersion
	metrics       []*varnishMetric
	metricsByName map[string]*varnishMetric
}

func NewVarnishExporter() *varnishExporter {
	return &varnishExporter{
		version:       NewVarnishVersion(),
		metricsByName: make(map[string]*varnishMetric),
	}
}

// Returns the result of 'varnishtat' with optional command line params.
func (v *varnishExporter) executeVarnishstat(params ...string) (*bytes.Buffer, error) {
	buf := bytes.Buffer{}
	cmd := exec.Command(varnishstatExe, params...)
	cmd.Stdout = &buf
	cmd.Stderr = &buf
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	if err := cmd.Wait(); err != nil {
		return nil, err
	}
	return &buf, nil
}

func (v *varnishExporter) queryVersion() error {
	buf, err := v.executeVarnishstat("-V")
	if err != nil {
		return err
	}
	scanner := bufio.NewScanner(buf)
	for scanner.Scan() {
		return v.parseVersion(scanner.Text())

	}
	return nil
}

func (v *varnishExporter) parseVersion(version string) error {
	if v.version == nil {
		v.version = NewVarnishVersion()
	}

	r := regexp.MustCompile(`(\d)\.?(\d)?\.?(\d)?(?:.*revision\s(.*)\))?`)
	parts := r.FindStringSubmatch(version)
	if len(parts) > 1 {
		if err := v.version.set(parts[1:]); err != nil {
			return err
		}
	}
	if !v.version.isValid() {
		return fmt.Errorf("Failed to resolve version from %q", version)
	}
	return nil
}

// Initializes exporter.
func (v *varnishExporter) Initialize() error {
	v.Lock()
	defer v.Unlock()

	err := v.queryVersion()
	if err != nil {
		return err
	}
	v.metrics, err = v.queryMetrics()
	if err == nil && len(v.metrics) == 0 {
		return fmt.Errorf("No metrics found from %s output", varnishstatExe)
	}
	v.metricsByName = make(map[string]*varnishMetric)
	for _, m := range v.metrics {
		v.metricsByName[m.Name] = m
	}
	if len(v.metricsByName) != len(v.metrics) {
		return fmt.Errorf("No metrics found from %s output", varnishstatExe)
	}
	return nil
}

// Updates all metrics from varnishstat.
func (v *varnishExporter) Update() error {
	v.Lock()
	defer v.Unlock()

	// query process
	if len(v.metrics) == 0 {
		return errors.New("varnishExporter.Collect: no metrics to update")
	}
	buf, err := v.executeVarnishstat("-j")
	if err != nil {
		return err
	}

	// The output JSON annoyingly is not stuctured so that we could make a nice struct for it.
	// it has a 'timestamp' key
	// @todo slight code duplication with parseMetrics, this is a bit slimmed down impl though.
	var metricsJSON map[string]interface{}
	dec := json.NewDecoder(buf)
	if errDec := dec.Decode(&metricsJSON); errDec != nil {
		return errDec
	}

	const timestamp = "timestamp"
	for name, raw := range metricsJSON {
		if name == timestamp {
			continue
		}
		m := v.metricsByName[name]
		if m == nil {
			logWarn("Failed to find existing metric for %q", name)
			continue
		}
		// @note We can skip the reflect type check and cast validation here.
		// They were executed in parseMetrics and if failed, would never end up
		// int metricsByName.
		data := raw.(map[string]interface{})

		// We are only interested in the new value for updating existing metrics.
		// Type is float64 or there would have been a error in parseMetrics.
		if value, ok := data["value"]; ok {
			m.Value = value.(float64)
		}
	}
	return nil
}

// Initial query at startup to resolve available metrics.
func (v *varnishExporter) queryMetrics() ([]*varnishMetric, error) {
	buf, err := v.executeVarnishstat("-j")
	if err != nil {
		return nil, err
	}
	return v.parseMetrics(buf)
}

// Parse new metrics.
func (v *varnishExporter) parseMetrics(r io.Reader) ([]*varnishMetric, error) {
	// The output JSON annoyingly is not stuctured so that we could make a nice struct for it.
	// it has a 'timestamp' key
	var metricsJSON map[string]interface{}
	dec := json.NewDecoder(r)
	if err := dec.Decode(&metricsJSON); err != nil {
		return nil, err
	}

	const timestamp = "timestamp"
	var metrics []*varnishMetric
	for name, raw := range metricsJSON {
		if name == timestamp {
			continue
		}
		if dt := reflect.TypeOf(raw); dt.Kind() != reflect.Map {
			return nil, fmt.Errorf("Found unexpected data from json: %q = %#v", name, raw)
		}
		data, ok := raw.(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("Failed to cast to map[string]interface{}: %q = %#v", name, raw)
		}
		m := &varnishMetric{
			Name: name,
		}
		for prop, value := range data {
			switch prop {
			case "description":
				m.Description = value.(string)
			case "ident":
				m.Identifier = value.(string)
			case "type":
				m.Type = value.(string)
			case "flag":
				m.Flag = value.(string)
			case "format":
				m.Format = value.(string)
			case "value":
				m.Value, ok = value.(float64)
				if !ok {
					return nil, fmt.Errorf("Non float64 property value: %s = %#v", prop, value)
				}
			default:
				// Test mode failure only, don't break future versions that might add more stuff
				if StartParams.Test {
					return nil, fmt.Errorf("Unhandled property: %s = %#v", prop, value)
				}
			}
		}
		metrics = append(metrics, m)
	}
	return metrics, nil
}

// @note deprecated in favor of JSON queries, might make a helpful library however if exported one day
func (v *varnishExporter) queryMetricsList() ([]*varnishMetric, error) {
	buf, err := v.executeVarnishstat("-l")
	if err != nil {
		return nil, err
	}
	return v.parseMetricsList(buf)
}

// @note deprecated in favor of JSON queries, might make a helpful library however if exported one day
func (v *varnishExporter) parseMetricsList(r io.Reader) ([]*varnishMetric, error) {
	scanner := bufio.NewScanner(r)

	var metrics []*varnishMetric
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) == 0 || startsWithAny(line, ignoredLinesList, caseInsensitive) {
			continue
		}
		if parts := strings.SplitAfterN(line, " ", 2); len(parts) == 2 {
			m := &varnishMetric{
				Name:        strings.TrimSpace(parts[0]),
				Description: strings.TrimSpace(parts[1]),
			}
			metrics = append(metrics, m)
		} else {
			logWarn("Found invalid metrics line: %q", line)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return metrics, nil
}

// varnishVersion

type varnishVersion struct {
	major    int
	minor    int
	patch    int
	revision string
}

func NewVarnishVersion() *varnishVersion {
	return &varnishVersion{
		major: -1, minor: -1, patch: -1,
	}
}

func (v *varnishVersion) set(parts []string) error {
	for i, part := range parts {
		if len(part) == 0 {
			continue
		}
		if i == 3 {
			v.revision = part
			break
		}
		num, err := strconv.Atoi(part)
		if err != nil {
			return err
		}
		switch i {
		case 0:
			v.major = num
		case 1:
			v.minor = num
		case 2:
			v.patch = num
		}
	}
	return nil
}

func (v *varnishVersion) isValid() bool {
	return v.major != -1
}

func (v *varnishVersion) String() string {
	parts := []string{}
	for _, num := range []int{v.major, v.minor, v.patch} {
		if num != -1 {
			parts = append(parts, strconv.Itoa(num))
		}
	}
	version := strings.Join(parts, ".")
	if v.revision != "" {
		version += " " + v.revision
	}
	return version
}
<|endoftext|>


<commit_before>package butlerd

import (
	"bufio"
	"context"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"time"

	"github.com/itchio/wharf/state"
	"github.com/pkg/errors"
	uuid "github.com/satori/go.uuid"
	"github.com/sourcegraph/jsonrpc2"
)

type Server struct {
	secret string
}

func NewServer(secret string) *Server {
	return &Server{secret: secret}
}

type gatedHandler struct {
	h        jsonrpc2.Handler
	c        chan struct{}
	unlocked bool
}

func (gh *gatedHandler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) {
	if !gh.unlocked {
		select {
		case <-gh.c:
			gh.unlocked = true
		case <-ctx.Done():
			return
		}
	}
	gh.h.Handle(ctx, conn, req)
}

func (s *Server) Serve(ctx context.Context, lis net.Listener, h jsonrpc2.Handler, consumer *state.Consumer, opt ...jsonrpc2.ConnOpt) error {
	cancel := make(chan struct{})
	conns := make(chan net.Conn)
	disconnects := make(chan struct{})
	defer close(cancel)

	numClients := 0

	go func() {
		defer close(conns)

		for {
			conn, err := lis.Accept()
			if err != nil {
				consumer.Warnf("While accepting: %s", err.Error())
			}
			conns <- conn
		}
	}()

	for {
		select {
		case conn := <-conns:
			handshakeDone := make(chan struct{})
			gh := &gatedHandler{
				h: h,
				c: handshakeDone,
			}
			agh := jsonrpc2.AsyncHandler(gh)

			connCtx, cancelFunc := context.WithCancel(ctx)

			jc := jsonrpc2.NewConn(connCtx, jsonrpc2.NewBufferedStream(conn, LFObjectCodec{}), agh, opt...)
			numClients++
			consumer.Infof("butlerd: Accepted connection! (%d clients now)", numClients)
			go func() {
				<-jc.DisconnectNotify()
				cancelFunc()
				disconnects <- struct{}{}
			}()

			generateMessage := func() (string, error) {
				msg := ""
				for i := 0; i < 4; i++ {
					u, err := uuid.NewV4()
					if err != nil {
						return "", errors.Wrap(err, "generating UUID")
					}
					msg += u.String()
				}
				return msg, nil
			}

			go func() {
				die := func(msg string, args ...interface{}) {
					fmsg := fmt.Sprintf(msg, args...)
					consumer.Warnf("%s", fmsg)
					jc.Notify(ctx, "Log", LogNotification{
						Level:   "error",
						Message: fmsg,
					})
					jc.Close()
				}

				hres := &HandshakeResult{}
				message, err := generateMessage()
				if err != nil {
					die("butlerd: Message generation error: %s", err.Error())
					return
				}

				err = jc.Call(ctx, "Handshake", &HandshakeParams{
					Message: message,
				}, hres)
				if err != nil {
					die("butlerd: Handshake error: %s", err.Error())
					return
				}

				expectedSigBytes := sha256.Sum256([]byte(s.secret + message))
				expectedSig := fmt.Sprintf("%x", expectedSigBytes)
				if expectedSig != hres.Signature {
					die("butlerd: Handshake failed")
					return
				}

				close(handshakeDone)
			}()

			select {
			case <-handshakeDone:
				// good!
			case <-time.After(15 * time.Second):
				consumer.Warnf("butlerd: Handshake timed out!")
				jc.Close()
			}
		case <-disconnects:
			numClients--
			consumer.Infof("butlerd: Client disconnected! (%d clients left)", numClients)
			if numClients == 0 {
				consumer.Infof("butlerd: Last client left, shutting down")
				return nil
			}
		}
	}
}

type LFObjectCodec struct{}

var separator = []byte("\n")

func (LFObjectCodec) WriteObject(stream io.Writer, obj interface{}) error {
	data, err := json.Marshal(obj)
	if err != nil {
		return err
	}

	if _, err := stream.Write(data); err != nil {
		return err
	}
	if _, err := stream.Write(separator); err != nil {
		return err
	}
	return nil
}

func (LFObjectCodec) ReadObject(stream *bufio.Reader, v interface{}) error {
	var buf []byte

scanLoop:
	for {
		b, err := stream.ReadByte()
		if err != nil {
			return err
		}

		switch b {
		case '\n':
			break scanLoop
		default:
			buf = append(buf, b)
		}
	}

	return json.Unmarshal(buf, v)
}

type Conn interface {
	Notify(ctx context.Context, method string, params interface{}) error
	Call(ctx context.Context, method string, params interface{}, result interface{}) error
}

//

type JsonRPC2Conn struct {
	Conn *jsonrpc2.Conn
}

var _ Conn = (*JsonRPC2Conn)(nil)

func (jc *JsonRPC2Conn) Notify(ctx context.Context, method string, params interface{}) error {
	return jc.Conn.Notify(ctx, method, params)
}

func (jc *JsonRPC2Conn) Call(ctx context.Context, method string, params interface{}, result interface{}) error {
	return jc.Conn.Call(ctx, method, params, result)
}

func (jc *JsonRPC2Conn) Close() error {
	return jc.Conn.Close()
}
<commit_msg>Handle handshakes asynchronously, so concurrent handshakes don't block<commit_after>package butlerd

import (
	"bufio"
	"context"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"time"

	"github.com/itchio/wharf/state"
	"github.com/pkg/errors"
	uuid "github.com/satori/go.uuid"
	"github.com/sourcegraph/jsonrpc2"
)

type Server struct {
	secret string
}

func NewServer(secret string) *Server {
	return &Server{secret: secret}
}

type gatedHandler struct {
	h        jsonrpc2.Handler
	c        chan struct{}
	unlocked bool
}

func (gh *gatedHandler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) {
	if !gh.unlocked {
		select {
		case <-gh.c:
			gh.unlocked = true
		case <-ctx.Done():
			return
		}
	}
	gh.h.Handle(ctx, conn, req)
}

func (s *Server) Serve(ctx context.Context, lis net.Listener, h jsonrpc2.Handler, consumer *state.Consumer, opt ...jsonrpc2.ConnOpt) error {
	cancel := make(chan struct{})
	conns := make(chan net.Conn)
	disconnects := make(chan struct{})
	defer close(cancel)

	numClients := 0

	go func() {
		defer close(conns)

		for {
			conn, err := lis.Accept()
			if err != nil {
				consumer.Warnf("While accepting: %s", err.Error())
			}
			conns <- conn
		}
	}()

	for {
		select {
		case conn := <-conns:
			handshakeDone := make(chan struct{})
			gh := &gatedHandler{
				h: h,
				c: handshakeDone,
			}
			agh := jsonrpc2.AsyncHandler(gh)

			connCtx, cancelFunc := context.WithCancel(ctx)

			jc := jsonrpc2.NewConn(connCtx, jsonrpc2.NewBufferedStream(conn, LFObjectCodec{}), agh, opt...)
			numClients++
			consumer.Infof("butlerd: Accepted connection! (%d clients now)", numClients)
			go func() {
				<-jc.DisconnectNotify()
				cancelFunc()
				disconnects <- struct{}{}
			}()

			generateMessage := func() (string, error) {
				msg := ""
				for i := 0; i < 4; i++ {
					u, err := uuid.NewV4()
					if err != nil {
						return "", errors.Wrap(err, "generating UUID")
					}
					msg += u.String()
				}
				return msg, nil
			}

			go func() {
				die := func(msg string, args ...interface{}) {
					fmsg := fmt.Sprintf(msg, args...)
					consumer.Warnf("%s", fmsg)
					jc.Notify(ctx, "Log", LogNotification{
						Level:   "error",
						Message: fmsg,
					})
					jc.Close()
				}

				hres := &HandshakeResult{}
				message, err := generateMessage()
				if err != nil {
					die("butlerd: Message generation error: %s", err.Error())
					return
				}

				err = jc.Call(ctx, "Handshake", &HandshakeParams{
					Message: message,
				}, hres)
				if err != nil {
					die("butlerd: Handshake error: %s", err.Error())
					return
				}

				expectedSigBytes := sha256.Sum256([]byte(s.secret + message))
				expectedSig := fmt.Sprintf("%x", expectedSigBytes)
				if expectedSig != hres.Signature {
					die("butlerd: Handshake failed")
					return
				}

				close(handshakeDone)
			}()

			go func() {
				select {
				case <-handshakeDone:
					// good!
				case <-time.After(15 * time.Second):
					consumer.Warnf("butlerd: Handshake timed out!")
					jc.Close()
				}
			}()
		case <-disconnects:
			numClients--
			consumer.Infof("butlerd: Client disconnected! (%d clients left)", numClients)
			if numClients == 0 {
				consumer.Infof("butlerd: Last client left, shutting down")
				return nil
			}
		}
	}
}

type LFObjectCodec struct{}

var separator = []byte("\n")

func (LFObjectCodec) WriteObject(stream io.Writer, obj interface{}) error {
	data, err := json.Marshal(obj)
	if err != nil {
		return err
	}

	if _, err := stream.Write(data); err != nil {
		return err
	}
	if _, err := stream.Write(separator); err != nil {
		return err
	}
	return nil
}

func (LFObjectCodec) ReadObject(stream *bufio.Reader, v interface{}) error {
	var buf []byte

scanLoop:
	for {
		b, err := stream.ReadByte()
		if err != nil {
			return err
		}

		switch b {
		case '\n':
			break scanLoop
		default:
			buf = append(buf, b)
		}
	}

	return json.Unmarshal(buf, v)
}

type Conn interface {
	Notify(ctx context.Context, method string, params interface{}) error
	Call(ctx context.Context, method string, params interface{}, result interface{}) error
}

//

type JsonRPC2Conn struct {
	Conn *jsonrpc2.Conn
}

var _ Conn = (*JsonRPC2Conn)(nil)

func (jc *JsonRPC2Conn) Notify(ctx context.Context, method string, params interface{}) error {
	return jc.Conn.Notify(ctx, method, params)
}

func (jc *JsonRPC2Conn) Call(ctx context.Context, method string, params interface{}, result interface{}) error {
	return jc.Conn.Call(ctx, method, params, result)
}

func (jc *JsonRPC2Conn) Close() error {
	return jc.Conn.Close()
}
<|endoftext|>


<commit_before>package integrationtests

import (
	"crypto/rand"
	"fmt"
	"io"
	"net"
	"net/http"
	"os/exec"
	"strconv"
	"time"

	"github.com/lucas-clemente/quic-go/h2quic"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/testdata"
	"github.com/tebeka/selenium"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"

	"testing"
)

const (
	dataLen = 50 * 1024
)

var (
	server *h2quic.Server
	data   []byte
	port   string

	docker *gexec.Session
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Integration Tests Suite")
}

var _ = BeforeSuite(func() {
	setupHTTPHandlers()
	setupQuicServer()
	setupSelenium()
})

var _ = AfterSuite(func() {
	err := server.Close()
	Expect(err).NotTo(HaveOccurred())

	stopSelenium()
})

func setupHTTPHandlers() {
	defer GinkgoRecover()
	data = make([]byte, dataLen)
	_, err := rand.Read(data)
	Expect(err).NotTo(HaveOccurred())

	http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := io.WriteString(w, "Hello, World!\n")
		Expect(err).NotTo(HaveOccurred())
	})

	http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := w.Write(data)
		Expect(err).NotTo(HaveOccurred())
	})

	http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := io.Copy(w, r.Body)
		Expect(err).NotTo(HaveOccurred())
	})
}

func setupQuicServer() {
	server = &h2quic.Server{
		Server: &http.Server{
			TLSConfig: testdata.GetTLSConfig(),
		},
	}

	addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:0")
	Expect(err).NotTo(HaveOccurred())
	conn, err := net.ListenUDP("udp", addr)
	Expect(err).NotTo(HaveOccurred())
	port = strconv.Itoa(conn.LocalAddr().(*net.UDPAddr).Port)

	go func() {
		defer GinkgoRecover()
		server.Serve(conn)
	}()
}

func setupSelenium() {
	var err error
	pullCmd := exec.Command("docker", "pull", "lclemente/standalone-chrome:latest")
	pull, err := gexec.Start(pullCmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	// Assuming a download at 10 Mbit/s
	Eventually(pull, 10*time.Minute).Should(gexec.Exit(0))

	dockerCmd := exec.Command(
		"docker",
		"run",
		"-i",
		"--rm",
		"-p=4444:4444",
		"lclemente/standalone-chrome:latest",
	)
	docker, err = gexec.Start(dockerCmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(docker.Out, 5).Should(gbytes.Say("Selenium Server is up and running"))
}

func stopSelenium() {
	docker.Interrupt().Wait(1)
}

func getWebdriverForVersion(version protocol.VersionNumber) selenium.WebDriver {
	caps := selenium.Capabilities{
		"browserName": "chrome",
		"chromeOptions": map[string]interface{}{
			"args": []string{
				"--enable-quic",
				"--no-proxy-server",
				"--origin-to-force-quic-on=quic.clemente.io:443",
				fmt.Sprintf(`--host-resolver-rules=MAP quic.clemente.io:443 %s:%s`, GetLocalIP(), port),
				fmt.Sprintf(`--quic-version=QUIC_VERSION_%d`, version),
			},
		},
	}
	wd, err := selenium.NewRemote(caps, "http://localhost:4444/wd/hub")
	Expect(err).NotTo(HaveOccurred())
	return wd
}

func GetLocalIP() string {
	// First, try finding interface docker0
	i, err := net.InterfaceByName("docker0")
	if err == nil {
		var addrs []net.Addr
		addrs, err = i.Addrs()
		Expect(err).NotTo(HaveOccurred())
		return addrs[0].(*net.IPNet).IP.String()
	}

	addrs, err := net.InterfaceAddrs()
	Expect(err).NotTo(HaveOccurred())
	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}
	panic("no addr")
}
<commit_msg>remove timeout for stopping docker, add timeout for inttests aftersuite<commit_after>package integrationtests

import (
	"crypto/rand"
	"fmt"
	"io"
	"net"
	"net/http"
	"os/exec"
	"strconv"
	"time"

	"github.com/lucas-clemente/quic-go/h2quic"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/testdata"
	"github.com/tebeka/selenium"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"

	"testing"
)

const (
	dataLen = 50 * 1024
)

var (
	server *h2quic.Server
	data   []byte
	port   string

	docker *gexec.Session
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Integration Tests Suite")
}

var _ = BeforeSuite(func() {
	setupHTTPHandlers()
	setupQuicServer()
	setupSelenium()
})

var _ = AfterSuite(func() {
	err := server.Close()
	Expect(err).NotTo(HaveOccurred())

	stopSelenium()
}, 5)

func setupHTTPHandlers() {
	defer GinkgoRecover()
	data = make([]byte, dataLen)
	_, err := rand.Read(data)
	Expect(err).NotTo(HaveOccurred())

	http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := io.WriteString(w, "Hello, World!\n")
		Expect(err).NotTo(HaveOccurred())
	})

	http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := w.Write(data)
		Expect(err).NotTo(HaveOccurred())
	})

	http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
		defer GinkgoRecover()
		_, err := io.Copy(w, r.Body)
		Expect(err).NotTo(HaveOccurred())
	})
}

func setupQuicServer() {
	server = &h2quic.Server{
		Server: &http.Server{
			TLSConfig: testdata.GetTLSConfig(),
		},
	}

	addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:0")
	Expect(err).NotTo(HaveOccurred())
	conn, err := net.ListenUDP("udp", addr)
	Expect(err).NotTo(HaveOccurred())
	port = strconv.Itoa(conn.LocalAddr().(*net.UDPAddr).Port)

	go func() {
		defer GinkgoRecover()
		server.Serve(conn)
	}()
}

func setupSelenium() {
	var err error
	pullCmd := exec.Command("docker", "pull", "lclemente/standalone-chrome:latest")
	pull, err := gexec.Start(pullCmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	// Assuming a download at 10 Mbit/s
	Eventually(pull, 10*time.Minute).Should(gexec.Exit(0))

	dockerCmd := exec.Command(
		"docker",
		"run",
		"-i",
		"--rm",
		"-p=4444:4444",
		"lclemente/standalone-chrome:latest",
	)
	docker, err = gexec.Start(dockerCmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(docker.Out, 5).Should(gbytes.Say("Selenium Server is up and running"))
}

func stopSelenium() {
	docker.Interrupt().Wait()
}

func getWebdriverForVersion(version protocol.VersionNumber) selenium.WebDriver {
	caps := selenium.Capabilities{
		"browserName": "chrome",
		"chromeOptions": map[string]interface{}{
			"args": []string{
				"--enable-quic",
				"--no-proxy-server",
				"--origin-to-force-quic-on=quic.clemente.io:443",
				fmt.Sprintf(`--host-resolver-rules=MAP quic.clemente.io:443 %s:%s`, GetLocalIP(), port),
				fmt.Sprintf(`--quic-version=QUIC_VERSION_%d`, version),
			},
		},
	}
	wd, err := selenium.NewRemote(caps, "http://localhost:4444/wd/hub")
	Expect(err).NotTo(HaveOccurred())
	return wd
}

func GetLocalIP() string {
	// First, try finding interface docker0
	i, err := net.InterfaceByName("docker0")
	if err == nil {
		var addrs []net.Addr
		addrs, err = i.Addrs()
		Expect(err).NotTo(HaveOccurred())
		return addrs[0].(*net.IPNet).IP.String()
	}

	addrs, err := net.InterfaceAddrs()
	Expect(err).NotTo(HaveOccurred())
	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}
	panic("no addr")
}
<|endoftext|>


<commit_before>//
//  Important -- when you're creating a new cb-cli version for github,
//  set the cbCliVersion string var below before pushing to github.
//  -swm
//
package main

var cbCliVersion = "2.14"
<commit_msg>bump to v3.0<commit_after>//
//  Important -- when you're creating a new cb-cli version for github,
//  set the cbCliVersion string var below before pushing to github.
//  -swm
//
package main

var cbCliVersion = "3.0"
<|endoftext|>


<commit_before>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "1.0.0"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<commit_msg>1.0.1<commit_after>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "1.0.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<|endoftext|>


<commit_before>package swag

// Version of swag
const Version = "v1.6.6"
<commit_msg>chore: jump to v1.6.7 (#725)<commit_after>package swag

// Version of swag
const Version = "v1.6.7"
<|endoftext|>