<commit_before>package broker

import (
	"errors"
	"sync"
	"time"

	"gopkg.in/redis.v3"

	pb "github.com/TheThingsNetwork/ttn/api/broker"
	"github.com/TheThingsNetwork/ttn/api/networkserver"
	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/broker/application"
)

type Broker interface {
	core.ComponentInterface

	HandleUplink(uplink *pb.UplinkMessage) error
	HandleDownlink(downlink *pb.DownlinkMessage) error
	HandleActivation(activation *pb.DeviceActivationRequest) (*pb.DeviceActivationResponse, error)

	ActivateRouter(id string) (<-chan *pb.DownlinkMessage, error)
	DeactivateRouter(id string) error
	ActivateHandler(id string) (<-chan *pb.DeduplicatedUplinkMessage, error)
	DeactivateHandler(id string) error
}

func NewRedisBroker(client *redis.Client, networkserver string, timeout time.Duration) Broker {
	return &broker{
		routers:                make(map[string]chan *pb.DownlinkMessage),
		handlers:               make(map[string]chan *pb.DeduplicatedUplinkMessage),
		applications:           application.NewRedisApplicationStore(client),
		uplinkDeduplicator:     NewDeduplicator(timeout),
		activationDeduplicator: NewDeduplicator(timeout),
		nsAddr:                 networkserver,
	}
}

type broker struct {
	*core.Component
	routers                map[string]chan *pb.DownlinkMessage
	routersLock            sync.RWMutex
	handlers               map[string]chan *pb.DeduplicatedUplinkMessage
	handlersLock           sync.RWMutex
	applications           application.Store
	nsAddr                 string
	ns                     networkserver.NetworkServerClient
	uplinkDeduplicator     Deduplicator
	activationDeduplicator Deduplicator
}

func (b *broker) Init(c *core.Component) error {
	b.Component = c
	err := b.Component.UpdateTokenKey()
	if err != nil {
		return err
	}
	err = b.Component.Announce()
	if err != nil {
		return err
	}

	return nil
}

func (b *broker) ActivateRouter(id string) (<-chan *pb.DownlinkMessage, error) {
	b.routersLock.Lock()
	defer b.routersLock.Unlock()
	if existing, ok := b.routers[id]; ok {
		return existing, errors.New("Router already active")
	}
	b.routers[id] = make(chan *pb.DownlinkMessage)
	return b.routers[id], nil
}

func (b *broker) DeactivateRouter(id string) error {
	b.routersLock.Lock()
	defer b.routersLock.Unlock()
	if channel, ok := b.routers[id]; ok {
		close(channel)
		delete(b.routers, id)
		return nil
	}
	return errors.New("Router not active")
}

func (b *broker) getRouter(id string) (chan<- *pb.DownlinkMessage, error) {
	b.routersLock.RLock()
	defer b.routersLock.RUnlock()
	if router, ok := b.routers[id]; ok {
		return router, nil
	}
	return nil, errors.New("Router not active")
}

func (b *broker) ActivateHandler(id string) (<-chan *pb.DeduplicatedUplinkMessage, error) {
	b.handlersLock.Lock()
	defer b.handlersLock.Unlock()
	if existing, ok := b.handlers[id]; ok {
		return existing, errors.New("Handler already active")
	}
	b.handlers[id] = make(chan *pb.DeduplicatedUplinkMessage)
	return b.handlers[id], nil
}

func (b *broker) DeactivateHandler(id string) error {
	b.handlersLock.Lock()
	defer b.handlersLock.Unlock()
	if channel, ok := b.handlers[id]; ok {
		close(channel)
		delete(b.handlers, id)
		return nil
	}
	return errors.New("Handler not active")
}

func (b *broker) getHandler(id string) (chan<- *pb.DeduplicatedUplinkMessage, error) {
	b.handlersLock.RLock()
	defer b.handlersLock.RUnlock()
	if handler, ok := b.handlers[id]; ok {
		return handler, nil
	}
	return nil, errors.New("Handler not active")
}
<commit_msg>Start NetworkServer connection in Broker Init<commit_after>package broker

import (
	"errors"
	"sync"
	"time"

	"google.golang.org/grpc"

	"gopkg.in/redis.v3"

	"github.com/TheThingsNetwork/ttn/api"
	pb "github.com/TheThingsNetwork/ttn/api/broker"
	"github.com/TheThingsNetwork/ttn/api/networkserver"
	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/broker/application"
)

type Broker interface {
	core.ComponentInterface

	HandleUplink(uplink *pb.UplinkMessage) error
	HandleDownlink(downlink *pb.DownlinkMessage) error
	HandleActivation(activation *pb.DeviceActivationRequest) (*pb.DeviceActivationResponse, error)

	ActivateRouter(id string) (<-chan *pb.DownlinkMessage, error)
	DeactivateRouter(id string) error
	ActivateHandler(id string) (<-chan *pb.DeduplicatedUplinkMessage, error)
	DeactivateHandler(id string) error
}

func NewRedisBroker(client *redis.Client, networkserver string, timeout time.Duration) Broker {
	return &broker{
		routers:                make(map[string]chan *pb.DownlinkMessage),
		handlers:               make(map[string]chan *pb.DeduplicatedUplinkMessage),
		applications:           application.NewRedisApplicationStore(client),
		uplinkDeduplicator:     NewDeduplicator(timeout),
		activationDeduplicator: NewDeduplicator(timeout),
		nsAddr:                 networkserver,
	}
}

type broker struct {
	*core.Component
	routers                map[string]chan *pb.DownlinkMessage
	routersLock            sync.RWMutex
	handlers               map[string]chan *pb.DeduplicatedUplinkMessage
	handlersLock           sync.RWMutex
	applications           application.Store
	nsAddr                 string
	ns                     networkserver.NetworkServerClient
	uplinkDeduplicator     Deduplicator
	activationDeduplicator Deduplicator
}

func (b *broker) Init(c *core.Component) error {
	b.Component = c
	err := b.Component.UpdateTokenKey()
	if err != nil {
		return err
	}
	err = b.Component.Announce()
	if err != nil {
		return err
	}
	conn, err := grpc.Dial(b.nsAddr, api.DialOptions...)
	if err != nil {
		return err
	}
	client := networkserver.NewNetworkServerClient(conn)
	b.ns = client

	return nil
}

func (b *broker) ActivateRouter(id string) (<-chan *pb.DownlinkMessage, error) {
	b.routersLock.Lock()
	defer b.routersLock.Unlock()
	if existing, ok := b.routers[id]; ok {
		return existing, errors.New("Router already active")
	}
	b.routers[id] = make(chan *pb.DownlinkMessage)
	return b.routers[id], nil
}

func (b *broker) DeactivateRouter(id string) error {
	b.routersLock.Lock()
	defer b.routersLock.Unlock()
	if channel, ok := b.routers[id]; ok {
		close(channel)
		delete(b.routers, id)
		return nil
	}
	return errors.New("Router not active")
}

func (b *broker) getRouter(id string) (chan<- *pb.DownlinkMessage, error) {
	b.routersLock.RLock()
	defer b.routersLock.RUnlock()
	if router, ok := b.routers[id]; ok {
		return router, nil
	}
	return nil, errors.New("Router not active")
}

func (b *broker) ActivateHandler(id string) (<-chan *pb.DeduplicatedUplinkMessage, error) {
	b.handlersLock.Lock()
	defer b.handlersLock.Unlock()
	if existing, ok := b.handlers[id]; ok {
		return existing, errors.New("Handler already active")
	}
	b.handlers[id] = make(chan *pb.DeduplicatedUplinkMessage)
	return b.handlers[id], nil
}

func (b *broker) DeactivateHandler(id string) error {
	b.handlersLock.Lock()
	defer b.handlersLock.Unlock()
	if channel, ok := b.handlers[id]; ok {
		close(channel)
		delete(b.handlers, id)
		return nil
	}
	return errors.New("Handler not active")
}

func (b *broker) getHandler(id string) (chan<- *pb.DeduplicatedUplinkMessage, error) {
	b.handlersLock.RLock()
	defer b.handlersLock.RUnlock()
	if handler, ok := b.handlers[id]; ok {
		return handler, nil
	}
	return nil, errors.New("Handler not active")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

// Version ...
type Version struct {
	Major uint64
	Minor uint64
	Patch uint64
}

func (v Version) String() string {
	s := make([]byte, 0, 5)
	s = strconv.AppendUint(s, v.Major, 10)
	s = append(s, '.')
	s = strconv.AppendUint(s, v.Minor, 10)
	s = append(s, '.')
	s = strconv.AppendUint(s, v.Patch, 10)

	return string(s)
}

func bumpVersion(v Version, bumpLevel string) (Version, error) {

	if bumpLevel == "patch" {
		v.Patch++
	} else if bumpLevel == "minor" {
		v.Minor++
		v.Patch = 0
	} else if bumpLevel == "major" {
		v.Major++
		v.Minor = 0
		v.Patch = 0
	} else {
		return Version{}, fmt.Errorf("Bump level '%s' unknown", bumpLevel)
	}

	return v, nil
}

func gitCommit(path, bumpLevel, newVersion, gitRemotes string, gitPush bool) {

	// git add
	fmt.Println("Adding changes to Git index")
	os.Chdir(path)
	_, err := exec.Command("git", "add", "metadata.rb").Output()
	if err != nil {
		log.Fatal(err)
	}

	if gitPush {

		// git commit
		fmt.Println("Committing changes")
		commitMessage := fmt.Sprintf("%s bump to version %s", bumpLevel, newVersion)
		_, err := exec.Command("git", "commit", "-m", commitMessage, "-n").Output()
		if err != nil {
			log.Fatal(err)
		}

		// git tag
		fmt.Printf("Adding tag '%s'\n", newVersion)
		tagMessage := fmt.Sprintf("%s", newVersion)
		_, err = exec.Command("git", "tag", "-a", newVersion, "-m", tagMessage).Output()
		if err != nil {
			log.Fatal(err)
		}

		// git push to gitRemotes
		remotes := strings.Split(gitRemotes, ",")
		for i := range remotes {
			remote := strings.TrimSpace(remotes[i])
			fmt.Printf("Pushing changes to '%s'\n", remote)
			_, err = exec.Command("git", "push", remote, "master", "--follow-tags").Output()
			if err != nil {
				log.Fatal(err)
			}
		}

	}
}

func parseVersion(version string) (Version, error) {
	versionArray := strings.SplitN(version, ".", 3)
	if len(versionArray) != 3 {
		return Version{}, fmt.Errorf("No major/minor/patch elements found")
	}

	var err error
	v := Version{}

	// major
	v.Major, err = strconv.ParseUint(versionArray[0], 10, 64)
	if err != nil {
		return Version{}, err
	}

	// minor
	v.Minor, err = strconv.ParseUint(versionArray[1], 10, 64)
	if err != nil {
		return Version{}, err
	}

	// patch
	v.Patch, err = strconv.ParseUint(versionArray[2], 10, 64)
	if err != nil {
		return Version{}, err
	}

	return v, nil
}

func metadata(path, bumpLevel string) string {
	path += "/metadata.rb"
	input, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatalln(err)
	}

	lines := strings.Split(string(input), "\n")
	newVersion := Version{}

	for i, line := range lines {
		if strings.Contains(line, "version") {
			line = strings.Replace(line, "\"", "'", 2)
			lineArray := strings.Split(line, "'")
			fmt.Printf("Current version: %s\n", lineArray[1])

			version, err := parseVersion(lineArray[1])
			if err != nil {
				log.Fatalln(err)
			}

			newVersion, err = bumpVersion(version, bumpLevel)
			if err != nil {
				log.Fatalln(err)
			}

			lineArray[1] = newVersion.String()
			fmt.Printf("New version: %s\n", lineArray[1])

			lines[i] = strings.Join(lineArray, "'")
		}
	}

	output := strings.Join(lines, "\n")
	err = ioutil.WriteFile(path, []byte(output), 0644)
	if err != nil {
		log.Fatalln(err)
	}

	return newVersion.String()
}

func main() {
	path := flag.String("path", "", "Full or relative path to the cookbook directory. REQUIRED.")
	bumpLevel := flag.String("bump-level", "patch", "Version level to bump the cookbook")
	gitPush := flag.Bool("git-push", true, "Whether or not changes should be committed.")
	gitRemotes := flag.String("git-remotes", "upstream, origin", "Comma separated list of Git remotes")
	flag.Parse()

	if *path == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}

	newVersion := metadata(*path, *bumpLevel)
	gitCommit(*path, *bumpLevel, newVersion, *gitRemotes, *gitPush)
}
<commit_msg>A more strict pattern matching to detect cookbook version in metadata<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

// Version ...
type Version struct {
	Major uint64
	Minor uint64
	Patch uint64
}

func (v Version) String() string {
	s := make([]byte, 0, 5)
	s = strconv.AppendUint(s, v.Major, 10)
	s = append(s, '.')
	s = strconv.AppendUint(s, v.Minor, 10)
	s = append(s, '.')
	s = strconv.AppendUint(s, v.Patch, 10)

	return string(s)
}

func bumpVersion(v Version, bumpLevel string) (Version, error) {

	if bumpLevel == "patch" {
		v.Patch++
	} else if bumpLevel == "minor" {
		v.Minor++
		v.Patch = 0
	} else if bumpLevel == "major" {
		v.Major++
		v.Minor = 0
		v.Patch = 0
	} else {
		return Version{}, fmt.Errorf("Bump level '%s' unknown", bumpLevel)
	}

	return v, nil
}

func gitCommit(path, bumpLevel, newVersion, gitRemotes string, gitPush bool) {

	// git add
	fmt.Println("Adding changes to Git index")
	os.Chdir(path)
	_, err := exec.Command("git", "add", "metadata.rb").Output()
	if err != nil {
		log.Fatal(err)
	}

	if gitPush {

		// git commit
		fmt.Println("Committing changes")
		commitMessage := fmt.Sprintf("%s bump to version %s", bumpLevel, newVersion)
		_, err := exec.Command("git", "commit", "-m", commitMessage, "-n").Output()
		if err != nil {
			log.Fatal(err)
		}

		// git tag
		fmt.Printf("Adding tag '%s'\n", newVersion)
		tagMessage := fmt.Sprintf("%s", newVersion)
		_, err = exec.Command("git", "tag", "-a", newVersion, "-m", tagMessage).Output()
		if err != nil {
			log.Fatal(err)
		}

		// git push to gitRemotes
		remotes := strings.Split(gitRemotes, ",")
		for i := range remotes {
			remote := strings.TrimSpace(remotes[i])
			fmt.Printf("Pushing changes to '%s'\n", remote)
			_, err = exec.Command("git", "push", remote, "master", "--follow-tags").Output()
			if err != nil {
				log.Fatal(err)
			}
		}

	}
}

func parseVersion(version string) (Version, error) {
	versionArray := strings.SplitN(version, ".", 3)
	if len(versionArray) != 3 {
		return Version{}, fmt.Errorf("No major/minor/patch elements found")
	}

	var err error
	v := Version{}

	// major
	v.Major, err = strconv.ParseUint(versionArray[0], 10, 64)
	if err != nil {
		return Version{}, err
	}

	// minor
	v.Minor, err = strconv.ParseUint(versionArray[1], 10, 64)
	if err != nil {
		return Version{}, err
	}

	// patch
	v.Patch, err = strconv.ParseUint(versionArray[2], 10, 64)
	if err != nil {
		return Version{}, err
	}

	return v, nil
}

func metadata(path, bumpLevel string) string {
	path += "/metadata.rb"
	input, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatalln(err)
	}

	lines := strings.Split(string(input), "\n")
	newVersion := Version{}

	for i, line := range lines {
		matchedVersionPattern, _ := regexp.MatchString("^( |\t)*version( |\t)+(\\'|\")(.+)(\\'|\")", line)
		if matchedVersionPattern {
			line = strings.Replace(line, "\"", "'", 2)
			lineArray := strings.Split(line, "'")
			fmt.Printf("Current version: %s\n", lineArray[1])

			version, err := parseVersion(lineArray[1])
			if err != nil {
				log.Fatalln(err)
			}

			newVersion, err = bumpVersion(version, bumpLevel)
			if err != nil {
				log.Fatalln(err)
			}

			lineArray[1] = newVersion.String()
			fmt.Printf("New version: %s\n", lineArray[1])

			lines[i] = strings.Join(lineArray, "'")
			break
		}
	}

	output := strings.Join(lines, "\n")
	err = ioutil.WriteFile(path, []byte(output), 0644)
	if err != nil {
		log.Fatalln(err)
	}

	return newVersion.String()
}

func main() {
	path := flag.String("path", "", "Full or relative path to the cookbook directory. REQUIRED.")
	bumpLevel := flag.String("bump-level", "patch", "Version level to bump the cookbook")
	gitPush := flag.Bool("git-push", true, "Whether or not changes should be committed.")
	gitRemotes := flag.String("git-remotes", "upstream, origin", "Comma separated list of Git remotes")
	flag.Parse()

	if *path == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}

	newVersion := metadata(*path, *bumpLevel)
	gitCommit(*path, *bumpLevel, newVersion, *gitRemotes, *gitPush)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/codegangsta/cli"

	"launchpad.net/goyaml"

	"github.com/vito/spiff/compare"
	"github.com/vito/spiff/flow"
	"github.com/vito/spiff/yaml"
)

func main() {
	app := cli.NewApp()
	app.Name = "spiff"
	app.Usage = "BOSH deployment manifest toolkit"

	app.Commands = []cli.Command{
		{
			Name:      "merge",
			ShortName: "m",
			Usage:     "merge merge stub files into a manifest template",
			Action: func(c *cli.Context) {
				if len(c.Args()) < 2 {
					cli.ShowCommandHelp(c, "merge")
					os.Exit(1)
				}

				merge(c.Args()[0], c.Args()[1:])
			},
		},
		{
			Name:      "diff",
			ShortName: "d",
			Usage:     "structurally compare two YAML files",
			Action: func(c *cli.Context) {
				if len(c.Args()) < 2 {
					cli.ShowCommandHelp(c, "diff")
					os.Exit(1)
				}

				diff(c.Args()[0], c.Args()[1])
			},
		},
	}

	app.Run(os.Args)
}

func merge(templateFilePath string, stubFilePaths []string) {
	templateFile, err := ioutil.ReadFile(templateFilePath)
	if err != nil {
		log.Fatalln("error reading template:", err)
	}

	templateYAML, err := yaml.Parse(templateFile)
	if err != nil {
		log.Fatalln("error parsing template:", err)
	}

	stubs := []yaml.Node{}

	for _, stubFilePath := range stubFilePaths {
		stubFile, err := ioutil.ReadFile(stubFilePath)
		if err != nil {
			log.Fatalln("error reading stub:", err)
		}

		stubYAML, err := yaml.Parse(stubFile)
		if err != nil {
			log.Fatalln("error parsing stub:", err)
		}

		stubs = append(stubs, stubYAML)
	}

	flowed, err := flow.Flow(templateYAML, stubs...)
	if err != nil {
		log.Fatalln("error generating manifest:", err)
	}

	yaml, err := goyaml.Marshal(flowed)
	if err != nil {
		log.Fatalln("error marshalling manifest:", err)
	}

	fmt.Println(string(yaml))
}

func diff(aFilePath, bFilePath string) {
	aFile, err := ioutil.ReadFile(aFilePath)
	if err != nil {
		log.Fatalln("error reading a:", err)
	}

	aYAML, err := yaml.Parse(aFile)
	if err != nil {
		log.Fatalln("error parsing a:", err)
	}

	bFile, err := ioutil.ReadFile(bFilePath)
	if err != nil {
		log.Fatalln("error reading b:", err)
	}

	bYAML, err := yaml.Parse(bFile)
	if err != nil {
		log.Fatalln("error parsing b:", err)
	}

	diffs := compare.Compare(aYAML, bYAML)

	if len(diffs) == 0 {
		fmt.Println("no differences!")
		return
	}

	for _, diff := range diffs {
		fmt.Println("Difference in", strings.Join(diff.Path, "."))

		if diff.A != nil {
			ayaml, err := goyaml.Marshal(diff.A)
			if err != nil {
				panic(err)
			}

			fmt.Printf("  %s has:\n    \x1b[32m%s\x1b[0m\n", aFilePath, strings.Replace(string(ayaml), "\n", "\n    ", -1))
		}

		if diff.B != nil {
			byaml, err := goyaml.Marshal(diff.B)
			if err != nil {
				panic(err)
			}

			fmt.Printf("  %s has:\n    \x1b[31m%s\x1b[0m\n", bFilePath, strings.Replace(string(byaml), "\n", "\n    ", -1))
		}
	}
}
<commit_msg>reverse coloring of spiff diff<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/codegangsta/cli"

	"launchpad.net/goyaml"

	"github.com/vito/spiff/compare"
	"github.com/vito/spiff/flow"
	"github.com/vito/spiff/yaml"
)

func main() {
	app := cli.NewApp()
	app.Name = "spiff"
	app.Usage = "BOSH deployment manifest toolkit"

	app.Commands = []cli.Command{
		{
			Name:      "merge",
			ShortName: "m",
			Usage:     "merge merge stub files into a manifest template",
			Action: func(c *cli.Context) {
				if len(c.Args()) < 2 {
					cli.ShowCommandHelp(c, "merge")
					os.Exit(1)
				}

				merge(c.Args()[0], c.Args()[1:])
			},
		},
		{
			Name:      "diff",
			ShortName: "d",
			Usage:     "structurally compare two YAML files",
			Action: func(c *cli.Context) {
				if len(c.Args()) < 2 {
					cli.ShowCommandHelp(c, "diff")
					os.Exit(1)
				}

				diff(c.Args()[0], c.Args()[1])
			},
		},
	}

	app.Run(os.Args)
}

func merge(templateFilePath string, stubFilePaths []string) {
	templateFile, err := ioutil.ReadFile(templateFilePath)
	if err != nil {
		log.Fatalln("error reading template:", err)
	}

	templateYAML, err := yaml.Parse(templateFile)
	if err != nil {
		log.Fatalln("error parsing template:", err)
	}

	stubs := []yaml.Node{}

	for _, stubFilePath := range stubFilePaths {
		stubFile, err := ioutil.ReadFile(stubFilePath)
		if err != nil {
			log.Fatalln("error reading stub:", err)
		}

		stubYAML, err := yaml.Parse(stubFile)
		if err != nil {
			log.Fatalln("error parsing stub:", err)
		}

		stubs = append(stubs, stubYAML)
	}

	flowed, err := flow.Flow(templateYAML, stubs...)
	if err != nil {
		log.Fatalln("error generating manifest:", err)
	}

	yaml, err := goyaml.Marshal(flowed)
	if err != nil {
		log.Fatalln("error marshalling manifest:", err)
	}

	fmt.Println(string(yaml))
}

func diff(aFilePath, bFilePath string) {
	aFile, err := ioutil.ReadFile(aFilePath)
	if err != nil {
		log.Fatalln("error reading a:", err)
	}

	aYAML, err := yaml.Parse(aFile)
	if err != nil {
		log.Fatalln("error parsing a:", err)
	}

	bFile, err := ioutil.ReadFile(bFilePath)
	if err != nil {
		log.Fatalln("error reading b:", err)
	}

	bYAML, err := yaml.Parse(bFile)
	if err != nil {
		log.Fatalln("error parsing b:", err)
	}

	diffs := compare.Compare(aYAML, bYAML)

	if len(diffs) == 0 {
		fmt.Println("no differences!")
		return
	}

	for _, diff := range diffs {
		fmt.Println("Difference in", strings.Join(diff.Path, "."))

		if diff.A != nil {
			ayaml, err := goyaml.Marshal(diff.A)
			if err != nil {
				panic(err)
			}

			fmt.Printf("  %s has:\n    \x1b[31m%s\x1b[0m\n", aFilePath, strings.Replace(string(ayaml), "\n", "\n    ", -1))
		}

		if diff.B != nil {
			byaml, err := goyaml.Marshal(diff.B)
			if err != nil {
				panic(err)
			}

			fmt.Printf("  %s has:\n    \x1b[32m%s\x1b[0m\n", bFilePath, strings.Replace(string(byaml), "\n", "\n    ", -1))
		}
	}
}
<|endoftext|>


<commit_before>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"

	log "github.com/Sirupsen/logrus"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"

	"github.com/emccode/rexray/core/errors"
	"github.com/emccode/rexray/util"
)

var (
	envVarRx *regexp.Regexp
)

func init() {
	envVarRx = regexp.MustCompile(`^\s*([^#=]+)=(.+)$`)
	loadEtcEnvironment()
	initConfigKeyMap()
}

// JSONMarshalStrategy is a JSON marshalling strategy
type JSONMarshalStrategy int

const (
	// JSONMarshalSecure indicates that the secure fields should be omitted
	JSONMarshalSecure JSONMarshalStrategy = iota

	// JSONMarshalPlainText indicates that all fields should be included
	JSONMarshalPlainText
)

type secureConfig struct {
	LogLevel         string
	StorageDrivers   []string
	VolumeDrivers    []string
	OSDrivers        []string
	MinVolSize       int
	RemoteManagement bool

	DockerVolumeType       string
	DockerIOPS             int
	DockerSize             int
	DockerAvailabilityZone string

	AwsAccessKey string
	AwsRegion    string

	RackspaceAuthURL    string
	RackspaceUserID     string
	RackspaceUserName   string
	RackspaceTenantID   string
	RackspaceTenantName string
	RackspaceDomainID   string
	RackspaceDomainName string

	OpenstackAuthURL              string
	OpenstackUserID               string
	OpenstackUserName             string
	OpenstackTenantID             string
	OpenstackTenantName           string
	OpenstackDomainID             string
	OpenstackDomainName           string
	OpenstackRegionName           string
	OpenstackAvailabilityZoneName string

	ScaleIOEndpoint             string
	ScaleIOInsecure             bool
	ScaleIOUseCerts             bool
	ScaleIOUserName             string
	ScaleIOSystemID             string
	ScaleIOSystemName           string
	ScaleIOProtectionDomainID   string
	ScaleIOProtectionDomainName string
	ScaleIOStoragePoolID        string
	ScaleIOStoragePoolName      string

	XtremIOEndpoint         string
	XtremIOUserName         string
	XtremIOInsecure         bool
	XtremIODeviceMapper     bool
	XtremIOMultipath        bool
	XtremIORemoteManagement bool
}

type plainTextConfig struct {
	AwsSecretKey      string
	RackspacePassword string
	OpenstackPassword string
	ScaleIoPassword   string
	XtremIoPassword   string
}

// Config contains the configuration information
type Config struct {
	secureConfig
	plainTextConfig

	GlobalFlags     *flag.FlagSet `json:"-"`
	AdditionalFlags *flag.FlagSet `json:"-"`
	Viper           *viper.Viper  `json:"-"`
	Host            string        `json:"-"`

	jsonMarshalStrategy JSONMarshalStrategy
}

// New initializes a new instance of a Config struct
func New() *Config {
	return NewConfig(true, true, "config", "yml")
}

// NewConfig initialies a new instance of a Config object with the specified
// options.
func NewConfig(
	loadGlobalConfig, loadUserConfig bool,
	configName, configType string) *Config {

	log.Debug("initializing configuration")

	c := &Config{
		secureConfig:        secureConfig{},
		plainTextConfig:     plainTextConfig{},
		Viper:               viper.New(),
		GlobalFlags:         &flag.FlagSet{},
		AdditionalFlags:     &flag.FlagSet{},
		jsonMarshalStrategy: JSONMarshalSecure,
	}
	c.Viper.SetTypeByDefaultValue(true)
	c.Viper.SetConfigName(configName)
	c.Viper.SetConfigType(configType)

	cfgFile := fmt.Sprintf("%s.%s", configName, configType)
	etcRexRayFile := util.EtcFilePath(cfgFile)
	usrRexRayFile := fmt.Sprintf("%s/.rexray/%s", util.HomeDir(), cfgFile)

	if loadGlobalConfig && util.FileExists(etcRexRayFile) {
		log.WithField("path", etcRexRayFile).Debug("loading global config file")
		if err := c.ReadConfigFile(etcRexRayFile); err != nil {
			log.WithFields(log.Fields{
				"path":  etcRexRayFile,
				"error": err}).Error(
				"error reading global config file")
		}
	}

	if loadUserConfig && util.FileExists(usrRexRayFile) {
		log.WithField("path", usrRexRayFile).Debug("loading user config file")
		if err := c.ReadConfigFile(usrRexRayFile); err != nil {
			log.WithFields(log.Fields{
				"path":  usrRexRayFile,
				"error": err}).Error(
				"error reading user config file")
		}
	}

	c.initConfigKeys()

	return c

}

// JSONMarshalStrategy gets the JSON marshalling strategy
func (c *Config) JSONMarshalStrategy() JSONMarshalStrategy {
	return c.jsonMarshalStrategy
}

// SetJSONMarshalStrategy sets the JSON marshalling strategy
func (c *Config) SetJSONMarshalStrategy(s JSONMarshalStrategy) {
	c.jsonMarshalStrategy = s
}

// Copy creates a copy of this Config instance
func (c *Config) Copy() (*Config, error) {
	newC := New()
	c.Viper.Unmarshal(&newC.plainTextConfig)
	c.Viper.Unmarshal(&newC.secureConfig)
	return newC, nil
}

// FromJSON initializes a new Config instance from a JSON string
func FromJSON(from string) (*Config, error) {
	c := New()
	if err := json.Unmarshal([]byte(from), c); err != nil {
		return nil, err
	}
	c.sync()
	return c, nil
}

// ToJSON exports this Config instance to a JSON string
func (c *Config) ToJSON() (string, error) {
	buf, _ := c.marshalJSON(JSONMarshalPlainText)
	return string(buf), nil
}

// ToSecureJSON exports this Config instance to a JSON string omitting any of
// the secure fields
func (c *Config) ToSecureJSON() (string, error) {
	buf, _ := c.marshalJSON(JSONMarshalSecure)
	return string(buf), nil
}

// MarshalJSON implements the encoding/json.Marshaller interface. It allows
// this type to provide its own marshalling routine.
func (c *Config) MarshalJSON() ([]byte, error) {
	return c.marshalJSON(c.jsonMarshalStrategy)
}

func (c *Config) marshalJSON(s JSONMarshalStrategy) ([]byte, error) {
	switch s {
	case JSONMarshalPlainText:
		return json.MarshalIndent(c.plainTextConfig, "", "  ")
	default:
		return json.MarshalIndent(c.secureConfig, "", "  ")
	}
}

// ReadConfig reads a configuration stream into the current config instance
func (c *Config) ReadConfig(in io.Reader) error {

	if in == nil {
		return errors.New("config reader is nil")
	}

	c.Viper.ReadConfigNoNil(in)
	c.Viper.Unmarshal(&c.secureConfig)
	c.Viper.Unmarshal(&c.plainTextConfig)

	for key := range keys {
		c.updateFlag(key, c.GlobalFlags)
		c.updateFlag(key, c.AdditionalFlags)
	}

	return nil
}

// ReadConfigFile reads a configuration files into the current config instance
func (c *Config) ReadConfigFile(filePath string) error {
	buf, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	return c.ReadConfig(bytes.NewBuffer(buf))
}

func (c *Config) updateFlag(name string, flags *flag.FlagSet) {
	if f := flags.Lookup(name); f != nil {
		val := c.Viper.Get(name)
		strVal := fmt.Sprintf("%v", val)
		f.DefValue = strVal
	}
}

// EnvVars returns an array of the initialized configuration keys as key=value
// strings where the key is configuration key's environment variable key and
// the value is the current value for that key.
func (c *Config) EnvVars() []string {
	evArr := make([]string, len(keys))
	for k, v := range keys {
		evArr = append(evArr,
			fmt.Sprintf("%s=%s", v.EnvVar, c.Viper.GetString(k)))
	}
	return evArr
}

func (c *Config) sync() {

	w := c.Viper.Set

	w(Host, c.Host)
	w(LogLevel, c.LogLevel)
	w(StorageDrivers, c.StorageDrivers)
	w(VolumeDrivers, c.VolumeDrivers)
	w(OSDrivers, c.OSDrivers)
	w(MinVolSize, c.MinVolSize)
	w(RemoteManagement, c.RemoteManagement)

	w(DockerVolumeType, c.DockerVolumeType)
	w(DockerIOPS, c.DockerIOPS)
	w(DockerSize, c.DockerSize)
	w(DockerAvailabilityZone, c.DockerAvailabilityZone)
	w(AwsAccessKey, c.AwsAccessKey)
	w(AwsSecretKey, c.AwsSecretKey)
	w(AwsRegion, c.AwsRegion)

	w(RackspaceAuthURL, c.RackspaceAuthURL)
	w(RackspaceUserID, c.RackspaceUserID)
	w(RackspaceUserName, c.RackspaceUserName)
	w(RackspacePassword, c.RackspacePassword)
	w(RackspaceTenantID, c.RackspaceTenantID)
	w(RackspaceTenantName, c.RackspaceTenantName)
	w(RackspaceDomainID, c.RackspaceDomainID)
	w(RackspaceDomainName, c.RackspaceDomainName)

	w(OpenstackAuthURL, c.OpenstackAuthURL)
	w(OpenstackUserID, c.OpenstackUserID)
	w(OpenstackUserName, c.OpenstackUserName)
	w(OpenstackPassword, c.OpenstackPassword)
	w(OpenstackTenantID, c.OpenstackTenantID)
	w(OpenstackTenantName, c.OpenstackTenantName)
	w(OpenstackDomainID, c.OpenstackDomainID)
	w(OpenstackDomainName, c.OpenstackDomainName)
	w(OpenstackRegionName, c.OpenstackRegionName)
	w(OpenstackAvailabilityZoneName, c.OpenstackAvailabilityZoneName)

	w(ScaleIOEndpoint, c.ScaleIOEndpoint)
	w(ScaleIOInsecure, c.ScaleIOInsecure)
	w(ScaleIOUseCerts, c.ScaleIOUseCerts)
	w(ScaleIOUserName, c.ScaleIOUserName)
	w(ScaleIOPassword, c.ScaleIoPassword)
	w(ScaleIOSystemID, c.ScaleIOSystemID)
	w(ScaleIOSystemName, c.ScaleIOSystemName)
	w(ScaleIOProtectionDomainID, c.ScaleIOProtectionDomainID)
	w(ScaleIOProtectionDomainName, c.ScaleIOProtectionDomainName)
	w(ScaleIOStoragePoolID, c.ScaleIOStoragePoolID)
	w(ScaleIOStoragePoolName, c.ScaleIOStoragePoolName)

	w(XtremIOEndpoint, c.XtremIOEndpoint)
	w(XtremIOUserName, c.XtremIOUserName)
	w(XtremIOPassword, c.XtremIoPassword)
	w(XtremIOInsecure, c.XtremIOInsecure)
	w(XtremIODeviceMapper, c.XtremIODeviceMapper)
	w(XtremIOMultipath, c.XtremIOMultipath)
	w(XtremIORemoteManagement, c.XtremIORemoteManagement)
}

func loadEtcEnvironment() {
	lr := util.LineReader("/etc/environment")
	if lr == nil {
		return
	}
	for l := range lr {
		m := envVarRx.FindStringSubmatch(l)
		if m == nil || len(m) < 3 || os.Getenv(m[1]) != "" {
			continue
		}
		os.Setenv(m[1], m[2])
	}
}
<commit_msg>Bugfix for Config.ToJSON getting just private info<commit_after>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"

	log "github.com/Sirupsen/logrus"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"

	"github.com/emccode/rexray/core/errors"
	"github.com/emccode/rexray/util"
)

var (
	envVarRx *regexp.Regexp
)

func init() {
	envVarRx = regexp.MustCompile(`^\s*([^#=]+)=(.+)$`)
	loadEtcEnvironment()
	initConfigKeyMap()
}

// JSONMarshalStrategy is a JSON marshalling strategy
type JSONMarshalStrategy int

const (
	// JSONMarshalSecure indicates that the secure fields should be omitted
	JSONMarshalSecure JSONMarshalStrategy = iota

	// JSONMarshalPlainText indicates that all fields should be included
	JSONMarshalPlainText
)

type secureConfig struct {
	LogLevel         string
	StorageDrivers   []string
	VolumeDrivers    []string
	OSDrivers        []string
	MinVolSize       int
	RemoteManagement bool

	DockerVolumeType       string
	DockerIOPS             int
	DockerSize             int
	DockerAvailabilityZone string

	AwsAccessKey string
	AwsRegion    string

	RackspaceAuthURL    string
	RackspaceUserID     string
	RackspaceUserName   string
	RackspaceTenantID   string
	RackspaceTenantName string
	RackspaceDomainID   string
	RackspaceDomainName string

	OpenstackAuthURL              string
	OpenstackUserID               string
	OpenstackUserName             string
	OpenstackTenantID             string
	OpenstackTenantName           string
	OpenstackDomainID             string
	OpenstackDomainName           string
	OpenstackRegionName           string
	OpenstackAvailabilityZoneName string

	ScaleIOEndpoint             string
	ScaleIOInsecure             bool
	ScaleIOUseCerts             bool
	ScaleIOUserName             string
	ScaleIOSystemID             string
	ScaleIOSystemName           string
	ScaleIOProtectionDomainID   string
	ScaleIOProtectionDomainName string
	ScaleIOStoragePoolID        string
	ScaleIOStoragePoolName      string

	XtremIOEndpoint         string
	XtremIOUserName         string
	XtremIOInsecure         bool
	XtremIODeviceMapper     bool
	XtremIOMultipath        bool
	XtremIORemoteManagement bool
}

type plainTextConfig struct {
	AwsSecretKey      string
	RackspacePassword string
	OpenstackPassword string
	ScaleIoPassword   string
	XtremIoPassword   string
}

// Config contains the configuration information
type Config struct {
	secureConfig
	plainTextConfig

	GlobalFlags     *flag.FlagSet `json:"-"`
	AdditionalFlags *flag.FlagSet `json:"-"`
	Viper           *viper.Viper  `json:"-"`
	Host            string        `json:"-"`

	jsonMarshalStrategy JSONMarshalStrategy
}

// New initializes a new instance of a Config struct
func New() *Config {
	return NewConfig(true, true, "config", "yml")
}

// NewConfig initialies a new instance of a Config object with the specified
// options.
func NewConfig(
	loadGlobalConfig, loadUserConfig bool,
	configName, configType string) *Config {

	log.Debug("initializing configuration")

	c := &Config{
		secureConfig:        secureConfig{},
		plainTextConfig:     plainTextConfig{},
		Viper:               viper.New(),
		GlobalFlags:         &flag.FlagSet{},
		AdditionalFlags:     &flag.FlagSet{},
		jsonMarshalStrategy: JSONMarshalSecure,
	}
	c.Viper.SetTypeByDefaultValue(true)
	c.Viper.SetConfigName(configName)
	c.Viper.SetConfigType(configType)

	cfgFile := fmt.Sprintf("%s.%s", configName, configType)
	etcRexRayFile := util.EtcFilePath(cfgFile)
	usrRexRayFile := fmt.Sprintf("%s/.rexray/%s", util.HomeDir(), cfgFile)

	if loadGlobalConfig && util.FileExists(etcRexRayFile) {
		log.WithField("path", etcRexRayFile).Debug("loading global config file")
		if err := c.ReadConfigFile(etcRexRayFile); err != nil {
			log.WithFields(log.Fields{
				"path":  etcRexRayFile,
				"error": err}).Error(
				"error reading global config file")
		}
	}

	if loadUserConfig && util.FileExists(usrRexRayFile) {
		log.WithField("path", usrRexRayFile).Debug("loading user config file")
		if err := c.ReadConfigFile(usrRexRayFile); err != nil {
			log.WithFields(log.Fields{
				"path":  usrRexRayFile,
				"error": err}).Error(
				"error reading user config file")
		}
	}

	c.initConfigKeys()

	return c

}

// JSONMarshalStrategy gets the JSON marshalling strategy
func (c *Config) JSONMarshalStrategy() JSONMarshalStrategy {
	return c.jsonMarshalStrategy
}

// SetJSONMarshalStrategy sets the JSON marshalling strategy
func (c *Config) SetJSONMarshalStrategy(s JSONMarshalStrategy) {
	c.jsonMarshalStrategy = s
}

// Copy creates a copy of this Config instance
func (c *Config) Copy() (*Config, error) {
	newC := New()
	c.Viper.Unmarshal(&newC.plainTextConfig)
	c.Viper.Unmarshal(&newC.secureConfig)
	return newC, nil
}

// FromJSON initializes a new Config instance from a JSON string
func FromJSON(from string) (*Config, error) {
	c := New()
	if err := json.Unmarshal([]byte(from), c); err != nil {
		return nil, err
	}
	c.sync()
	return c, nil
}

// ToJSON exports this Config instance to a JSON string
func (c *Config) ToJSON() (string, error) {
	buf, _ := c.marshalJSON(JSONMarshalPlainText)
	return string(buf), nil
}

// ToSecureJSON exports this Config instance to a JSON string omitting any of
// the secure fields
func (c *Config) ToSecureJSON() (string, error) {
	buf, _ := c.marshalJSON(JSONMarshalSecure)
	return string(buf), nil
}

// MarshalJSON implements the encoding/json.Marshaller interface. It allows
// this type to provide its own marshalling routine.
func (c *Config) MarshalJSON() ([]byte, error) {
	return c.marshalJSON(c.jsonMarshalStrategy)
}

func (c *Config) marshalJSON(s JSONMarshalStrategy) ([]byte, error) {
	switch s {
	case JSONMarshalPlainText:
		s := struct {
			plainTextConfig
			secureConfig
		}{
			c.plainTextConfig,
			c.secureConfig,
		}
		return json.MarshalIndent(s, "", "  ")
	default:
		return json.MarshalIndent(c.secureConfig, "", "  ")
	}
}

// ReadConfig reads a configuration stream into the current config instance
func (c *Config) ReadConfig(in io.Reader) error {

	if in == nil {
		return errors.New("config reader is nil")
	}

	c.Viper.ReadConfigNoNil(in)
	c.Viper.Unmarshal(&c.secureConfig)
	c.Viper.Unmarshal(&c.plainTextConfig)

	for key := range keys {
		c.updateFlag(key, c.GlobalFlags)
		c.updateFlag(key, c.AdditionalFlags)
	}

	return nil
}

// ReadConfigFile reads a configuration files into the current config instance
func (c *Config) ReadConfigFile(filePath string) error {
	buf, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	return c.ReadConfig(bytes.NewBuffer(buf))
}

func (c *Config) updateFlag(name string, flags *flag.FlagSet) {
	if f := flags.Lookup(name); f != nil {
		val := c.Viper.Get(name)
		strVal := fmt.Sprintf("%v", val)
		f.DefValue = strVal
	}
}

// EnvVars returns an array of the initialized configuration keys as key=value
// strings where the key is configuration key's environment variable key and
// the value is the current value for that key.
func (c *Config) EnvVars() []string {
	evArr := make([]string, len(keys))
	for k, v := range keys {
		evArr = append(evArr,
			fmt.Sprintf("%s=%s", v.EnvVar, c.Viper.GetString(k)))
	}
	return evArr
}

func (c *Config) sync() {

	w := c.Viper.Set

	w(Host, c.Host)
	w(LogLevel, c.LogLevel)
	w(StorageDrivers, c.StorageDrivers)
	w(VolumeDrivers, c.VolumeDrivers)
	w(OSDrivers, c.OSDrivers)
	w(MinVolSize, c.MinVolSize)
	w(RemoteManagement, c.RemoteManagement)

	w(DockerVolumeType, c.DockerVolumeType)
	w(DockerIOPS, c.DockerIOPS)
	w(DockerSize, c.DockerSize)
	w(DockerAvailabilityZone, c.DockerAvailabilityZone)
	w(AwsAccessKey, c.AwsAccessKey)
	w(AwsSecretKey, c.AwsSecretKey)
	w(AwsRegion, c.AwsRegion)

	w(RackspaceAuthURL, c.RackspaceAuthURL)
	w(RackspaceUserID, c.RackspaceUserID)
	w(RackspaceUserName, c.RackspaceUserName)
	w(RackspacePassword, c.RackspacePassword)
	w(RackspaceTenantID, c.RackspaceTenantID)
	w(RackspaceTenantName, c.RackspaceTenantName)
	w(RackspaceDomainID, c.RackspaceDomainID)
	w(RackspaceDomainName, c.RackspaceDomainName)

	w(OpenstackAuthURL, c.OpenstackAuthURL)
	w(OpenstackUserID, c.OpenstackUserID)
	w(OpenstackUserName, c.OpenstackUserName)
	w(OpenstackPassword, c.OpenstackPassword)
	w(OpenstackTenantID, c.OpenstackTenantID)
	w(OpenstackTenantName, c.OpenstackTenantName)
	w(OpenstackDomainID, c.OpenstackDomainID)
	w(OpenstackDomainName, c.OpenstackDomainName)
	w(OpenstackRegionName, c.OpenstackRegionName)
	w(OpenstackAvailabilityZoneName, c.OpenstackAvailabilityZoneName)

	w(ScaleIOEndpoint, c.ScaleIOEndpoint)
	w(ScaleIOInsecure, c.ScaleIOInsecure)
	w(ScaleIOUseCerts, c.ScaleIOUseCerts)
	w(ScaleIOUserName, c.ScaleIOUserName)
	w(ScaleIOPassword, c.ScaleIoPassword)
	w(ScaleIOSystemID, c.ScaleIOSystemID)
	w(ScaleIOSystemName, c.ScaleIOSystemName)
	w(ScaleIOProtectionDomainID, c.ScaleIOProtectionDomainID)
	w(ScaleIOProtectionDomainName, c.ScaleIOProtectionDomainName)
	w(ScaleIOStoragePoolID, c.ScaleIOStoragePoolID)
	w(ScaleIOStoragePoolName, c.ScaleIOStoragePoolName)

	w(XtremIOEndpoint, c.XtremIOEndpoint)
	w(XtremIOUserName, c.XtremIOUserName)
	w(XtremIOPassword, c.XtremIoPassword)
	w(XtremIOInsecure, c.XtremIOInsecure)
	w(XtremIODeviceMapper, c.XtremIODeviceMapper)
	w(XtremIOMultipath, c.XtremIOMultipath)
	w(XtremIORemoteManagement, c.XtremIORemoteManagement)
}

func loadEtcEnvironment() {
	lr := util.LineReader("/etc/environment")
	if lr == nil {
		return
	}
	for l := range lr {
		m := envVarRx.FindStringSubmatch(l)
		if m == nil || len(m) < 3 || os.Getenv(m[1]) != "" {
			continue
		}
		os.Setenv(m[1], m[2])
	}
}
<|endoftext|>


<commit_before>package bazooka

func CopyMap(source map[string][]string) map[string][]string {
	dst := make(map[string][]string)
	for k, v := range source {
		dst[k] = v
	}
	return dst
}
<commit_msg>Remove unused file<commit_after><|endoftext|>


<commit_before>package event

import (
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
)

// EvtPeerConnectednessChange should be emitted every time we form a connection with a peer or drop our last
// connection with the peer. Essentially, it is emitted in two cases:
// a) We form a/any connection with a peer.
// b) We go from having a connection/s with a peer to having no connection with the peer.
// It contains the Id of the remote peer and the new connectedness state.
type EvtPeerConnectednessChange struct {
	RemotePeerId  peer.ID
	Connectedness network.Connectedness
}
<commit_msg>changes as per raul's review<commit_after>package event

import (
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
)

// EvtPeerConnectednessChanged should be emitted every time we form a connection with a peer or drop our last
// connection with the peer. Essentially, it is emitted in two cases:
// a) We form a/any connection with a peer.
// b) We go from having a connection/s with a peer to having no connection with the peer.
// It contains the Id of the remote peer and the new connectedness state.
type EvtPeerConnectednessChanged struct {
	Peer          peer.ID
	Connectedness network.Connectedness
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/wayf-dk/pkcs11"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

type Hsm struct {
	session pkcs11.SessionHandle
	used    int
	started time.Time
	sessno  int
}

type aclmap struct {
	handle       pkcs11.ObjectHandle
	sharedsecret string
	label        string
}

var currentsessions int
var hsm1 Hsm
var sem chan Hsm
var pguard sync.Mutex
var p *pkcs11.Ctx
var config = map[string]string{
	"GOELEVEN_HSMLIB":        "",
	"GOELEVEN_INTERFACE":     "localhost:8080",
	"GOELEVEN_ALLOWEDIP":     "127.0.0.1",
	"GOELEVEN_SLOT":          "",
	"GOELEVEN_SLOT_PASSWORD": "",
	"GOELEVEN_KEY_LABEL":     "",
	"GOELEVEN_MINSESSIONS":   "1",
	"GOELEVEN_MAXSESSIONS":   "1",
	"GOELEVEN_MAXSESSIONAGE": "1000000",
	"GOELEVEN_MECH":          "CKM_RSA_PKCS",
	"GOELEVEN_DEBUG":         "false",
	"SOFTHSM_CONF":           "softhsm.conf",
	"GOELEVEN_HTTPS_KEY":     "false",
	"GOELEVEN_HTTPS_CERT":    "false",
}

var keymap map[string]aclmap

var sharedsecretlen = map[string]int{
	"min": 12,
	"max": 32,
}

func main() {
	currentsessions = 0
	keymap = make(map[string]aclmap)
	//wd, _ := os.Getwd()
	initConfig()
	p = pkcs11.New(config["GOELEVEN_HSMLIB"])
	p.Initialize()
	handlesessions()
	http.HandleFunc("/", handler)
	var err error
	if config["GOELEVEN_HTTPS_CERT"] == "false" {
		err = http.ListenAndServe(config["GOELEVEN_INTERFACE"], nil)
	} else {
		err = http.ListenAndServeTLS(config["GOELEVEN_INTERFACE"], config["GOELEVEN_HTTPS_CERT"], config["GOELEVEN_HTTPS_KEY"], nil)
	}
	if err != nil {
		fmt.Printf("main(): %s\n", err)
	}
}

// initConfig read several Environment variables and based on them initialise the configuration
func initConfig() {
	envFiles := []string{"GOELEVEN_HSMLIB"}

	// Load all Environments variables
	for k, _ := range config {
		if os.Getenv(k) != "" {
			config[k] = os.Getenv(k)
		}
	}
	// All variable MUST have a value but we can not verify the variable content
	for k, _ := range config {
		if isdebug() {
			// Don't write PASSWORD to debug
			if k == "GOELEVEN_SLOT_PASSWORD" {
				debug(fmt.Sprintf("%v: xxxxxx\n", k))
			} else {
				debug(fmt.Sprintf("%v: %v\n", k, config[k]))
			}
		}
		if config[k] == "" {
			exit(fmt.Sprintf("Problem with %s", k), 2)
		}
	}

	// Check file exists
	for _, v := range envFiles {
		_, err := os.Stat(config[v])
		if err != nil {
			exit(fmt.Sprintf("%s %s", v, err.Error()), 2)
		}
	}
}

func handlesessions() {
	// String->int64->int convert
	max, _ := strconv.ParseInt(config["GOELEVEN_MAXSESSIONS"], 10, 0)
	var maxsessions int = int(max)
	sem = make(chan Hsm, maxsessions)
	for currentsessions < maxsessions {
		currentsessions++
		sem <- inithsm(currentsessions)
	}

	s := <-sem

	keys := strings.Split(config["GOELEVEN_KEY_LABEL"], ",")

	for _, v := range keys {

		parts := strings.Split(v, ":")
		label := parts[0]
		sharedsecret := parts[1]
        // Test validity of key specific sharedsecret
        if len(sharedsecret) < sharedsecretlen["min"] || len(sharedsecret) > sharedsecretlen["max"] {
            exit(fmt.Sprintf("problem with sharedsecret: '%s' for label: '%s'", sharedsecret, label), 2)
        }

		template := []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_LABEL, label), pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY)}
		if e := p.FindObjectsInit(s.session, template); e != nil {
			panic(fmt.Sprintf("Failed to init: %s\n", e.Error()))
		}
		obj, b, e := p.FindObjects(s.session, 2)

		debug(fmt.Sprintf("Obj %v\n", obj))
		if e != nil {
			exit(fmt.Sprintf("Failed to find: %s %v\n", e.Error(), b), 2)
		}
		if e := p.FindObjectsFinal(s.session); e != nil {
			exit(fmt.Sprintf("Failed to finalize: %s\n", e.Error()), 2)
		}
		debug(fmt.Sprintf("found keys: %v\n", len(obj)))
		if len(obj) == 0 {
			exit(fmt.Sprintf("did not find a key with label '%s'", label), 2)
		}
		keymap[label] = aclmap{obj[0], sharedsecret, label}
	}

	fmt.Printf("hsm initialized new: %#v\n", keymap)

	sem <- s

	debug(fmt.Sprintf("sem: %v\n", len(sem)))
}

// Client authenticate/authorization
func authClient(sharedkey string, slot string, keylabel string, mech string) error {
	//  Check sharedkey
	//  Check slot nummer
	if slot != config["GOELEVEN_SLOT"] {
		return errors.New("Slot number does not match")
	}
	//  Check key aliases/label
	if _, present := keymap[keylabel]; !present {
		return errors.New(fmt.Sprintf("Key label does not match %s", keylabel))
	}

	if sharedkey != keymap[keylabel].sharedsecret {
		return errors.New(fmt.Sprintf("Client secret for label: '%s' does not match", keymap[keylabel].label))
	}

	//  Check key mech
	if mech != config["GOELEVEN_MECH"] {
		return errors.New("Mech does not match")
	}
	// client ok
	return nil
}

// TODO: Cleanup
// TODO: Documentation
// TODO: Error handling
/*
 * If error then send HTTP 500 to client and keep the server running
 *
 */
func handler(w http.ResponseWriter, r *http.Request) {

	fmt.Println("access attempt from:", r.RemoteAddr)
	ips := strings.Split(config["GOELEVEN_ALLOWEDIP"], ",")
	ip := strings.Split(r.RemoteAddr, ":")
	var allowed bool
	for _, v := range ips {
		allowed = allowed || ip[0] == v
	}

	if !allowed {
		fmt.Println("unauthorised access attempt from:", r.RemoteAddr)
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	var err error
	var validPath = regexp.MustCompile("^/(\\d+)/([a-zA-Z0-9\\.]+)/sign$")
	mSlot := validPath.FindStringSubmatch(r.URL.Path)[1]
	mKeyAlias := validPath.FindStringSubmatch(r.URL.Path)[2]

	defer r.Body.Close()
	body, _ := ioutil.ReadAll(r.Body)

	// Parse JSON
	//var b struct { Data,Mech string }
	var b map[string]interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("json.unmarshall: %v\n", err.Error())
		return
	}
	data, err := base64.StdEncoding.DecodeString(b["data"].(string))
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("DecodeString: %v\n", err.Error())
		return
	}

	// Client auth
	err = authClient(b["sharedkey"].(string), mSlot, mKeyAlias, b["mech"].(string))
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("authClient: %v\n", err.Error())
		return
	}

	sig, err, sessno := signing(data, keymap[mKeyAlias].handle)
	if err != nil {
		http.Error(w, "Invalid output", 500)
		fmt.Printf("signing: %v %v\n", err.Error(), sessno)
		return
	}
	sigs := base64.StdEncoding.EncodeToString(sig)
	type Res struct {
		Slot   string `json:"slot"`
		Mech   string `json:"mech"`
		Signed string `json:"signed"`
	}
	res := Res{mSlot, "mech", sigs}
	json, err := json.Marshal(res)
	if err != nil {
		http.Error(w, "Invalid output", 500)
		fmt.Printf("json.marshall: %v\n", err.Error())
		return
	}
	fmt.Fprintf(w, "%s\n\n", json)
}

// TODO: Cleanup
// TODO: Documentation
func inithsm(sessno int) Hsm {
	pguard.Lock()
	defer pguard.Unlock()
	slot, _ := strconv.ParseUint(config["GOELEVEN_SLOT"], 10, 32)

	fmt.Printf("slot: %v\n", slot)
	session, e := p.OpenSession(uint(slot), pkcs11.CKF_SERIAL_SESSION)

	if e != nil {
		panic(fmt.Sprintf("Failed to open session: %s\n", e.Error()))
	}

	p.Login(session, pkcs11.CKU_USER, config["GOELEVEN_SLOT_PASSWORD"])

	return Hsm{session, 0, time.Now(), sessno}
}

// TODO: Cleanup
// TODO: Documentation
func signing(data []byte, key pkcs11.ObjectHandle) ([]byte, error, int) {
	// Pop HSM struct from queue
	s := <-sem
	s.used++
	if s.used > 10000 || time.Now().Sub(s.started) > 1000*time.Second {
		p.Logout(s.session)
		p.CloseSession(s.session)
		//p.Finalize()
		//p.Destroy()
		s = inithsm(s.sessno)
	}
	fmt.Printf("hsm: %v %v\n", s, key)
	//p.SignInit(s.session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil)}, key)
	p.SignInit(s.session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}, key)
	sig, err := p.Sign(s.session, data)
	fmt.Printf("err: %v\n", err)

	// Push HSM struct back on queue
	sem <- s
	return sig, nil, s.sessno
}

// Utils

func debug(messages string) {
	if config["GOELEVEN_DEBUG"] == "true" {
		fmt.Print(messages)
	}
}

// Standard function to test for debug mode
func isdebug() bool {
	if config["GOELEVEN_DEBUG"] == "true" {
		return true
	} else {
		return false
	}
}

func exit(messages string, errorCode int) {
	// Exit code and messages based on Nagios plugin return codes (https://nagios-plugins.org/doc/guidelines.html#AEN78)
	var prefix = map[int]string{0: "OK", 1: "Warning", 2: "Critical", 3: "Unknown"}

	// Catch all unknown errorCode and convert them to Unknown
	if errorCode < 0 || errorCode > 3 {
		errorCode = 3
	}

	fmt.Printf("%s %s\n", prefix[errorCode], messages)
	os.Exit(errorCode)
}
<commit_msg>fixed control of sharedsecret. Added one-line logging.<commit_after>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/wayf-dk/pkcs11"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

type Hsm struct {
	session pkcs11.SessionHandle
	used    int
	started time.Time
	sessno  int
}

type aclmap struct {
	handle       pkcs11.ObjectHandle
	sharedsecret string
	label        string
}

var currentsessions int
var hsm1 Hsm
var sem chan Hsm
var pguard sync.Mutex
var p *pkcs11.Ctx
var config = map[string]string{
	"GOELEVEN_HSMLIB":        "",
	"GOELEVEN_INTERFACE":     "localhost:8080",
	"GOELEVEN_ALLOWEDIP":     "127.0.0.1",
	"GOELEVEN_SLOT":          "",
	"GOELEVEN_SLOT_PASSWORD": "",
	"GOELEVEN_KEY_LABEL":     "",
	"GOELEVEN_MINSESSIONS":   "1",
	"GOELEVEN_MAXSESSIONS":   "1",
	"GOELEVEN_MAXSESSIONAGE": "1000000",
	"GOELEVEN_MECH":          "CKM_RSA_PKCS",
	"GOELEVEN_DEBUG":         "false",
	"SOFTHSM_CONF":           "softhsm.conf",
	"GOELEVEN_HTTPS_KEY":     "false",
	"GOELEVEN_HTTPS_CERT":    "false",
}

var keymap map[string]aclmap

var sharedsecretlen = map[string]int{
	"min": 12,
	"max": 32,
}

func main() {
	currentsessions = 0
	keymap = make(map[string]aclmap)
	//wd, _ := os.Getwd()
	initConfig()
	p = pkcs11.New(config["GOELEVEN_HSMLIB"])
	p.Initialize()
	handlesessions()
	http.HandleFunc("/", handler)
	var err error
	if config["GOELEVEN_HTTPS_CERT"] == "false" {
		err = http.ListenAndServe(config["GOELEVEN_INTERFACE"], nil)
	} else {
		err = http.ListenAndServeTLS(config["GOELEVEN_INTERFACE"], config["GOELEVEN_HTTPS_CERT"], config["GOELEVEN_HTTPS_KEY"], nil)
	}
	if err != nil {
		fmt.Printf("main(): %s\n", err)
	}
}

// initConfig read several Environment variables and based on them initialise the configuration
func initConfig() {
	envFiles := []string{"GOELEVEN_HSMLIB"}

	// Load all Environments variables
	for k, _ := range config {
		if os.Getenv(k) != "" {
			config[k] = os.Getenv(k)
		}
	}
	// All variable MUST have a value but we can not verify the variable content
	for k, _ := range config {
		if isdebug() {
			// Don't write PASSWORD to debug
			if k == "GOELEVEN_SLOT_PASSWORD" {
				debug(fmt.Sprintf("%v: xxxxxx\n", k))
			} else {
				debug(fmt.Sprintf("%v: %v\n", k, config[k]))
			}
		}
		if config[k] == "" {
			exit(fmt.Sprintf("Problem with %s", k), 2)
		}
	}

	// Check file exists
	for _, v := range envFiles {
		_, err := os.Stat(config[v])
		if err != nil {
			exit(fmt.Sprintf("%s %s", v, err.Error()), 2)
		}
	}
}

func handlesessions() {
	// String->int64->int convert
	max, _ := strconv.ParseInt(config["GOELEVEN_MAXSESSIONS"], 10, 0)
	var maxsessions int = int(max)
	sem = make(chan Hsm, maxsessions)
	for currentsessions < maxsessions {
		currentsessions++
		sem <- inithsm(currentsessions)
	}

	s := <-sem

	keys := strings.Split(config["GOELEVEN_KEY_LABEL"], ",")

	for _, v := range keys {

		parts := strings.Split(v, ":")
		label := parts[0]
		sharedsecret := parts[1]
		// Test validity of key specific sharedsecret
		if len(sharedsecret) < sharedsecretlen["min"] || len(sharedsecret) > sharedsecretlen["max"] {
			exit(fmt.Sprintf("problem with sharedsecret: '%s' for label: '%s'", sharedsecret, label), 2)
		}

		template := []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_LABEL, label), pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY)}
		if e := p.FindObjectsInit(s.session, template); e != nil {
			panic(fmt.Sprintf("Failed to init: %s\n", e.Error()))
		}
		obj, b, e := p.FindObjects(s.session, 2)

		debug(fmt.Sprintf("Obj %v\n", obj))
		if e != nil {
			exit(fmt.Sprintf("Failed to find: %s %v\n", e.Error(), b), 2)
		}
		if e := p.FindObjectsFinal(s.session); e != nil {
			exit(fmt.Sprintf("Failed to finalize: %s\n", e.Error()), 2)
		}
		debug(fmt.Sprintf("found keys: %v\n", len(obj)))
		if len(obj) == 0 {
			exit(fmt.Sprintf("did not find a key with label '%s'", label), 2)
		}
		keymap[label] = aclmap{obj[0], sharedsecret, label}
	}

	fmt.Printf("hsm initialized new: %#v\n", keymap)

	sem <- s

	debug(fmt.Sprintf("sem: %v\n", len(sem)))
}

// Client authenticate/authorization
func authClient(sharedkey string, slot string, keylabel string, mech string) error {
	//  Check sharedkey
	//  Check slot nummer
	if slot != config["GOELEVEN_SLOT"] {
		return errors.New("Slot number does not match")
	}
	//  Check key aliases/label
	if _, present := keymap[keylabel]; !present {
		return errors.New(fmt.Sprintf("Key label does not match %s", keylabel))
	}

	if sharedkey != keymap[keylabel].sharedsecret {
		return errors.New(fmt.Sprintf("Client secret for label: '%s' does not match", keymap[keylabel].label))
	}

	//  Check key mech
	if mech != config["GOELEVEN_MECH"] {
		return errors.New("Mech does not match")
	}
	// client ok
	return nil
}

// TODO: Cleanup
// TODO: Documentation
// TODO: Error handling
/*
 * If error then send HTTP 500 to client and keep the server running
 *
 */
func handler(w http.ResponseWriter, r *http.Request) {

	ips := strings.Split(config["GOELEVEN_ALLOWEDIP"], ",")
	ip := strings.Split(r.RemoteAddr, ":")
	var allowed bool
	for _, v := range ips {
		allowed = allowed || ip[0] == v
	}

	if !allowed {
		fmt.Println("unauthorised access attempt from:", r.RemoteAddr)
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	var err error
	var validPath = regexp.MustCompile("^/(\\d+)/([a-zA-Z0-9\\.]+)/sign$")
	mSlot := validPath.FindStringSubmatch(r.URL.Path)[1]
	mKeyAlias := validPath.FindStringSubmatch(r.URL.Path)[2]

	defer r.Body.Close()
	body, _ := ioutil.ReadAll(r.Body)

	// Parse JSON
	//var b struct { Data,Mech string }
	var b map[string]interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("json.unmarshall: %v\n", err.Error())
		return
	}
	data, err := base64.StdEncoding.DecodeString(b["data"].(string))
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("DecodeString: %v\n", err.Error())
		return
	}

	// Client auth
	err = authClient(b["sharedkey"].(string), mSlot, mKeyAlias, b["mech"].(string))
	if err != nil {
		http.Error(w, "Invalid input", 500)
		fmt.Printf("authClient: %v\n", err.Error())
		return
	}

	sig, err, sessno := signing(data, mKeyAlias, r.RemoteAddr)
	if err != nil {
		http.Error(w, "Invalid output", 500)
		fmt.Printf("signing: %v %v\n", err.Error(), sessno)
		return
	}
	sigs := base64.StdEncoding.EncodeToString(sig)
	type Res struct {
		Slot   string `json:"slot"`
		Mech   string `json:"mech"`
		Signed string `json:"signed"`
	}
	res := Res{mSlot, "mech", sigs}
	json, err := json.Marshal(res)
	if err != nil {
		http.Error(w, "Invalid output", 500)
		fmt.Printf("json.marshall: %v\n", err.Error())
		return
	}
	fmt.Fprintf(w, "%s\n\n", json)
}

// TODO: Cleanup
// TODO: Documentation
func inithsm(sessno int) Hsm {
	pguard.Lock()
	defer pguard.Unlock()
	slot, _ := strconv.ParseUint(config["GOELEVEN_SLOT"], 10, 32)

	fmt.Printf("slot: %v\n", slot)
	session, e := p.OpenSession(uint(slot), pkcs11.CKF_SERIAL_SESSION)

	if e != nil {
		panic(fmt.Sprintf("Failed to open session: %s\n", e.Error()))
	}

	p.Login(session, pkcs11.CKU_USER, config["GOELEVEN_SLOT_PASSWORD"])

	return Hsm{session, 0, time.Now(), sessno}
}

// TODO: Cleanup
// TODO: Documentation
func signing(data []byte, key string, remoteip string) ([]byte, error, int) {
	// Pop HSM struct from queue
	s := <-sem
	s.used++
	if s.used > 10000 || time.Now().Sub(s.started) > 1000*time.Second {
		p.Logout(s.session)
		p.CloseSession(s.session)
		//p.Finalize()
		//p.Destroy()
		s = inithsm(s.sessno)
	}
	fmt.Printf("label: %s handle: %d ip: %s\n", keymap[key].label, keymap[key].handle, remoteip)
	p.SignInit(s.session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}, keymap[key].handle)
	sig, err := p.Sign(s.session, data)

	// Push HSM struct back on queue
	sem <- s
	return sig, err, s.sessno
}

// Utils

func debug(messages string) {
	if config["GOELEVEN_DEBUG"] == "true" {
		fmt.Print(messages)
	}
}

// Standard function to test for debug mode
func isdebug() bool {
	if config["GOELEVEN_DEBUG"] == "true" {
		return true
	} else {
		return false
	}
}

func exit(messages string, errorCode int) {
	// Exit code and messages based on Nagios plugin return codes (https://nagios-plugins.org/doc/guidelines.html#AEN78)
	var prefix = map[int]string{0: "OK", 1: "Warning", 2: "Critical", 3: "Unknown"}

	// Catch all unknown errorCode and convert them to Unknown
	if errorCode < 0 || errorCode > 3 {
		errorCode = 3
	}

	fmt.Printf("%s %s\n", prefix[errorCode], messages)
	os.Exit(errorCode)
}
<|endoftext|>


<commit_before>package admin

import (
	"errors"
	"fmt"
	"net/http"

	"github.com/qor/admin"
	"github.com/qor/media_library"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
	"github.com/qor/qor/resource"
	"github.com/qor/sorting"
	"github.com/qor/widget"
)

var Widgets *widget.Widgets

func init() {
	Widgets = widget.New(&widget.Config{DB: db.DB})
	Widgets.RegisterScope(&widget.Scope{
		Name: "From Google",
		Visible: func(context *widget.Context) bool {
			if request, ok := context.Get("Request"); ok {
				_, ok := request.(*http.Request).URL.Query()["from_google"]
				return ok
			}
			return false
		},
	})

	Admin.AddResource(Widgets)

	// Top Banner
	type bannerArgument struct {
		Title           string
		ButtonTitle     string
		Link            string
		BackgroundImage media_library.FileSystem
		Logo            media_library.FileSystem
	}

	Widgets.RegisterWidget(&widget.Widget{
		Name:      "NormalBanner",
		Templates: []string{"banner", "banner2"},
		Setting:   Admin.NewResource(&bannerArgument{}),
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			context.Options["Setting"] = setting
			return context
		},
	})

	type slideImage struct {
		Title string
		Image media_library.FileSystem
	}

	type slideShowArgument struct {
		SlideImages []slideImage
	}
	slideShowResource := Admin.NewResource(&slideShowArgument{})
	slideShowResource.AddValidator(func(value interface{}, metaValues *resource.MetaValues, context *qor.Context) error {
		if slides, ok := value.(*slideShowArgument); ok {
			for _, slide := range slides.SlideImages {
				if slide.Title == "" {
					return errors.New("slide title is blank")
				}
			}
		}
		return nil
	})

	Widgets.RegisterWidget(&widget.Widget{
		Name:      "SlideShow",
		Templates: []string{"slideshow"},
		Setting:   slideShowResource,
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			context.Options["Setting"] = setting
			return context
		},
	})

	Widgets.RegisterWidgetsGroup(&widget.WidgetsGroup{
		Name:    "Banner",
		Widgets: []string{"NormalBanner", "SlideShow"},
	})

	// selected Products
	type selectedProductsArgument struct {
		Products       []string
		ProductsSorter sorting.SortableCollection
	}
	selectedProductsResource := Admin.NewResource(&selectedProductsArgument{})
	selectedProductsResource.Meta(&admin.Meta{Name: "Products", Type: "select_many", Collection: func(value interface{}, context *qor.Context) [][]string {
		var collectionValues [][]string
		var products []*models.Product
		db.DB.Find(&products)
		for _, product := range products {
			collectionValues = append(collectionValues, []string{fmt.Sprintf("%v", product.ID), product.Name})
		}
		return collectionValues
	}})
	Widgets.RegisterWidget(&widget.Widget{
		Name:      "Products",
		Templates: []string{"products"},
		Setting:   selectedProductsResource,
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			if setting != nil {
				var products []*models.Product
				db.DB.Limit(9).Preload("ColorVariations").Preload("ColorVariations.Images").Where("id IN (?)", setting.(*selectedProductsArgument).Products).Find(&products)
				setting.(*selectedProductsArgument).ProductsSorter.Sort(&products)
				context.Options["Products"] = products
			}
			return context
		},
	})
}
<commit_msg>Add processor validataor<commit_after>package admin

import (
	"errors"
	"fmt"
	"net/http"

	"github.com/qor/admin"
	"github.com/qor/media_library"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
	"github.com/qor/qor/resource"
	"github.com/qor/sorting"
	"github.com/qor/widget"
)

var Widgets *widget.Widgets

func init() {
	Widgets = widget.New(&widget.Config{DB: db.DB})
	Widgets.RegisterScope(&widget.Scope{
		Name: "From Google",
		Visible: func(context *widget.Context) bool {
			if request, ok := context.Get("Request"); ok {
				_, ok := request.(*http.Request).URL.Query()["from_google"]
				return ok
			}
			return false
		},
	})

	Admin.AddResource(Widgets)

	// Top Banner
	type bannerArgument struct {
		Title           string
		ButtonTitle     string
		Link            string
		BackgroundImage media_library.FileSystem
		Logo            media_library.FileSystem
	}

	Widgets.RegisterWidget(&widget.Widget{
		Name:      "NormalBanner",
		Templates: []string{"banner", "banner2"},
		Setting:   Admin.NewResource(&bannerArgument{}),
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			context.Options["Setting"] = setting
			return context
		},
	})

	type slideImage struct {
		Title string
		Image media_library.FileSystem
	}

	type slideShowArgument struct {
		SlideImages []slideImage
	}
	slideShowResource := Admin.NewResource(&slideShowArgument{})
	slideShowResource.AddProcessor(func(value interface{}, metaValues *resource.MetaValues, context *qor.Context) error {
		if slides, ok := value.(*slideShowArgument); ok {
			for _, slide := range slides.SlideImages {
				if slide.Title == "" {
					return errors.New("slide title is blank")
				}
			}
		}
		return nil
	})

	Widgets.RegisterWidget(&widget.Widget{
		Name:      "SlideShow",
		Templates: []string{"slideshow"},
		Setting:   slideShowResource,
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			context.Options["Setting"] = setting
			return context
		},
	})

	Widgets.RegisterWidgetsGroup(&widget.WidgetsGroup{
		Name:    "Banner",
		Widgets: []string{"NormalBanner", "SlideShow"},
	})

	// selected Products
	type selectedProductsArgument struct {
		Products       []string
		ProductsSorter sorting.SortableCollection
	}
	selectedProductsResource := Admin.NewResource(&selectedProductsArgument{})
	selectedProductsResource.Meta(&admin.Meta{Name: "Products", Type: "select_many", Collection: func(value interface{}, context *qor.Context) [][]string {
		var collectionValues [][]string
		var products []*models.Product
		db.DB.Find(&products)
		for _, product := range products {
			collectionValues = append(collectionValues, []string{fmt.Sprintf("%v", product.ID), product.Name})
		}
		return collectionValues
	}})
	Widgets.RegisterWidget(&widget.Widget{
		Name:      "Products",
		Templates: []string{"products"},
		Setting:   selectedProductsResource,
		Context: func(context *widget.Context, setting interface{}) *widget.Context {
			if setting != nil {
				var products []*models.Product
				db.DB.Limit(9).Preload("ColorVariations").Preload("ColorVariations.Images").Where("id IN (?)", setting.(*selectedProductsArgument).Products).Find(&products)
				setting.(*selectedProductsArgument).ProductsSorter.Sort(&products)
				context.Options["Products"] = products
			}
			return context
		},
	})
}
<|endoftext|>


<commit_before>/*
** ===============================================
** USER NAME: garlic(QQ:3173413)
** FILE NAME: api_dataservice.go
** DATE TIME: 2017-08-22 13:40:49
** 开放平台财务 API
** ===============================================
 */

package a

import (
	"errors"
	"time"
)

/**
查询对账单下载地址
alipay.data.dataservice.bill.downloadurl.query
为方便商户快速查账，支持商户通过本接口获取商户离线账单下载地址
*/
type alipay_data_dataservice_bill_downloadurl_query struct {
	AlipayApi
}

func (a *alipay_data_dataservice_bill_downloadurl_query) apiMethod() string {
	return "alipay.data.dataservice.bill.downloadurl.query"
}

func (a *alipay_data_dataservice_bill_downloadurl_query) apiName() string {
	return "查询对账单下载地址"
}

type Biz_alipay_data_dataservice_bill_downloadurl_query struct {
	//账单类型，商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型：
	//trade、signcustomer；
	//trade 指商户基于支付宝交易收单的业务账单；
	//signcustomer 是指基于商户支付宝余额收入及支出等资金变动的帐务账单
	BillType string `json:"bill_type,omitempty"`
	//账单时间：日账单格式为yyyy-MM-dd，月账单格式为yyyy-MM。
	BillDate string `json:"bill_date,omitempty"`
}

func (b Biz_alipay_data_dataservice_bill_downloadurl_query) valid() error {
	if len(b.BillType) == 0 {
		return errors.New("bill_type" + CAN_NOT_NIL)
	}

	if b.BillType != "trade" || b.BillType != "signcustomer" {
		return errors.New("bill_type" + FORAMT_ERROR)
	}

	if len(b.BillDate) == 0 {
		return errors.New("bill_date" + CAN_NOT_NIL)
	} else if len(b.BillDate) == 10 {
		//日账单
		if _, err := time.Parse("2006-01-02", b.BillDate); err == nil {
			return errors.New("bill_date" + FORAMT_ERROR)
		}
	} else if len(b.BillDate) == 7 {
		//月账单
		if _, err := time.Parse("2006-01", b.BillDate); err == nil {
			return errors.New("bill_date" + FORAMT_ERROR)
		}
	} else {
		return errors.New("bill_date" + FORAMT_ERROR)
	}

	return nil
}

type Resp_alipay_data_dataservice_bill_downloadurl_query struct {
	Response
	BillDownloadUrl string `json:"bill_download_url,omitempty"` //账单下载地址链接，获取连接后30秒后未下载，链接地址失效。
}

func init() {
	registerApi(new(alipay_data_dataservice_bill_downloadurl_query))
}
<commit_msg>修改对账单一个参数校验<commit_after>/*
** ===============================================
** USER NAME: garlic(QQ:3173413)
** FILE NAME: api_dataservice.go
** DATE TIME: 2017-08-22 13:40:49
** 开放平台财务 API
** ===============================================
 */

package a

import (
	"errors"
	"time"
)

/**
查询对账单下载地址
alipay.data.dataservice.bill.downloadurl.query
为方便商户快速查账，支持商户通过本接口获取商户离线账单下载地址
*/
type alipay_data_dataservice_bill_downloadurl_query struct {
	AlipayApi
}

func (a *alipay_data_dataservice_bill_downloadurl_query) apiMethod() string {
	return "alipay.data.dataservice.bill.downloadurl.query"
}

func (a *alipay_data_dataservice_bill_downloadurl_query) apiName() string {
	return "查询对账单下载地址"
}

type Biz_alipay_data_dataservice_bill_downloadurl_query struct {
	//账单类型，商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型：
	//trade、signcustomer；
	//trade 指商户基于支付宝交易收单的业务账单；
	//signcustomer 是指基于商户支付宝余额收入及支出等资金变动的帐务账单
	BillType string `json:"bill_type,omitempty"`
	//账单时间：日账单格式为yyyy-MM-dd，月账单格式为yyyy-MM。
	BillDate string `json:"bill_date,omitempty"`
}

func (b Biz_alipay_data_dataservice_bill_downloadurl_query) valid() error {
	if len(b.BillType) == 0 {
		return errors.New("bill_type" + CAN_NOT_NIL)
	}
	if b.BillType != "trade" && b.BillType != "signcustomer" {
		return errors.New("bill_type" + FORAMT_ERROR)
	}

	if len(b.BillDate) == 0 {
		return errors.New("bill_date" + CAN_NOT_NIL)
	} else if len(b.BillDate) == 10 {
		//日账单
		if _, err := time.Parse("2006-01-02", b.BillDate); err == nil {
			return errors.New("bill_date" + FORAMT_ERROR)
		}
	} else if len(b.BillDate) == 7 {
		//月账单
		if _, err := time.Parse("2006-01", b.BillDate); err == nil {
			return errors.New("bill_date" + FORAMT_ERROR)
		}
	} else {
		return errors.New("bill_date" + FORAMT_ERROR)
	}

	return nil
}

type Resp_alipay_data_dataservice_bill_downloadurl_query struct {
	Response
	BillDownloadUrl string `json:"bill_download_url,omitempty"` //账单下载地址链接，获取连接后30秒后未下载，链接地址失效。
}

func init() {
	registerApi(new(alipay_data_dataservice_bill_downloadurl_query))
}
<|endoftext|>


<commit_before>/*
 Copyright 2015 Stack Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"github.com/micosa/stack/cli"
	"github.com/spf13/cobra"
	"os"
	"strings"
)

var DispStackTrace bool = true
var ExitOnFailure bool = false
var ExportAll bool = false
var ImportAll bool = false
var StackVersion string = "1.0"
var StackRepo *cli.Repo
var StackLogLevel string = ""

func StackUsage(cmd *cobra.Command, err error) {
	if err != nil {
		sErr := err.(*cli.StackError)
		fmt.Println("Error: ", sErr)
		if DispStackTrace {
			fmt.Printf("%s", sErr.StackTrace)
		}
	}

	if cmd != nil {
		cmd.Usage()
	}
	os.Exit(1)
}

func targetSetCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd,
			cli.NewStackError("Must specify two arguments (sect & k=v) to set"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}
	ar := strings.Split(args[1], "=")

	t.Vars[ar[0]] = ar[1]

	err = t.Save()
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully set %s to %s\n", args[0],
		ar[0], ar[1])
}

func targetShowCmd(cmd *cobra.Command, args []string) {
	dispSect := ""
	if len(args) == 1 {
		dispSect = args[0]
	}

	targets, err := cli.GetTargets(StackRepo)
	if err != nil {
		StackUsage(cmd, err)
	}

	for _, target := range targets {
		if dispSect == "" || dispSect == target.Vars["name"] {
			fmt.Println(target.Vars["name"])
			vars := target.GetVars()
			for k, v := range vars {
				fmt.Printf("	%s: %s\n", k, v)
			}
		}
	}
}

func targetCreateCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd, cli.NewStackError("Wrong number of args to create cmd."))
	}

	fmt.Println("Creating target " + args[0])

	if cli.TargetExists(StackRepo, args[0]) {
		StackUsage(cmd, cli.NewStackError(
			"Target already exists, cannot create target with same name."))
	}

	target := &cli.Target{
		Repo: StackRepo,
		Vars: map[string]string{},
	}
	target.Vars["name"] = args[0]
	target.Vars["arch"] = args[1]

	err := target.Save()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Target %s sucessfully created!\n", args[0])
	}
}

func targetBuildCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.BuildClean(true)
		} else {
			err = t.BuildClean(false)
		}
	} else {
		err = t.Build()
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetTestCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.Test("testclean", true)
		} else {
			err = t.Test("testclean", false)
		}
	} else {
		err = t.Test("test", ExitOnFailure)
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetExportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ExportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to export"))
		}
		targetName = args[0]
	}

	err := cli.ExportTargets(StackRepo, targetName, ExportAll, os.Stdout)
	if err != nil {
		StackUsage(cmd, err)
	}
}

func targetImportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ImportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to import"))
		}

		targetName = args[0]
	}

	err := cli.ImportTargets(StackRepo, targetName, ImportAll, os.Stdin)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Target(s) successfully imported!")
}

func targetAddCmds(base *cobra.Command) {
	targetCmd := &cobra.Command{
		Use:   "target",
		Short: "Set and view target information",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	setCmd := &cobra.Command{
		Use:   "set",
		Short: "Set target configuration variable",
		Run:   targetSetCmd,
	}

	targetCmd.AddCommand(setCmd)

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a target",
		Run:   targetCreateCmd,
	}

	targetCmd.AddCommand(createCmd)

	showCmd := &cobra.Command{
		Use:   "show",
		Short: "View target configuration variables",
		Run:   targetShowCmd,
	}

	targetCmd.AddCommand(showCmd)

	buildCmd := &cobra.Command{
		Use:   "build",
		Short: "Build target",
		Run:   targetBuildCmd,
	}

	targetCmd.AddCommand(buildCmd)

	testCmd := &cobra.Command{
		Use:   "test",
		Short: "Test target",
		Run:   targetTestCmd,
	}

	targetCmd.AddCommand(testCmd)

	exportCmd := &cobra.Command{
		Use:   "export",
		Short: "Export target",
		Run:   targetExportCmd,
	}

	exportCmd.PersistentFlags().BoolVarP(&ExportAll, "export-all", "a", false,
		"If present, export all targets")

	targetCmd.AddCommand(exportCmd)

	importCmd := &cobra.Command{
		Use:   "import",
		Short: "Import target",
		Run:   targetImportCmd,
	}

	importCmd.PersistentFlags().BoolVarP(&ImportAll, "import-all", "a", false,
		"If present, import all targets")

	targetCmd.AddCommand(importCmd)

	base.AddCommand(targetCmd)
}

func repoCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a repo name to create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a repo name to repo create"))
	}

	cwd, err := os.Getwd()
	if err != nil {
		StackUsage(cmd, err)
	}

	_, err = cli.CreateRepo(cwd, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Repo " + args[0] + " successfully created!")
}

func repoAddCmds(baseCmd *cobra.Command) {
	repoCmd := &cobra.Command{
		Use:   "repo",
		Short: "Commands to manipulate the base repository",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a repository",
		Run:   repoCreateCmd,
	}

	repoCmd.AddCommand(createCmd)

	baseCmd.AddCommand(repoCmd)
}

func compilerCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a compiler name to compiler create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a compiler name to compiler create"))
	}

	err := StackRepo.CreateCompiler(args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + args[0] + " successfully created!")
}

func compilerInstallCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Need to specify URL to install compiler "+
			"def from"))
	}

	var name string
	var err error

	if len(args) > 1 {
		name = args[1]
	} else {
		name, err = cli.UrlPath(args[0])
		if err != nil {
			StackUsage(cmd, err)
		}
	}

	dirName := StackRepo.BasePath + "/compiler/" + name + "/"
	if cli.NodeExist(dirName) {
		StackUsage(cmd, cli.NewStackError("Compiler "+name+" already installed."))
	}

	err = cli.CopyUrl(args[0], dirName)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + name + " successfully installed.")
}

func compilerAddCmds(baseCmd *cobra.Command) {
	compilerCmd := &cobra.Command{
		Use:   "compiler",
		Short: "Commands to install and create compiler definitions",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new compiler definition",
		Run:   compilerCreateCmd,
	}

	compilerCmd.AddCommand(createCmd)

	installCmd := &cobra.Command{
		Use:   "install",
		Short: "Install a compiler from the specified URL",
		Run:   compilerInstallCmd,
	}

	compilerCmd.AddCommand(installCmd)

	baseCmd.AddCommand(compilerCmd)
}

func parseCmds() *cobra.Command {
	stackCmd := &cobra.Command{
		Use:   "stack",
		Short: "Stack is a tool to help you compose and build your own OS",
		Long: `Stack allows you to create your own embedded project based on the
		     stack operating system`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	stackCmd.PersistentFlags().StringVarP(&StackLogLevel, "loglevel", "l",
		"WARN", "Log level, defaults to WARN.")

	versCmd := &cobra.Command{
		Use:   "version",
		Short: "Print the stack version number",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Stack version: ", StackVersion)
		},
	}

	stackCmd.AddCommand(versCmd)

	targetAddCmds(stackCmd)
	repoAddCmds(stackCmd)
	compilerAddCmds(stackCmd)

	return stackCmd
}

func main() {
	cmd := parseCmds()
	cmd.Execute()
}
<commit_msg>only display stack trace when -lDEBUG<commit_after>/*
 Copyright 2015 Stack Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"github.com/micosa/stack/cli"
	"github.com/spf13/cobra"
	"log"
	"os"
	"strings"
)

var ExitOnFailure bool = false
var ExportAll bool = false
var ImportAll bool = false
var StackVersion string = "1.0"
var StackRepo *cli.Repo
var StackLogLevel string = ""

func StackUsage(cmd *cobra.Command, err error) {
	if err != nil {
		sErr := err.(*cli.StackError)
		log.Printf("[DEBUG] %s", sErr.StackTrace)

		fmt.Println("Error: ", sErr)
	}

	if cmd != nil {
		cmd.Usage()
	}
	os.Exit(1)
}

func targetSetCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd,
			cli.NewStackError("Must specify two arguments (sect & k=v) to set"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}
	ar := strings.Split(args[1], "=")

	t.Vars[ar[0]] = ar[1]

	err = t.Save()
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully set %s to %s\n", args[0],
		ar[0], ar[1])
}

func targetShowCmd(cmd *cobra.Command, args []string) {
	dispSect := ""
	if len(args) == 1 {
		dispSect = args[0]
	}

	targets, err := cli.GetTargets(StackRepo)
	if err != nil {
		StackUsage(cmd, err)
	}

	for _, target := range targets {
		if dispSect == "" || dispSect == target.Vars["name"] {
			fmt.Println(target.Vars["name"])
			vars := target.GetVars()
			for k, v := range vars {
				fmt.Printf("	%s: %s\n", k, v)
			}
		}
	}
}

func targetCreateCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd, cli.NewStackError("Wrong number of args to create cmd."))
	}

	fmt.Println("Creating target " + args[0])

	if cli.TargetExists(StackRepo, args[0]) {
		StackUsage(cmd, cli.NewStackError(
			"Target already exists, cannot create target with same name."))
	}

	target := &cli.Target{
		Repo: StackRepo,
		Vars: map[string]string{},
	}
	target.Vars["name"] = args[0]
	target.Vars["arch"] = args[1]

	err := target.Save()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Target %s sucessfully created!\n", args[0])
	}
}

func targetBuildCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.BuildClean(true)
		} else {
			err = t.BuildClean(false)
		}
	} else {
		err = t.Build()
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetTestCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.Test("testclean", true)
		} else {
			err = t.Test("testclean", false)
		}
	} else {
		err = t.Test("test", ExitOnFailure)
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetExportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ExportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to export"))
		}
		targetName = args[0]
	}

	err := cli.ExportTargets(StackRepo, targetName, ExportAll, os.Stdout)
	if err != nil {
		StackUsage(cmd, err)
	}
}

func targetImportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ImportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to import"))
		}

		targetName = args[0]
	}

	err := cli.ImportTargets(StackRepo, targetName, ImportAll, os.Stdin)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Target(s) successfully imported!")
}

func targetAddCmds(base *cobra.Command) {
	targetCmd := &cobra.Command{
		Use:   "target",
		Short: "Set and view target information",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	setCmd := &cobra.Command{
		Use:   "set",
		Short: "Set target configuration variable",
		Run:   targetSetCmd,
	}

	targetCmd.AddCommand(setCmd)

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a target",
		Run:   targetCreateCmd,
	}

	targetCmd.AddCommand(createCmd)

	showCmd := &cobra.Command{
		Use:   "show",
		Short: "View target configuration variables",
		Run:   targetShowCmd,
	}

	targetCmd.AddCommand(showCmd)

	buildCmd := &cobra.Command{
		Use:   "build",
		Short: "Build target",
		Run:   targetBuildCmd,
	}

	targetCmd.AddCommand(buildCmd)

	testCmd := &cobra.Command{
		Use:   "test",
		Short: "Test target",
		Run:   targetTestCmd,
	}

	targetCmd.AddCommand(testCmd)

	exportCmd := &cobra.Command{
		Use:   "export",
		Short: "Export target",
		Run:   targetExportCmd,
	}

	exportCmd.PersistentFlags().BoolVarP(&ExportAll, "export-all", "a", false,
		"If present, export all targets")

	targetCmd.AddCommand(exportCmd)

	importCmd := &cobra.Command{
		Use:   "import",
		Short: "Import target",
		Run:   targetImportCmd,
	}

	importCmd.PersistentFlags().BoolVarP(&ImportAll, "import-all", "a", false,
		"If present, import all targets")

	targetCmd.AddCommand(importCmd)

	base.AddCommand(targetCmd)
}

func repoCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a repo name to create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a repo name to repo create"))
	}

	cwd, err := os.Getwd()
	if err != nil {
		StackUsage(cmd, err)
	}

	_, err = cli.CreateRepo(cwd, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Repo " + args[0] + " successfully created!")
}

func repoAddCmds(baseCmd *cobra.Command) {
	repoCmd := &cobra.Command{
		Use:   "repo",
		Short: "Commands to manipulate the base repository",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a repository",
		Run:   repoCreateCmd,
	}

	repoCmd.AddCommand(createCmd)

	baseCmd.AddCommand(repoCmd)
}

func compilerCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a compiler name to compiler create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a compiler name to compiler create"))
	}

	err := StackRepo.CreateCompiler(args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + args[0] + " successfully created!")
}

func compilerInstallCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Need to specify URL to install compiler "+
			"def from"))
	}

	var name string
	var err error

	if len(args) > 1 {
		name = args[1]
	} else {
		name, err = cli.UrlPath(args[0])
		if err != nil {
			StackUsage(cmd, err)
		}
	}

	dirName := StackRepo.BasePath + "/compiler/" + name + "/"
	if cli.NodeExist(dirName) {
		StackUsage(cmd, cli.NewStackError("Compiler "+name+" already installed."))
	}

	err = cli.CopyUrl(args[0], dirName)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + name + " successfully installed.")
}

func compilerAddCmds(baseCmd *cobra.Command) {
	compilerCmd := &cobra.Command{
		Use:   "compiler",
		Short: "Commands to install and create compiler definitions",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new compiler definition",
		Run:   compilerCreateCmd,
	}

	compilerCmd.AddCommand(createCmd)

	installCmd := &cobra.Command{
		Use:   "install",
		Short: "Install a compiler from the specified URL",
		Run:   compilerInstallCmd,
	}

	compilerCmd.AddCommand(installCmd)

	baseCmd.AddCommand(compilerCmd)
}

func parseCmds() *cobra.Command {
	stackCmd := &cobra.Command{
		Use:   "stack",
		Short: "Stack is a tool to help you compose and build your own OS",
		Long: `Stack allows you to create your own embedded project based on the
		     stack operating system`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	stackCmd.PersistentFlags().StringVarP(&StackLogLevel, "loglevel", "l",
		"WARN", "Log level, defaults to WARN.")

	versCmd := &cobra.Command{
		Use:   "version",
		Short: "Print the stack version number",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Stack version: ", StackVersion)
		},
	}

	stackCmd.AddCommand(versCmd)

	targetAddCmds(stackCmd)
	repoAddCmds(stackCmd)
	compilerAddCmds(stackCmd)

	return stackCmd
}

func main() {
	cmd := parseCmds()
	cmd.Execute()
}
<|endoftext|>


<commit_before>package stack

import "net/http"

type chainHandler func(*Context) http.Handler
type chainMiddleware func(*Context, http.Handler) http.Handler

type Chain struct {
	mws     []chainMiddleware
	h       chainHandler
	baseCtx *Context
}

func New(mws ...chainMiddleware) Chain {
	return Chain{mws: mws, baseCtx: NewContext()}
}

func (c Chain) Append(mws ...chainMiddleware) Chain {
	newMws := make([]chainMiddleware, len(c.mws)+len(mws))
	copy(newMws[:len(c.mws)], c.mws)
	copy(newMws[len(c.mws):], mws)
	c.mws = newMws
	return c
}

func (c Chain) Then(chf func(ctx *Context, w http.ResponseWriter, r *http.Request)) HandlerChain {
	c.h = adaptContextHandlerFunc(chf)
	return HandlerChain(c)
}

func (c Chain) ThenHandler(h http.Handler) HandlerChain {
	c.h = adaptHandler(h)
	return HandlerChain(c)
}

func (c Chain) ThenHandlerFunc(fn func(http.ResponseWriter, *http.Request)) HandlerChain {
	c.h = adaptHandlerFunc(fn)
	return HandlerChain(c)
}

type HandlerChain Chain

func (hc HandlerChain) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Always take a copy of baseCtx (i.e. pointing to a brand new memory location)
	ctx := hc.baseCtx.copy()

	final := hc.h(ctx)
	for i := len(hc.mws) - 1; i >= 0; i-- {
		final = hc.mws[i](ctx, final)
	}
	final.ServeHTTP(w, r)
}

func Inject(hc HandlerChain, key string, val interface{}) HandlerChain {
	ctx := hc.baseCtx.copy()
	ctx.Put(key, val)
	hc.baseCtx = ctx
	return hc
}

// Adapt third party middleware with the signature
// func(http.Handler) http.Handler into chainMiddleware
func Adapt(fn func(http.Handler) http.Handler) chainMiddleware {
	return func(ctx *Context, h http.Handler) http.Handler {
		return fn(h)
	}
}

// Adapt http.Handler into a chainHandler
func adaptHandler(h http.Handler) chainHandler {
	return func(ctx *Context) http.Handler {
		return h
	}
}

// Adapt a function with the signature
// func(http.ResponseWriter, *http.Request) into a chainHandler
func adaptHandlerFunc(fn func(w http.ResponseWriter, r *http.Request)) chainHandler {
	return adaptHandler(http.HandlerFunc(fn))
}

// Adapt a function with the signature
// func(Context, http.ResponseWriter, *http.Request) into a chainHandler
func adaptContextHandlerFunc(fn func(ctx *Context, w http.ResponseWriter, r *http.Request)) chainHandler {
	return func(ctx *Context) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fn(ctx, w, r)
		})
	}
}
<commit_msg>Move baseCtx into HandlerChain<commit_after>package stack

import "net/http"

type chainHandler func(*Context) http.Handler
type chainMiddleware func(*Context, http.Handler) http.Handler

type Chain struct {
	mws []chainMiddleware
	h   chainHandler
}

func New(mws ...chainMiddleware) Chain {
	return Chain{mws: mws}
}

func (c Chain) Append(mws ...chainMiddleware) Chain {
	newMws := make([]chainMiddleware, len(c.mws)+len(mws))
	copy(newMws[:len(c.mws)], c.mws)
	copy(newMws[len(c.mws):], mws)
	c.mws = newMws
	return c
}

func (c Chain) Then(chf func(ctx *Context, w http.ResponseWriter, r *http.Request)) HandlerChain {
	c.h = adaptContextHandlerFunc(chf)
	return newHandlerChain(c)
}

func (c Chain) ThenHandler(h http.Handler) HandlerChain {
	c.h = adaptHandler(h)
	return newHandlerChain(c)
}

func (c Chain) ThenHandlerFunc(fn func(http.ResponseWriter, *http.Request)) HandlerChain {
	c.h = adaptHandlerFunc(fn)
	return newHandlerChain(c)
}

type HandlerChain struct {
	baseCtx *Context
	Chain
}

func newHandlerChain(c Chain) HandlerChain {
	return HandlerChain{baseCtx: NewContext(), Chain: c}
}

func (hc HandlerChain) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Always take a copy of baseCtx (i.e. pointing to a brand new memory location)
	ctx := hc.baseCtx.copy()

	final := hc.h(ctx)
	for i := len(hc.mws) - 1; i >= 0; i-- {
		final = hc.mws[i](ctx, final)
	}
	final.ServeHTTP(w, r)
}

func Inject(hc HandlerChain, key string, val interface{}) HandlerChain {
	ctx := hc.baseCtx.copy()
	ctx.Put(key, val)
	hc.baseCtx = ctx
	return hc
}

// Adapt third party middleware with the signature
// func(http.Handler) http.Handler into chainMiddleware
func Adapt(fn func(http.Handler) http.Handler) chainMiddleware {
	return func(ctx *Context, h http.Handler) http.Handler {
		return fn(h)
	}
}

// Adapt http.Handler into a chainHandler
func adaptHandler(h http.Handler) chainHandler {
	return func(ctx *Context) http.Handler {
		return h
	}
}

// Adapt a function with the signature
// func(http.ResponseWriter, *http.Request) into a chainHandler
func adaptHandlerFunc(fn func(w http.ResponseWriter, r *http.Request)) chainHandler {
	return adaptHandler(http.HandlerFunc(fn))
}

// Adapt a function with the signature
// func(Context, http.ResponseWriter, *http.Request) into a chainHandler
func adaptContextHandlerFunc(fn func(ctx *Context, w http.ResponseWriter, r *http.Request)) chainHandler {
	return func(ctx *Context) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fn(ctx, w, r)
		})
	}
}
<|endoftext|>


<commit_before>// platform-independent system statistics things

package main

import (
	"time"
)

type memData struct {
	memTotal    uint64
	memFree     uint64
	memUse      uint64
	memPercent  int
	swapTotal   uint64
	swapFree    uint64
	swapUse     uint64
	swapPercent int
}

type netData struct {
	name    []string
	upacc   []DeltaAcc
	downacc []DeltaAcc
}

func newNetData(ifnum int, depth int) *netData {
	t := new(netData)
	t.name = make([]string, ifnum, ifnum)
	t.upacc = make([]DeltaAcc, ifnum, ifnum)
	t.downacc = make([]DeltaAcc, ifnum, ifnum)

	for i := 0; i < ifnum; i++ {
		t.upacc[i] = *NewDeltaAcc(depth)
		t.downacc[i] = *NewDeltaAcc(depth)
	}
	return t
}

func (nd *netData) Init(depth int, rt time.Duration) error {
	noi, err := getifnum()

	if err != nil {
		return err
	}
	nd = newNetData(noi, depth)
	go func() {
		nd.Update()
		time.Sleep(rt)
	}()
	return nil
}
<commit_msg>Made it so now iterator works<commit_after>// platform-independent system statistics things

package main

import (
	"time"
)

type memData struct {
	memTotal    uint64
	memFree     uint64
	memUse      uint64
	memPercent  int
	swapTotal   uint64
	swapFree    uint64
	swapUse     uint64
	swapPercent int
}

type netData struct {
	name    []string
	upacc   []DeltaAcc
	downacc []DeltaAcc
	done    chan bool
}

func (t *netData) setNetData(ifnum int, depth int) {

	t.name = make([]string, ifnum, ifnum)
	t.upacc = make([]DeltaAcc, ifnum, ifnum)
	t.downacc = make([]DeltaAcc, ifnum, ifnum)
	t.done = make(chan bool, 3)

	for i := 0; i < ifnum; i++ {
		t.upacc[i] = *NewDeltaAcc(depth)
		t.downacc[i] = *NewDeltaAcc(depth)
	}
	return
}

func (nd *netData) Init(depth int, rt time.Duration) error {
	noi, err := getifnum()

	if err != nil {
		return err
	}
	nd.setNetData(noi, depth)
	go func() {
		for {
			select {
			case <-nd.done:
				return
			default:
				nd.Update()
				time.Sleep(rt)
			}
		}
	}()
	return nil
}

func (nd *netData) Close() {
	nd.done <- true
}
<|endoftext|>


<commit_before>package circuitry

import "time"

type circuitState interface {
	BeforeCall() bool
	HandleFailure()
	HandleSuccess()
}

type closedCircuit struct {
	Breaker *CircuitBreaker
}

func (c *closedCircuit) BeforeCall() bool {
	if c.Breaker.FailCounter >= c.Breaker.FailMax {
		c.Breaker.Open()
		return false
	}
	return true
}

func (c *closedCircuit) HandleFailure() {
	c.Breaker.FailCounter++
}

func (c *closedCircuit) HandleSuccess() {
	c.Breaker.FailCounter = 0
}

type openCircuit struct {
	OpenedAt time.Time
	Breaker  *CircuitBreaker
}

func (c *openCircuit) BeforeCall() (b bool) {
	if time.Now().Before(c.OpenedAt.Add(c.Breaker.ResetTimeout)) {
		b = false
	} else {
		c.Breaker.HalfOpen()
		b = true
	}
	return
}

func (c *openCircuit) HandleFailure() {}

func (c *openCircuit) HandleSuccess() {}

type halfopenCircuit struct {
	Breaker *CircuitBreaker
}

func (c *halfopenCircuit) BeforeCall() bool {
	return true
}

func (c *halfopenCircuit) HandleFailure() {
	c.Breaker.FailCounter++
	c.Breaker.Open()
}

func (c *halfopenCircuit) HandleSuccess() {
	c.Breaker.FailCounter = 0
	c.Breaker.Close()
}
<commit_msg>don't export state fields<commit_after>package circuitry

import "time"

type circuitState interface {
	BeforeCall() bool
	HandleFailure()
	HandleSuccess()
}

type closedCircuit struct {
	breaker *CircuitBreaker
}

func (c *closedCircuit) BeforeCall() bool {
	if c.breaker.FailCounter >= c.breaker.FailMax {
		c.breaker.Open()
		return false
	}
	return true
}

func (c *closedCircuit) HandleFailure() {
	c.breaker.FailCounter++
}

func (c *closedCircuit) HandleSuccess() {
	c.breaker.FailCounter = 0
}

type openCircuit struct {
	openedAt time.Time
	breaker  *CircuitBreaker
}

func (c *openCircuit) BeforeCall() (b bool) {
	if time.Now().Before(c.openedAt.Add(c.breaker.ResetTimeout)) {
		b = false
	} else {
		c.breaker.HalfOpen()
		b = true
	}
	return
}

func (c *openCircuit) HandleFailure() {}

func (c *openCircuit) HandleSuccess() {}

type halfopenCircuit struct {
	breaker *CircuitBreaker
}

func (c *halfopenCircuit) BeforeCall() bool {
	return true
}

func (c *halfopenCircuit) HandleFailure() {
	c.breaker.FailCounter++
	c.breaker.Open()
}

func (c *halfopenCircuit) HandleSuccess() {
	c.breaker.FailCounter = 0
	c.breaker.Close()
}
<|endoftext|>