<commit_before>package main

import (
	"os"

	"github.com/subutai-io/base/agent/agent"
	"github.com/subutai-io/base/agent/cli"
	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/log"

	"github.com/codegangsta/cli"
)

var TIMESTAMP string = "-unknown"

func init() {
	os.Setenv("PATH", "/apps/subutai/current/bin:/apps/subutai-mng/current/bin:"+os.Getenv("PATH"))
	if len(os.Args) > 1 {
		if os.Args[1] == "-d" {
			log.Level(log.DebugLevel)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "Subutai"
	app.Version = "v4.0.0-RC6" + TIMESTAMP
	app.Usage = "daemon and command line interface binary"

	app.Flags = []cli.Flag{cli.BoolFlag{
		Name:  "d",
		Usage: "debug mode"}}

	app.Commands = []cli.Command{{
		Name: "attach", Usage: "attach to container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "clear environment"},
			cli.BoolFlag{Name: "x", Usage: "use x86 personality"},
			cli.BoolFlag{Name: "r", Usage: "connect as regular user"}},
		Action: func(c *cli.Context) {
			lib.LxcAttach(c.Args().Get(0), c.Bool("c"), c.Bool("x"), c.Bool("r"))
		}}, {

		Name: "batch", Usage: "batch commands execution",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "json", Usage: "JSON string with commands"}},
		Action: func(c *cli.Context) {
			lib.Batch(c.String("json"))
		}}, {

		Name: "clone", Usage: "clone Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "e", Usage: "set environment id for container"},
			cli.StringFlag{Name: "i", Usage: "set container IP address and VLAN"},
			cli.StringFlag{Name: "t", Usage: "token to verify with MH"}},
		Action: func(c *cli.Context) {
			lib.LxcClone(c.Args().Get(0), c.Args().Get(1), c.String("e"), c.String("i"), c.String("t"))
		}}, {

		Name: "cleanup", Usage: "clean Subutai environment",
		Action: func(c *cli.Context) {
			lib.Cleanup(c.Args().Get(0))
		}}, {

		Name: "collect", Usage: "collect performance stats",
		Action: func(c *cli.Context) {
			lib.CollectStats()
		}}, {

		Name: "config", Usage: "containerName add/del key value",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "o", Usage: "add/del key value"},
			cli.StringFlag{Name: "k", Usage: "add/del key value"},
			cli.StringFlag{Name: "v", Usage: "add/del key value"},
		},
		Action: func(c *cli.Context) {
			lib.LxcConfig(c.Args().Get(0), c.String("o"), c.String("k"), c.String("v"))
		}}, {

		Name: "daemon", Usage: "start an agent",
		Action: func(c *cli.Context) {
			config.InitAgentDebug()
			agent.Start(c)
		},
		Flags: []cli.Flag{
			cli.StringFlag{Name: "server", Value: config.Management.Host, Usage: "management host ip address/host name"},
			cli.StringFlag{Name: "port", Value: config.Management.Port, Usage: "management host port number"},
			cli.StringFlag{Name: "user", Value: config.Agent.GpgUser, Usage: "gpg user name/email to encrypt/decrypt messages"},
			cli.StringFlag{Name: "secret", Value: config.Management.Secret, Usage: "send secret passphrase via flag"},
		}}, {

		Name: "demote", Usage: "demote Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "i", Usage: "network value ie 192.168.1.1/24"},
			cli.StringFlag{Name: "v", Usage: "vlan id"},
		},
		Action: func(c *cli.Context) {
			lib.LxcDemote(c.Args().Get(0), c.String("i"), c.String("v"))
		}}, {

		Name: "destroy", Usage: "destroy Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcDestroy(c.Args().Get(0))
		}}, {

		Name: "export", Usage: "export Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcExport(c.Args().Get(0))
		}}, {

		Name: "import", Usage: "import Subutai template",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"},
			cli.StringFlag{Name: "t", Usage: "token to access kurjun repo"}},
		Action: func(c *cli.Context) {
			lib.LxcImport(c.Args().Get(0), c.String("v"), c.String("t"))
		}}, {

		Name: "list", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "containers only"},
			cli.BoolFlag{Name: "t", Usage: "templates only"},
			cli.BoolFlag{Name: "r", Usage: "registered only"},
			cli.BoolFlag{Name: "i", Usage: "info ???? only"},
			cli.BoolFlag{Name: "a", Usage: "with ancestors"},
			cli.BoolFlag{Name: "f", Usage: "fancy mode"},
			cli.BoolFlag{Name: "p", Usage: "with parent"}},
		Action: func(c *cli.Context) {
			lib.LxcList(c.Args().Get(0), c.Bool("c"), c.Bool("t"), c.Bool("r"), c.Bool("i"), c.Bool("a"), c.Bool("f"), c.Bool("p"))
		}}, {

		Name: "management_network", Usage: "configure management network",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "listtunnel, l", Usage: "-l"},
			cli.StringFlag{Name: "createtunnel, c", Usage: "-c TUNNELPORTNAME TUNNELIPADDRESS TUNNELTYPE"},
			cli.StringFlag{Name: "removetunnel, r", Usage: "-r tunnerPortName"},

			cli.BoolFlag{Name: "listvnimap, v", Usage: "-v"},
			cli.StringFlag{Name: "createvnimap, m", Usage: "-m TUNNELPORTNAME VNI VLANID ENV_ID"},
			cli.StringFlag{Name: "reservvni, E", Usage: "-E vni, vlanid, envid"},
			cli.StringFlag{Name: "removevni, M", Usage: "-M TUNNELPORTNAME VNI VLANID"},

			cli.StringFlag{Name: "deletegateway, D", Usage: "-D VLANID"},
			cli.StringFlag{Name: "creategateway, T", Usage: "-T VLANIP/SUBNET VLANID"},
			cli.StringFlag{Name: "vniop, Z", Usage: "-Z [deleteall] | [list]"}},

		Subcommands: []cli.Command{{
			Name:  "p2p",
			Usage: "p2p network operation",
			Flags: []cli.Flag{
				cli.BoolFlag{Name: "c", Usage: "create p2p instance (p2p -c interfaceName localPeepIPAddr hash key ttl)"},
				cli.BoolFlag{Name: "d", Usage: "delete p2p instance (p2p -d hash)"},
				cli.BoolFlag{Name: "u", Usage: "update p2p instance encryption key (p2p -u hash newkey ttl)"},
				cli.BoolFlag{Name: "l", Usage: "list of p2p instances (p2p -l)"},
				cli.BoolFlag{Name: "p", Usage: "list of p2p participants (p2p -p hash)"}},
			Action: func(c *cli.Context) {
				lib.P2P(c.Bool("c"), c.Bool("d"), c.Bool("u"), c.Bool("l"), c.Bool("p"), os.Args)
			}}},

		Action: func(c *cli.Context) {
			lib.LxcManagementNetwork(os.Args)
		}}, {

		Name: "metrics", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "start time"},
			cli.StringFlag{Name: "e", Usage: "end time"}},
		Action: func(c *cli.Context) {
			lib.HostMetrics(c.Args().Get(0), c.String("s"), c.String("e"))
		}}, {

		Name: "network", Usage: "containerName set/remove/list network vlan id",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "set, s", Usage: "IPADDRESS/NETMASK"},
			cli.StringFlag{Name: "vlan, v", Usage: "vlanid"},
			cli.BoolFlag{Name: "remove, r", Usage: ""},
			cli.BoolFlag{Name: "list, l", Usage: ""},
		},
		Action: func(c *cli.Context) {
			lib.LxcNetwork(c.Args().Get(0), c.String("s"), c.String("vlan"), c.Bool("r"), c.Bool("l"))
		}}, {

		Name: "promote", Usage: "promote Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcPromote(c.Args().Get(0))
		}}, {

		Name: "proxy", Usage: "Subutai reverse proxy",
		Subcommands: []cli.Command{
			{
				Name:     "add",
				Usage:    "add reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.StringFlag{Name: "domain,d", Usage: "add domain to vlan"},
					cli.StringFlag{Name: "host, h", Usage: "add host to domain on vlan"},
					cli.StringFlag{Name: "policy, p", Usage: "set load balance policy (rr|lb|hash)"},
					cli.StringFlag{Name: "file, f", Usage: "specify pem certificate file"}},
				Action: func(c *cli.Context) {
					lib.ProxyAdd(c.Args().Get(0), c.String("d"), c.String("h"), c.String("p"), c.String("f"))
				},
			},
			{
				Name:     "del",
				Usage:    "del reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "delete domain from vlan"},
					cli.StringFlag{Name: "host, h", Usage: "delete host from domain on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyDel(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
			{
				Name:     "check",
				Usage:    "check existing domain or host",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "check domains on vlan"},
					cli.StringFlag{Name: "host, h", Usage: "check hosts on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyCheck(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
		}}, {

		Name: "quota", Usage: "set quotas for Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "set quota for the specified resource type"},
			cli.StringFlag{Name: "m", Usage: "get the maximum quota can be set to the specified container and resource_type in their default units"}},
		Action: func(c *cli.Context) {
			lib.LxcQuota(c.Args().Get(0), c.Args().Get(1), c.String("s"), c.String("m"))
		}}, {

		Name: "rename", Usage: "rename Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRename(c.Args().Get(0), c.Args().Get(1))
		}}, {

		Name: "register", Usage: "register Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRegister(c.Args().Get(0))
		}}, {

		Name: "stats", Usage: "statistics from host",
		Action: func(c *cli.Context) {
			lib.Stats(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "start", Usage: "start Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStart(c.Args().Get(0))
		}}, {

		Name: "stop", Usage: "stop Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStop(c.Args().Get(0))
		}}, {

		Name: "tunnel", Usage: "create SSH tunnel",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "g", Usage: "global accessible tunnel"}},
		Action: func(c *cli.Context) {
			lib.Tunnel(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2), c.Bool("g"))
		}}, {

		Name: "unregister", Usage: "unregister Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcUnregister(c.Args().Get(0))
		}}, {

		Name: "backup", Usage: "backup Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "full", Usage: "make full backup"}},
		Action: func(c *cli.Context) {
			lib.BackupContainer(c.Args().Get(0), c.Bool("full"))
		}}, {

		Name: "restore", Usage: "restore Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "d", Usage: "date of backup snapshot"},
			cli.StringFlag{Name: "c", Usage: "name of new container"}},
		Action: func(c *cli.Context) {
			lib.RestoreContainer(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}},
	}

	app.Run(os.Args)
}
<commit_msg>Root user check added<commit_after>package main

import (
	"os"

	"github.com/subutai-io/base/agent/agent"
	"github.com/subutai-io/base/agent/cli"
	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/log"

	"github.com/codegangsta/cli"
)

var TIMESTAMP string = "-unknown"

func init() {
	if os.Getenv("USER") != "root" {
		log.Error("Please run as root")
	}
	os.Setenv("PATH", "/apps/subutai/current/bin:"+os.Getenv("PATH"))
	if len(os.Args) > 1 {
		if os.Args[1] == "-d" {
			log.Level(log.DebugLevel)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "Subutai"
	app.Version = "v4.0.0-RC6" + TIMESTAMP
	app.Usage = "daemon and command line interface binary"

	app.Flags = []cli.Flag{cli.BoolFlag{
		Name:  "d",
		Usage: "debug mode"}}

	app.Commands = []cli.Command{{
		Name: "attach", Usage: "attach to container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "clear environment"},
			cli.BoolFlag{Name: "x", Usage: "use x86 personality"},
			cli.BoolFlag{Name: "r", Usage: "connect as regular user"}},
		Action: func(c *cli.Context) {
			lib.LxcAttach(c.Args().Get(0), c.Bool("c"), c.Bool("x"), c.Bool("r"))
		}}, {

		Name: "batch", Usage: "batch commands execution",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "json", Usage: "JSON string with commands"}},
		Action: func(c *cli.Context) {
			lib.Batch(c.String("json"))
		}}, {

		Name: "clone", Usage: "clone Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "e", Usage: "set environment id for container"},
			cli.StringFlag{Name: "i", Usage: "set container IP address and VLAN"},
			cli.StringFlag{Name: "t", Usage: "token to verify with MH"}},
		Action: func(c *cli.Context) {
			lib.LxcClone(c.Args().Get(0), c.Args().Get(1), c.String("e"), c.String("i"), c.String("t"))
		}}, {

		Name: "cleanup", Usage: "clean Subutai environment",
		Action: func(c *cli.Context) {
			lib.Cleanup(c.Args().Get(0))
		}}, {

		Name: "collect", Usage: "collect performance stats",
		Action: func(c *cli.Context) {
			lib.CollectStats()
		}}, {

		Name: "config", Usage: "containerName add/del key value",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "o", Usage: "add/del key value"},
			cli.StringFlag{Name: "k", Usage: "add/del key value"},
			cli.StringFlag{Name: "v", Usage: "add/del key value"},
		},
		Action: func(c *cli.Context) {
			lib.LxcConfig(c.Args().Get(0), c.String("o"), c.String("k"), c.String("v"))
		}}, {

		Name: "daemon", Usage: "start an agent",
		Action: func(c *cli.Context) {
			config.InitAgentDebug()
			agent.Start(c)
		},
		Flags: []cli.Flag{
			cli.StringFlag{Name: "server", Value: config.Management.Host, Usage: "management host ip address/host name"},
			cli.StringFlag{Name: "port", Value: config.Management.Port, Usage: "management host port number"},
			cli.StringFlag{Name: "user", Value: config.Agent.GpgUser, Usage: "gpg user name/email to encrypt/decrypt messages"},
			cli.StringFlag{Name: "secret", Value: config.Management.Secret, Usage: "send secret passphrase via flag"},
		}}, {

		Name: "demote", Usage: "demote Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "i", Usage: "network value ie 192.168.1.1/24"},
			cli.StringFlag{Name: "v", Usage: "vlan id"},
		},
		Action: func(c *cli.Context) {
			lib.LxcDemote(c.Args().Get(0), c.String("i"), c.String("v"))
		}}, {

		Name: "destroy", Usage: "destroy Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcDestroy(c.Args().Get(0))
		}}, {

		Name: "export", Usage: "export Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcExport(c.Args().Get(0))
		}}, {

		Name: "import", Usage: "import Subutai template",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"},
			cli.StringFlag{Name: "t", Usage: "token to access kurjun repo"}},
		Action: func(c *cli.Context) {
			lib.LxcImport(c.Args().Get(0), c.String("v"), c.String("t"))
		}}, {

		Name: "list", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "containers only"},
			cli.BoolFlag{Name: "t", Usage: "templates only"},
			cli.BoolFlag{Name: "r", Usage: "registered only"},
			cli.BoolFlag{Name: "i", Usage: "info ???? only"},
			cli.BoolFlag{Name: "a", Usage: "with ancestors"},
			cli.BoolFlag{Name: "f", Usage: "fancy mode"},
			cli.BoolFlag{Name: "p", Usage: "with parent"}},
		Action: func(c *cli.Context) {
			lib.LxcList(c.Args().Get(0), c.Bool("c"), c.Bool("t"), c.Bool("r"), c.Bool("i"), c.Bool("a"), c.Bool("f"), c.Bool("p"))
		}}, {

		Name: "management_network", Usage: "configure management network",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "listtunnel, l", Usage: "-l"},
			cli.StringFlag{Name: "createtunnel, c", Usage: "-c TUNNELPORTNAME TUNNELIPADDRESS TUNNELTYPE"},
			cli.StringFlag{Name: "removetunnel, r", Usage: "-r tunnerPortName"},

			cli.BoolFlag{Name: "listvnimap, v", Usage: "-v"},
			cli.StringFlag{Name: "createvnimap, m", Usage: "-m TUNNELPORTNAME VNI VLANID ENV_ID"},
			cli.StringFlag{Name: "reservvni, E", Usage: "-E vni, vlanid, envid"},
			cli.StringFlag{Name: "removevni, M", Usage: "-M TUNNELPORTNAME VNI VLANID"},

			cli.StringFlag{Name: "deletegateway, D", Usage: "-D VLANID"},
			cli.StringFlag{Name: "creategateway, T", Usage: "-T VLANIP/SUBNET VLANID"},
			cli.StringFlag{Name: "vniop, Z", Usage: "-Z [deleteall] | [list]"}},

		Subcommands: []cli.Command{{
			Name:  "p2p",
			Usage: "p2p network operation",
			Flags: []cli.Flag{
				cli.BoolFlag{Name: "c", Usage: "create p2p instance (p2p -c interfaceName localPeepIPAddr hash key ttl)"},
				cli.BoolFlag{Name: "d", Usage: "delete p2p instance (p2p -d hash)"},
				cli.BoolFlag{Name: "u", Usage: "update p2p instance encryption key (p2p -u hash newkey ttl)"},
				cli.BoolFlag{Name: "l", Usage: "list of p2p instances (p2p -l)"},
				cli.BoolFlag{Name: "p", Usage: "list of p2p participants (p2p -p hash)"}},
			Action: func(c *cli.Context) {
				lib.P2P(c.Bool("c"), c.Bool("d"), c.Bool("u"), c.Bool("l"), c.Bool("p"), os.Args)
			}}},

		Action: func(c *cli.Context) {
			lib.LxcManagementNetwork(os.Args)
		}}, {

		Name: "metrics", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "start time"},
			cli.StringFlag{Name: "e", Usage: "end time"}},
		Action: func(c *cli.Context) {
			lib.HostMetrics(c.Args().Get(0), c.String("s"), c.String("e"))
		}}, {

		Name: "network", Usage: "containerName set/remove/list network vlan id",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "set, s", Usage: "IPADDRESS/NETMASK"},
			cli.StringFlag{Name: "vlan, v", Usage: "vlanid"},
			cli.BoolFlag{Name: "remove, r", Usage: ""},
			cli.BoolFlag{Name: "list, l", Usage: ""},
		},
		Action: func(c *cli.Context) {
			lib.LxcNetwork(c.Args().Get(0), c.String("s"), c.String("vlan"), c.Bool("r"), c.Bool("l"))
		}}, {

		Name: "promote", Usage: "promote Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcPromote(c.Args().Get(0))
		}}, {

		Name: "proxy", Usage: "Subutai reverse proxy",
		Subcommands: []cli.Command{
			{
				Name:     "add",
				Usage:    "add reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.StringFlag{Name: "domain,d", Usage: "add domain to vlan"},
					cli.StringFlag{Name: "host, h", Usage: "add host to domain on vlan"},
					cli.StringFlag{Name: "policy, p", Usage: "set load balance policy (rr|lb|hash)"},
					cli.StringFlag{Name: "file, f", Usage: "specify pem certificate file"}},
				Action: func(c *cli.Context) {
					lib.ProxyAdd(c.Args().Get(0), c.String("d"), c.String("h"), c.String("p"), c.String("f"))
				},
			},
			{
				Name:     "del",
				Usage:    "del reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "delete domain from vlan"},
					cli.StringFlag{Name: "host, h", Usage: "delete host from domain on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyDel(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
			{
				Name:     "check",
				Usage:    "check existing domain or host",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "check domains on vlan"},
					cli.StringFlag{Name: "host, h", Usage: "check hosts on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyCheck(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
		}}, {

		Name: "quota", Usage: "set quotas for Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "set quota for the specified resource type"},
			cli.StringFlag{Name: "m", Usage: "get the maximum quota can be set to the specified container and resource_type in their default units"}},
		Action: func(c *cli.Context) {
			lib.LxcQuota(c.Args().Get(0), c.Args().Get(1), c.String("s"), c.String("m"))
		}}, {

		Name: "rename", Usage: "rename Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRename(c.Args().Get(0), c.Args().Get(1))
		}}, {

		Name: "register", Usage: "register Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRegister(c.Args().Get(0))
		}}, {

		Name: "stats", Usage: "statistics from host",
		Action: func(c *cli.Context) {
			lib.Stats(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "start", Usage: "start Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStart(c.Args().Get(0))
		}}, {

		Name: "stop", Usage: "stop Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStop(c.Args().Get(0))
		}}, {

		Name: "tunnel", Usage: "create SSH tunnel",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "g", Usage: "global accessible tunnel"}},
		Action: func(c *cli.Context) {
			lib.Tunnel(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2), c.Bool("g"))
		}}, {

		Name: "unregister", Usage: "unregister Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcUnregister(c.Args().Get(0))
		}}, {

		Name: "backup", Usage: "backup Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "full", Usage: "make full backup"}},
		Action: func(c *cli.Context) {
			lib.BackupContainer(c.Args().Get(0), c.Bool("full"))
		}}, {

		Name: "restore", Usage: "restore Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "d", Usage: "date of backup snapshot"},
			cli.StringFlag{Name: "c", Usage: "name of new container"}},
		Action: func(c *cli.Context) {
			lib.RestoreContainer(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package agent

import (
	"reflect"

	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/log"
	"golang.org/x/net/context"
)

// taskManager manages all aspects of task execution and reporting for an agent
// through state management.
type taskManager struct {
	task     *api.Task
	ctlr     exec.Controller
	reporter StatusReporter

	updateq chan *api.Task

	shutdown chan struct{}
	closed   chan struct{}
}

func newTaskManager(ctx context.Context, task *api.Task, ctlr exec.Controller, reporter StatusReporter) *taskManager {
	t := &taskManager{
		task:     task.Copy(),
		ctlr:     ctlr,
		reporter: reporter,
		updateq:  make(chan *api.Task),
		shutdown: make(chan struct{}),
		closed:   make(chan struct{}),
	}
	go t.run(ctx)
	return t
}

// Update the task data.
func (tm *taskManager) Update(ctx context.Context, task *api.Task) error {
	select {
	case tm.updateq <- task:
		return nil
	case <-tm.closed:
		return ErrClosed
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Close shuts down the task manager, blocking until it is stopped.
func (tm *taskManager) Close() error {
	select {
	case <-tm.closed:
		return nil
	case <-tm.shutdown:
	default:
		close(tm.shutdown)
	}

	select {
	case <-tm.closed:
		return nil
	}
}

func (tm *taskManager) run(ctx context.Context) {
	ctx, cancelAll := context.WithCancel(ctx)
	defer cancelAll() // cancel all child operations on exit.

	var (
		opctx    context.Context
		cancel   context.CancelFunc
		run      = make(chan struct{}, 1)
		statusq  = make(chan *api.TaskStatus)
		errs     = make(chan error)
		shutdown = tm.shutdown
		updated  bool // true if the task was updated.
	)

	defer func() {
		// closure  picks up current value of cancel.
		if cancel != nil {
			cancel()
		}
	}()

	run <- struct{}{} // prime the pump
	for {
		select {
		case <-run:
			// always check for shutdown before running.
			select {
			case <-shutdown:
				continue // ignore run request and handle shutdown
			case <-tm.closed:
				continue
			default:
			}

			opctx, cancel = context.WithCancel(ctx)

			// Several variables need to be snapshotted for the closure below.
			opcancel := cancel        // fork for the closure
			running := tm.task.Copy() // clone the task before dispatch
			statusqLocal := statusq
			updatedLocal := updated // capture state of update for goroutine
			updated = false
			go runctx(ctx, tm.closed, errs, func(ctx context.Context) error {
				defer opcancel()

				if updatedLocal {
					// before we do anything, update the task for the controller.
					// always update the controller before running.
					if err := tm.ctlr.Update(opctx, running); err != nil {
						log.G(ctx).WithError(err).Error("updating task controller failed")
						return err
					}
				}

				status, err := exec.Do(opctx, running, tm.ctlr)
				if status != nil {
					// always report the status if we get one back. This
					// returns to the manager loop, then reports the status
					// upstream.
					select {
					case statusqLocal <- status:
					case <-ctx.Done(): // not opctx, since that may have been cancelled.
					}

					if err := tm.reporter.UpdateTaskStatus(ctx, running.ID, status); err != nil {
						log.G(ctx).WithError(err).Error("failed reporting status to agent")
					}
				}

				return err
			})
		case err := <-errs:
			// This branch is always executed when an operations completes. The
			// goal is to decide whether or not we re-dispatch the operation.
			cancel = nil

			switch err {
			case exec.ErrTaskNoop:
				if !updated {
					continue // wait till getting pumped via update.
				}
			case nil:
			case context.Canceled, context.DeadlineExceeded:
			default:
				log.G(ctx).WithError(err).Error("task operation failed")
			}

			run <- struct{}{}
		case status := <-statusq:
			tm.task.Status = *status
		case task := <-tm.updateq:
			if tasksEqual(task, tm.task) {
				continue // ignore the update
			}

			if task.ID != tm.task.ID {
				log.G(ctx).WithField("task.update.id", task.ID).Error("received update for incorrect task")
				continue
			}

			if task.DesiredState < tm.task.DesiredState {
				log.G(ctx).WithField("task.update.desiredstate", task.DesiredState).
					Error("ignoring task update with invalid desired state")
				continue
			}

			task = task.Copy()
			task.Status = tm.task.Status // overwrite our status, as it is canonical.
			tm.task = task
			updated = true

			// we have accepted the task update
			if cancel != nil {
				cancel() // cancel outstanding if necessary.
			} else {
				// no outstanding operation, pump run queue
				run <- struct{}{}
			}
		case <-shutdown:
			if cancel != nil {
				// cancel outstanding operation.
				cancel()
			}

			// TODO(stevvooe): This should be left for the repear.

			// make an attempt at removing. this is best effort. any errors will be
			// retried by the reaper later.
			if err := tm.ctlr.Remove(ctx); err != nil {
				log.G(ctx).WithError(err).WithField("task.id", tm.task.ID).Error("remove task failed")
			}

			if err := tm.ctlr.Close(); err != nil {
				log.G(ctx).WithError(err).Error("error closing controller")
			}
			// disable everything, and prepare for closing.
			statusq = nil
			errs = nil
			shutdown = nil
			close(tm.closed)
		case <-tm.closed:
			return
		case <-ctx.Done():
			return
		}
	}
}

// tasksEqual returns true if the tasks are functionaly equal, ignoring status,
// version and other superfluous fields.
//
// This used to decide whether or not to propagate a task update to a controller.
func tasksEqual(a, b *api.Task) bool {
	a, b = a.Copy(), b.Copy()

	a.Status, b.Status = api.TaskStatus{}, api.TaskStatus{}
	a.Meta, b.Meta = api.Meta{}, api.Meta{}

	return reflect.DeepEqual(a, b)
}
<commit_msg>agent: backoff on ErrTaskRetry<commit_after>package agent

import (
	"reflect"
	"time"

	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/log"
	"golang.org/x/net/context"
)

// taskManager manages all aspects of task execution and reporting for an agent
// through state management.
type taskManager struct {
	task     *api.Task
	ctlr     exec.Controller
	reporter StatusReporter

	updateq chan *api.Task

	shutdown chan struct{}
	closed   chan struct{}
}

func newTaskManager(ctx context.Context, task *api.Task, ctlr exec.Controller, reporter StatusReporter) *taskManager {
	t := &taskManager{
		task:     task.Copy(),
		ctlr:     ctlr,
		reporter: reporter,
		updateq:  make(chan *api.Task),
		shutdown: make(chan struct{}),
		closed:   make(chan struct{}),
	}
	go t.run(ctx)
	return t
}

// Update the task data.
func (tm *taskManager) Update(ctx context.Context, task *api.Task) error {
	select {
	case tm.updateq <- task:
		return nil
	case <-tm.closed:
		return ErrClosed
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Close shuts down the task manager, blocking until it is stopped.
func (tm *taskManager) Close() error {
	select {
	case <-tm.closed:
		return nil
	case <-tm.shutdown:
	default:
		close(tm.shutdown)
	}

	select {
	case <-tm.closed:
		return nil
	}
}

func (tm *taskManager) run(ctx context.Context) {
	ctx, cancelAll := context.WithCancel(ctx)
	defer cancelAll() // cancel all child operations on exit.

	var (
		opctx    context.Context
		cancel   context.CancelFunc
		run      = make(chan struct{}, 1)
		statusq  = make(chan *api.TaskStatus)
		errs     = make(chan error)
		shutdown = tm.shutdown
		updated  bool // true if the task was updated.
	)

	defer func() {
		// closure  picks up current value of cancel.
		if cancel != nil {
			cancel()
		}
	}()

	run <- struct{}{} // prime the pump
	for {
		select {
		case <-run:
			// always check for shutdown before running.
			select {
			case <-shutdown:
				continue // ignore run request and handle shutdown
			case <-tm.closed:
				continue
			default:
			}

			opctx, cancel = context.WithCancel(ctx)

			// Several variables need to be snapshotted for the closure below.
			opcancel := cancel        // fork for the closure
			running := tm.task.Copy() // clone the task before dispatch
			statusqLocal := statusq
			updatedLocal := updated // capture state of update for goroutine
			updated = false
			go runctx(ctx, tm.closed, errs, func(ctx context.Context) error {
				defer opcancel()

				if updatedLocal {
					// before we do anything, update the task for the controller.
					// always update the controller before running.
					if err := tm.ctlr.Update(opctx, running); err != nil {
						log.G(ctx).WithError(err).Error("updating task controller failed")
						return err
					}
				}

				status, err := exec.Do(opctx, running, tm.ctlr)
				if status != nil {
					// always report the status if we get one back. This
					// returns to the manager loop, then reports the status
					// upstream.
					select {
					case statusqLocal <- status:
					case <-ctx.Done(): // not opctx, since that may have been cancelled.
					}

					if err := tm.reporter.UpdateTaskStatus(ctx, running.ID, status); err != nil {
						log.G(ctx).WithError(err).Error("failed reporting status to agent")
					}
				}

				return err
			})
		case err := <-errs:
			// This branch is always executed when an operations completes. The
			// goal is to decide whether or not we re-dispatch the operation.
			cancel = nil

			switch err {
			case exec.ErrTaskNoop:
				if !updated {
					continue // wait till getting pumped via update.
				}
			case exec.ErrTaskRetry:
				// TODO(stevvooe): Add exponential backoff with random jitter
				// here. For now, this backoff is enough to keep the task
				// manager from running away with the CPU.
				time.AfterFunc(time.Second, func() {
					errs <- nil // repump this branch, with no err
				})
				continue
			case nil, context.Canceled, context.DeadlineExceeded:
				// no log in this case
			default:
				log.G(ctx).WithError(err).Error("task operation failed")
			}

			run <- struct{}{}
		case status := <-statusq:
			tm.task.Status = *status
		case task := <-tm.updateq:
			if tasksEqual(task, tm.task) {
				continue // ignore the update
			}

			if task.ID != tm.task.ID {
				log.G(ctx).WithField("task.update.id", task.ID).Error("received update for incorrect task")
				continue
			}

			if task.DesiredState < tm.task.DesiredState {
				log.G(ctx).WithField("task.update.desiredstate", task.DesiredState).
					Error("ignoring task update with invalid desired state")
				continue
			}

			task = task.Copy()
			task.Status = tm.task.Status // overwrite our status, as it is canonical.
			tm.task = task
			updated = true

			// we have accepted the task update
			if cancel != nil {
				cancel() // cancel outstanding if necessary.
			} else {
				// no outstanding operation, pump run queue
				run <- struct{}{}
			}
		case <-shutdown:
			if cancel != nil {
				// cancel outstanding operation.
				cancel()
			}

			// TODO(stevvooe): This should be left for the repear.

			// make an attempt at removing. this is best effort. any errors will be
			// retried by the reaper later.
			if err := tm.ctlr.Remove(ctx); err != nil {
				log.G(ctx).WithError(err).WithField("task.id", tm.task.ID).Error("remove task failed")
			}

			if err := tm.ctlr.Close(); err != nil {
				log.G(ctx).WithError(err).Error("error closing controller")
			}
			// disable everything, and prepare for closing.
			statusq = nil
			errs = nil
			shutdown = nil
			close(tm.closed)
		case <-tm.closed:
			return
		case <-ctx.Done():
			return
		}
	}
}

// tasksEqual returns true if the tasks are functionaly equal, ignoring status,
// version and other superfluous fields.
//
// This used to decide whether or not to propagate a task update to a controller.
func tasksEqual(a, b *api.Task) bool {
	a, b = a.Copy(), b.Copy()

	a.Status, b.Status = api.TaskStatus{}, api.TaskStatus{}
	a.Meta, b.Meta = api.Meta{}, api.Meta{}

	return reflect.DeepEqual(a, b)
}
<|endoftext|>


<commit_before>package brackets

var openBracketToCloseBracket = map[rune]rune{
	'[': ']',
	'{': '}',
	'(': ')',
}

func Bracket(input string) bool {
	stack := Stack{}
	for _, char := range input {
		if isOpenBracket(char) {
			stack.Push(char)
		} else if isCloseBracket(char) {
			if stack.Len() > 0 && isMatching(stack.Peek(), char) {
				stack.Pop()
			} else {
				return false
			}
		} else {
			continue
		}
	}
	return stack.Len() == 0
}

func isOpenBracket(r rune) bool {
	_, ok := openBracketToCloseBracket[r]
	return ok
}

func isCloseBracket(r rune) bool {
	for _, v := range openBracketToCloseBracket {
		if r == v {
			return true
		}
	}
	return false
}

func isMatching(open rune, close rune) bool {
	return openBracketToCloseBracket[open] == close
}

type Stack struct {
	slice []rune
}

func (s *Stack) Len() int {
	return len(s.slice)
}
func (s *Stack) Push(r rune) {
	s.slice = append(s.slice, r)
}
func (s *Stack) Peek() rune {
	return s.slice[len(s.slice)-1]
}
func (s *Stack) Pop() rune {
	result := s.Peek()
	s.slice = s.slice[:len(s.slice)-1]
	return result
}
<commit_msg>Remove redundant else branch<commit_after>package brackets

var openBracketToCloseBracket = map[rune]rune{
	'[': ']',
	'{': '}',
	'(': ')',
}

func Bracket(input string) bool {
	stack := Stack{}
	for _, char := range input {
		if isOpenBracket(char) {
			stack.Push(char)
		} else if isCloseBracket(char) {
			if stack.Len() > 0 && isMatching(stack.Peek(), char) {
				stack.Pop()
			} else {
				return false
			}
		}
	}
	return stack.Len() == 0
}

func isOpenBracket(r rune) bool {
	_, ok := openBracketToCloseBracket[r]
	return ok
}

func isCloseBracket(r rune) bool {
	for _, v := range openBracketToCloseBracket {
		if r == v {
			return true
		}
	}
	return false
}

func isMatching(open rune, close rune) bool {
	return openBracketToCloseBracket[open] == close
}

type Stack struct {
	slice []rune
}

func (s *Stack) Len() int {
	return len(s.slice)
}
func (s *Stack) Push(r rune) {
	s.slice = append(s.slice, r)
}
func (s *Stack) Peek() rune {
	return s.slice[len(s.slice)-1]
}
func (s *Stack) Pop() rune {
	result := s.Peek()
	s.slice = s.slice[:len(s.slice)-1]
	return result
}
<|endoftext|>


<commit_before>package stack

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"koding/api"
	stacktemplate "koding/remoteapi/client/j_stack_template"
	"koding/remoteapi/models"

	"github.com/koding/kite"
	yaml "gopkg.in/yaml.v2"
)

// ImportRequest represents a request struct for "stack.import"
// kloud's kite method.
type ImportRequest struct {
	Credentials map[string][]string `json:"credentials"`
	Template    []byte              `json:"template"`
	Provider    string              `json:"provider"`
	Team        string              `json:"team"`
	Title       string              `json:"title,omitempty"`
}

// Valid implements the Validator interface.
func (r *ImportRequest) Valid() error {
	if len(r.Credentials) == 0 {
		return errors.New("empty credentials")
	}

	if len(r.Template) == 0 {
		return errors.New("empty template")
	}

	if r.Team == "" {
		return errors.New("empty team")
	}

	var raw json.RawMessage

	if err := json.Unmarshal(r.Template, &raw); err != nil {
		return fmt.Errorf("template is not a valid JSON: %s", err)
	}

	return nil
}

// ImportResponse represents a response struct for "stack.import"
// kloud's kite method.
type ImportResponse struct {
	TemplateID string `json:"templateId"`
	StackID    string `json:"stackId"`
	Title      string `json:"title"`
	EventID    string `json:"eventId"`
}

var requiredData = map[string]interface{}{
	"group": []interface{}{"slug"},
	"user":  []interface{}{"username"},
}

func (k *Kloud) Import(r *kite.Request) (interface{}, error) {
	var req ImportRequest

	if err := r.Args.One().Unmarshal(&req); err != nil {
		return nil, err
	}

	if err := req.Valid(); err != nil {
		return nil, err
	}

	// TODO(rjeczalik): Refactor stack/provider/apply to make it possible to build
	// multiple stacks at once.
	if req.Provider == "" {
		providers, err := ReadProviders(req.Template)
		if err != nil {
			return nil, err
		}

		for _, provider := range providers {
			if _, ok := k.providers[provider]; ok {
				req.Provider = provider
				break
			}
		}
	}

	if req.Title == "" {
		req.Title = fmt.Sprintf("%s %s Stack", Pokemon(), strings.ToTitle(req.Provider))
	}

	p, ok := k.providers[req.Provider]
	if !ok {
		return nil, NewError(ErrProviderNotFound)
	}

	c := k.RemoteClient.New(&api.User{
		Username: r.Username,
		Team:     req.Team,
	})

	tmplParams := &stacktemplate.PostRemoteAPIJStackTemplateCreateParams{
		Body: stacktemplate.PostRemoteAPIJStackTemplateCreateBody{
			Template:    pstring(req.Template),
			Title:       &req.Title,
			Credentials: req.Credentials,
			Config: map[string]interface{}{
				"groupStack":        false,
				"requiredProviders": []interface{}{req.Provider},
				"requiredData":      requiredData,
			},
		},
	}

	tmplParams.SetTimeout(k.RemoteClient.Timeout())

	tmplResp, err := c.JStackTemplate.PostRemoteAPIJStackTemplateCreate(tmplParams)
	if err != nil {
		return nil, errors.New("JStackTemplate.create failure: " + err.Error())
	}

	k.Log.Debug("JStackTemplate.create response: %#v", tmplResp)

	// TODO(rjeczalik): generated model does not have an ID field.
	// var tmpl models.JStackTemplate
	var tmpl struct {
		ID string `json:"_id"`
	}

	if err := response(tmplResp.Payload, &tmpl); err != nil {
		return nil, errors.New("JStackTemplate.create failure: " + err.Error())
	}

	teamReq := &TeamRequest{
		Provider:   req.Provider,
		GroupName:  req.Team,
		Identifier: req.Credentials[req.Provider][0],
	}

	kiteReq := &kite.Request{
		Method:   "plan",
		Username: r.Username,
	}

	planReq := &PlanRequest{
		Provider:        req.Provider,
		StackTemplateID: tmpl.ID,
		GroupName:       req.Team,
	}

	planStack, ctx, err := k.NewStack(p, kiteReq, teamReq)
	if err != nil {
		return nil, err
	}

	ctx = context.WithValue(ctx, PlanRequestKey, planReq)

	v, err := planStack.HandlePlan(ctx)
	if err != nil {
		return nil, fmt.Errorf("error creating plan: %s", err)
	}

	k.Log.Debug("plan received %# v", v)

	var machines []*Machine

	if v, ok := v.(*PlanResponse); ok {
		if m, ok := v.Machines.([]*Machine); ok {
			machines = m
		}
	}

	tmplUpdateParams := &stacktemplate.PostRemoteAPIJStackTemplateUpdateIDParams{
		ID: tmpl.ID,
		Body: map[string]interface{}{
			"config.verified": true,
			"machines":        machines,
		},
	}

	tmplUpdateParams.SetTimeout(k.RemoteClient.Timeout())

	tmplUpdateResp, err := c.JStackTemplate.PostRemoteAPIJStackTemplateUpdateID(tmplUpdateParams)
	if err != nil {
		return nil, fmt.Errorf("JStackTemplate.update failure: " + err.Error())
	}

	k.Log.Debug("JStackTemplate.update response: %#v", tmplUpdateResp)

	stackParams := &stacktemplate.PostRemoteAPIJStackTemplateGenerateStackIDParams{
		ID: tmpl.ID,
	}

	stackParams.SetTimeout(k.RemoteClient.Timeout())

	stackResp, err := c.JStackTemplate.PostRemoteAPIJStackTemplateGenerateStackID(stackParams)
	if err != nil {
		return nil, errors.New("JStackTemplate.generateStack failure: " + err.Error())
	}

	var resp struct {
		Stack struct {
			ID string `json:"_id"`
		} `json:"stack"`
	}

	if err := response(&stackResp.Payload.DefaultResponse, &resp); err != nil {
		return nil, errors.New("JStackTemplate.generateStack failure: " + err.Error())
	}

	k.Log.Debug("JStackTemplate.generateStack response: %#v", stackResp)

	kiteReq = &kite.Request{
		Method:   "apply",
		Username: r.Username,
	}

	applyReq := &ApplyRequest{
		Provider:  req.Provider,
		StackID:   resp.Stack.ID,
		GroupName: req.Team,
	}

	applyStack, ctx, err := k.NewStack(p, kiteReq, teamReq)
	if err != nil {
		return nil, err
	}

	ctx = context.WithValue(ctx, ApplyRequestKey, applyReq)

	v, err = applyStack.HandleApply(ctx)
	if err != nil {
		return nil, fmt.Errorf("error building stack: %s", err)
	}

	return &ImportResponse{
		TemplateID: tmpl.ID,
		StackID:    resp.Stack.ID,
		Title:      req.Title,
		EventID:    v.(*ControlResult).EventId,
	}, nil
}

func response(resp *models.DefaultResponse, v interface{}) error {
	if resp.Error != nil {
		if err, ok := resp.Error.(map[string]interface{}); ok {
			msg, _ := err["message"].(string)
			typ, _ := err["name"].(string)

			if msg != "" && typ != "" {
				return &kite.Error{
					Type:    typ,
					Message: msg,
				}
			}
		}

		return fmt.Errorf("%v", resp.Error)
	}

	if v == nil {
		return nil
	}

	p, err := jsonMarshal(resp.Data)
	if err != nil {
		return err
	}

	return json.Unmarshal(p, v)
}

func jsonMarshal(v interface{}) ([]byte, error) {
	var buf bytes.Buffer

	enc := json.NewEncoder(&buf)
	enc.SetEscapeHTML(false)

	if err := enc.Encode(v); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func yamlReencode(template []byte) ([]byte, error) {
	var m map[string]interface{}

	if err := json.Unmarshal(template, &m); err != nil {
		return nil, err
	}

	p, err := yaml.Marshal(m)
	if err != nil {
		return nil, err
	}

	return p, nil
}

func pstring(p []byte) *string {
	if len(p) == 0 {
		return nil
	}

	s := string(p)
	return &s
}
<commit_msg>kloud/stack: refactor Import into smaller methods<commit_after>package stack

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"

	"koding/api"
	"koding/remoteapi/client"
	stacktemplate "koding/remoteapi/client/j_stack_template"
	"koding/remoteapi/models"

	"github.com/koding/kite"
	"github.com/koding/logging"
	yaml "gopkg.in/yaml.v2"
)

// ImportRequest represents a request struct for "stack.import"
// kloud's kite method.
type ImportRequest struct {
	Credentials map[string][]string `json:"credentials"`
	Template    []byte              `json:"template"`
	Provider    string              `json:"provider"`
	Team        string              `json:"team"`
	Title       string              `json:"title,omitempty"`
}

// Valid implements the Validator interface.
func (r *ImportRequest) Valid() error {
	if len(r.Credentials) == 0 {
		return errors.New("empty credentials")
	}

	if len(r.Template) == 0 {
		return errors.New("empty template")
	}

	if r.Team == "" {
		return errors.New("empty team")
	}

	var raw json.RawMessage

	if err := json.Unmarshal(r.Template, &raw); err != nil {
		return fmt.Errorf("template is not a valid JSON: %s", err)
	}

	return nil
}

// ImportResponse represents a response struct for "stack.import"
// kloud's kite method.
type ImportResponse struct {
	TemplateID string `json:"templateId"`
	StackID    string `json:"stackId"`
	Title      string `json:"title"`
	EventID    string `json:"eventId"`
}

var requiredData = map[string]interface{}{
	"group": []interface{}{"slug"},
	"user":  []interface{}{"username"},
}

func (k *Kloud) Import(r *kite.Request) (interface{}, error) {
	var req ImportRequest

	if err := r.Args.One().Unmarshal(&req); err != nil {
		return nil, err
	}

	if err := req.Valid(); err != nil {
		return nil, err
	}

	// TODO(rjeczalik): Refactor stack/provider/apply to make it possible to build
	// multiple stacks at once.
	if req.Provider == "" {
		providers, err := ReadProviders(req.Template)
		if err != nil {
			return nil, err
		}

		for _, provider := range providers {
			if _, ok := k.providers[provider]; ok {
				req.Provider = provider
				break
			}
		}
	}

	if req.Title == "" {
		req.Title = fmt.Sprintf("%s %s Stack", Pokemon(), strings.ToTitle(req.Provider))
	}

	p, ok := k.providers[req.Provider]
	if !ok {
		return nil, NewError(ErrProviderNotFound)
	}

	teamReq := &TeamRequest{
		Provider:   req.Provider,
		GroupName:  req.Team,
		Identifier: req.Credentials[req.Provider][0],
	}

	sb := &stackBuilder{
		req: &req,
		resp: &ImportResponse{
			Title: req.Title,
		},
		api: k.RemoteClient.New(&api.User{
			Username: r.Username,
			Team:     req.Team,
		}),
		timeout: k.RemoteClient.Timeout(),
		log:     k.Log.New("stackBuilder"),
	}

	if err := sb.buildTemplate(); err != nil {
		return nil, errors.New("failure creating template: " + err.Error())
	}

	planReq := &PlanRequest{
		Provider:        req.Provider,
		StackTemplateID: sb.resp.TemplateID,
		GroupName:       req.Team,
	}

	machines, err := k.doPlan(r, p, teamReq, planReq)
	if err != nil {
		return nil, errors.New("failure creating plan: " + err.Error())
	}

	if err := sb.setVerified(machines); err != nil {
		return nil, errors.New("failure updating template: " + err.Error())
	}

	if err := sb.buildStack(); err != nil {
		return nil, errors.New("failure creating stack: " + err.Error())
	}

	applyReq := &ApplyRequest{
		Provider:  req.Provider,
		StackID:   sb.resp.StackID,
		GroupName: req.Team,
	}

	eventID, err := k.doApply(r, p, teamReq, applyReq)
	if err != nil {
		return nil, errors.New("failure building stack: " + err.Error())
	}

	sb.resp.EventID = eventID

	return sb.resp, nil
}

func (k *Kloud) doPlan(r *kite.Request, p Provider, teamReq *TeamRequest, req *PlanRequest) ([]*Machine, error) {
	kiteReq := &kite.Request{
		Method:   "plan",
		Username: r.Username,
	}

	stack, ctx, err := k.NewStack(p, kiteReq, teamReq)
	if err != nil {
		return nil, err
	}

	ctx = context.WithValue(ctx, PlanRequestKey, req)

	v, err := stack.HandlePlan(ctx)
	if err != nil {
		return nil, err
	}

	k.Log.Debug("plan received: %# v", v)

	var machines []*Machine

	if v, ok := v.(*PlanResponse); ok {
		if m, ok := v.Machines.([]*Machine); ok {
			machines = m
		}
	}

	return machines, nil
}

func (k *Kloud) doApply(r *kite.Request, p Provider, teamReq *TeamRequest, req *ApplyRequest) (eventID string, err error) {
	kiteReq := &kite.Request{
		Method:   "apply",
		Username: r.Username,
	}

	stack, ctx, err := k.NewStack(p, kiteReq, teamReq)
	if err != nil {
		return "", err
	}

	ctx = context.WithValue(ctx, ApplyRequestKey, req)

	v, err := stack.HandleApply(ctx)
	if err != nil {
		return "", err
	}

	return v.(*ControlResult).EventId, nil
}

type stackBuilder struct {
	req     *ImportRequest
	resp    *ImportResponse
	log     logging.Logger
	api     *client.Koding
	timeout time.Duration
	once    sync.Once
}

func (sb *stackBuilder) buildTemplate() error {
	params := &stacktemplate.PostRemoteAPIJStackTemplateCreateParams{
		Body: stacktemplate.PostRemoteAPIJStackTemplateCreateBody{
			Template:    sb.reqTemplate(),
			Title:       &sb.req.Title,
			Credentials: sb.req.Credentials,
			Config: map[string]interface{}{
				"groupStack":        false,
				"requiredProviders": []interface{}{sb.req.Provider},
				"requiredData":      requiredData,
			},
		},
	}

	params.SetTimeout(sb.timeout)

	resp, err := sb.api.JStackTemplate.PostRemoteAPIJStackTemplateCreate(params)
	if err != nil {
		return err
	}

	sb.log.Debug("JStackTemplate.create response: %#v", resp)

	// TODO(rjeczalik): generated model does not have an ID field.
	// var tmpl models.JStackTemplate
	var tmpl struct {
		ID string `json:"_id"`
	}

	if err := response(resp.Payload, &tmpl); err != nil {
		return err
	}

	sb.resp.TemplateID = tmpl.ID

	return nil
}

func (sb *stackBuilder) setVerified(machines []*Machine) error {
	body := map[string]interface{}{
		"config.verified": true,
	}

	if len(machines) != 0 {
		body["machines"] = machines
	}

	params := &stacktemplate.PostRemoteAPIJStackTemplateUpdateIDParams{
		ID:   sb.resp.TemplateID,
		Body: body,
	}

	params.SetTimeout(sb.timeout)

	resp, err := sb.api.JStackTemplate.PostRemoteAPIJStackTemplateUpdateID(params)
	if err != nil {
		return err
	}

	sb.log.Debug("JStackTemplate.update response: %#v", resp)

	return response(&resp.Payload.DefaultResponse, nil)
}

func (sb *stackBuilder) buildStack() error {
	params := &stacktemplate.PostRemoteAPIJStackTemplateGenerateStackIDParams{
		ID: sb.resp.TemplateID,
	}

	params.SetTimeout(sb.timeout)

	resp, err := sb.api.JStackTemplate.PostRemoteAPIJStackTemplateGenerateStackID(params)
	if err != nil {
		return err
	}

	var payload struct {
		Stack struct {
			ID string `json:"_id"`
		} `json:"stack"`
	}

	if err := response(&resp.Payload.DefaultResponse, &payload); err != nil {
		return err
	}

	sb.log.Debug("JStackTemplate.generateStack response: %#v", resp)

	sb.resp.StackID = payload.Stack.ID

	return nil
}

func (sb *stackBuilder) reqTemplate() *string {
	s := string(sb.req.Template)
	return &s
}

func response(resp *models.DefaultResponse, v interface{}) error {
	if resp.Error != nil {
		if err, ok := resp.Error.(map[string]interface{}); ok {
			msg, _ := err["message"].(string)
			typ, _ := err["name"].(string)

			if msg != "" && typ != "" {
				return &kite.Error{
					Type:    typ,
					Message: msg,
				}
			}
		}

		return fmt.Errorf("%v", resp.Error)
	}

	if v == nil {
		return nil
	}

	p, err := jsonMarshal(resp.Data)
	if err != nil {
		return err
	}

	return json.Unmarshal(p, v)
}

func jsonMarshal(v interface{}) ([]byte, error) {
	var buf bytes.Buffer

	enc := json.NewEncoder(&buf)
	enc.SetEscapeHTML(false)

	if err := enc.Encode(v); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func yamlReencode(template []byte) ([]byte, error) {
	var m map[string]interface{}

	if err := json.Unmarshal(template, &m); err != nil {
		return nil, err
	}

	p, err := yaml.Marshal(m)
	if err != nil {
		return nil, err
	}

	return p, nil
}

func pstring(p []byte) *string {
	if len(p) == 0 {
		return nil
	}

	s := string(p)
	return &s
}
<|endoftext|>


<commit_before>// Code generated by protoc-gen-go. DO NOT EDIT.
// source: config.proto

/*
Package domainsocket is a generated protocol buffer package.

It is generated from these files:
	config.proto

It has these top-level messages:
	DomainSocketSecurity
	DomainSocketSettings
*/
package domainsocket

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

// Flag Array
type DomainSocketSecurityMode int32

const (
	DomainSocketSecurityMode_Danger DomainSocketSecurityMode = 0
	// Verfify is Dialer have a pid or ppid match pid file
	DomainSocketSecurityMode_VerifyPid DomainSocketSecurityMode = 1
	// Do not tolerance ppid match
	DomainSocketSecurityMode_DisqualifyPPIDMatch DomainSocketSecurityMode = 2
	// Enforce Uid Verify On euid
	DomainSocketSecurityMode_VerifyEUID DomainSocketSecurityMode = 4
	// Enforce Uid Verify On ruid
	DomainSocketSecurityMode_VerifyRUID DomainSocketSecurityMode = 8
	// Does not allow same user exception
	DomainSocketSecurityMode_DisqualifySameUser DomainSocketSecurityMode = 16
	// Does not allow root user exception
	DomainSocketSecurityMode_DisqualifyRootUser DomainSocketSecurityMode = 32
)

var DomainSocketSecurityMode_name = map[int32]string{
	0:  "Danger",
	1:  "VerifyPid",
	2:  "DisqualifyPPIDMatch",
	4:  "VerifyEUID",
	8:  "VerifyRUID",
	16: "DisqualifySameUser",
	32: "DisqualifyRootUser",
}
var DomainSocketSecurityMode_value = map[string]int32{
	"Danger":              0,
	"VerifyPid":           1,
	"DisqualifyPPIDMatch": 2,
	"VerifyEUID":          4,
	"VerifyRUID":          8,
	"DisqualifySameUser":  16,
	"DisqualifyRootUser":  32,
}

func (x DomainSocketSecurityMode) String() string {
	return proto.EnumName(DomainSocketSecurityMode_name, int32(x))
}
func (DomainSocketSecurityMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

type DomainSocketSecurity struct {
	// Flag Array Type, User can set an integer to define various configure
	Mode DomainSocketSecurityMode `protobuf:"varint,1,opt,name=Mode,enum=v2ray.core.internet.domainsocket.DomainSocketSecurityMode" json:"Mode,omitempty"`
	// Set pid files to be allowed
	AllowedPid []string `protobuf:"bytes,2,rep,name=AllowedPid" json:"AllowedPid,omitempty"`
	// Set uids to be allowed, either euid or ruid should match one of following
	// uids AllowedUid, or user that v2ray is running or root.
	AllowedUid []uint64 `protobuf:"varint,3,rep,packed,name=AllowedUid" json:"AllowedUid,omitempty"`
}

func (m *DomainSocketSecurity) Reset()                    { *m = DomainSocketSecurity{} }
func (m *DomainSocketSecurity) String() string            { return proto.CompactTextString(m) }
func (*DomainSocketSecurity) ProtoMessage()               {}
func (*DomainSocketSecurity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *DomainSocketSecurity) GetMode() DomainSocketSecurityMode {
	if m != nil {
		return m.Mode
	}
	return DomainSocketSecurityMode_Danger
}

func (m *DomainSocketSecurity) GetAllowedPid() []string {
	if m != nil {
		return m.AllowedPid
	}
	return nil
}

func (m *DomainSocketSecurity) GetAllowedUid() []uint64 {
	if m != nil {
		return m.AllowedUid
	}
	return nil
}

type DomainSocketSettings struct {
	// Path we should listen/dial
	Path     string                `protobuf:"bytes,1,opt,name=Path" json:"Path,omitempty"`
	Security *DomainSocketSecurity `protobuf:"bytes,2,opt,name=Security" json:"Security,omitempty"`
}

func (m *DomainSocketSettings) Reset()                    { *m = DomainSocketSettings{} }
func (m *DomainSocketSettings) String() string            { return proto.CompactTextString(m) }
func (*DomainSocketSettings) ProtoMessage()               {}
func (*DomainSocketSettings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

func (m *DomainSocketSettings) GetPath() string {
	if m != nil {
		return m.Path
	}
	return ""
}

func (m *DomainSocketSettings) GetSecurity() *DomainSocketSecurity {
	if m != nil {
		return m.Security
	}
	return nil
}

func init() {
	proto.RegisterType((*DomainSocketSecurity)(nil), "v2ray.core.internet.domainsocket.DomainSocketSecurity")
	proto.RegisterType((*DomainSocketSettings)(nil), "v2ray.core.internet.domainsocket.DomainSocketSettings")
	proto.RegisterEnum("v2ray.core.internet.domainsocket.DomainSocketSecurityMode", DomainSocketSecurityMode_name, DomainSocketSecurityMode_value)
}

func init() { proto.RegisterFile("config.proto", fileDescriptor0) }

var fileDescriptor0 = []byte{
	// 302 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xb1, 0x4b, 0x3b, 0x31,
	0x14, 0xc7, 0x7f, 0x69, 0x8f, 0xd2, 0xbe, 0x5f, 0x2d, 0xe1, 0x29, 0x7a, 0x93, 0x84, 0x4e, 0x87,
	0x43, 0x86, 0x0a, 0x0e, 0x6e, 0xca, 0x39, 0x74, 0xa8, 0x1c, 0x29, 0x75, 0x70, 0x8b, 0x97, 0xb4,
	0x0d, 0xb6, 0x89, 0xe6, 0x52, 0xa5, 0x8b, 0x7f, 0x8a, 0xa3, 0x7f, 0xa7, 0x34, 0xa2, 0x3d, 0x45,
	0x11, 0xdc, 0xf2, 0x3e, 0x49, 0x3e, 0x7c, 0xbf, 0xf0, 0xa0, 0x5b, 0x3a, 0x3b, 0x35, 0x33, 0x7e,
	0xe7, 0x5d, 0x70, 0xc8, 0x1e, 0x06, 0x5e, 0xae, 0x79, 0xe9, 0xbc, 0xe6, 0xc6, 0x06, 0xed, 0xad,
	0x0e, 0x5c, 0xb9, 0xa5, 0x34, 0xb6, 0x72, 0xe5, 0xad, 0x0e, 0xfd, 0x17, 0x02, 0x7b, 0x79, 0x04,
	0xe3, 0x08, 0xc6, 0xba, 0x5c, 0x79, 0x13, 0xd6, 0x78, 0x09, 0xc9, 0xc8, 0x29, 0x9d, 0x12, 0x46,
	0xb2, 0xde, 0xe0, 0x94, 0xff, 0x66, 0xe2, 0xdf, 0x59, 0x36, 0x06, 0x11, 0x3d, 0x78, 0x08, 0x70,
	0xb6, 0x58, 0xb8, 0x47, 0xad, 0x0a, 0xa3, 0xd2, 0x06, 0x6b, 0x66, 0x1d, 0x51, 0x23, 0xb5, 0xfb,
	0x89, 0x51, 0x69, 0x93, 0x35, 0xb3, 0x44, 0xd4, 0x48, 0xff, 0xe9, 0x6b, 0xce, 0x10, 0x8c, 0x9d,
	0x55, 0x88, 0x90, 0x14, 0x32, 0xcc, 0x63, 0xce, 0x8e, 0x88, 0x67, 0x14, 0xd0, 0x7e, 0x4f, 0x90,
	0x36, 0x18, 0xc9, 0xfe, 0x0f, 0x4e, 0xfe, 0x96, 0x5f, 0x7c, 0x78, 0x8e, 0x9e, 0x09, 0xa4, 0x3f,
	0x55, 0x44, 0x80, 0x56, 0x2e, 0xed, 0x4c, 0x7b, 0xfa, 0x0f, 0x77, 0xa0, 0x73, 0xa5, 0xbd, 0x99,
	0xae, 0x0b, 0xa3, 0x28, 0xc1, 0x03, 0xd8, 0xcd, 0x4d, 0x75, 0xbf, 0x92, 0x8b, 0x0d, 0x2a, 0x86,
	0xf9, 0x48, 0x86, 0x72, 0x4e, 0x1b, 0xd8, 0x03, 0x78, 0x7b, 0x77, 0x31, 0x19, 0xe6, 0x34, 0xd9,
	0xce, 0x62, 0x33, 0xb7, 0x71, 0x1f, 0x70, 0xfb, 0x71, 0x2c, 0x97, 0x7a, 0x52, 0x69, 0x4f, 0xe9,
	0x67, 0x2e, 0x9c, 0x0b, 0x91, 0xb3, 0xf3, 0xde, 0x75, 0xb7, 0xde, 0xe7, 0xa6, 0x15, 0x57, 0xe0,
	0xf8, 0x35, 0x00, 0x00, 0xff, 0xff, 0x53, 0x18, 0xa4, 0xc9, 0x12, 0x02, 0x00, 0x00,
}
<commit_msg>Regenerate Pb<commit_after>package domainsocket

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

// Flag Array
type DomainSocketSecurityMode int32

const (
	DomainSocketSecurityMode_Danger DomainSocketSecurityMode = 0
	// Verfify is Dialer have a pid or ppid match pid file
	DomainSocketSecurityMode_VerifyPid DomainSocketSecurityMode = 1
	// Do not tolerance ppid match
	DomainSocketSecurityMode_DisqualifyPPIDMatch DomainSocketSecurityMode = 2
	// Enforce Uid Verify On euid
	DomainSocketSecurityMode_VerifyEUID DomainSocketSecurityMode = 4
	// Enforce Uid Verify On ruid
	DomainSocketSecurityMode_VerifyRUID DomainSocketSecurityMode = 8
	// Does not allow same user exception
	DomainSocketSecurityMode_DisqualifySameUser DomainSocketSecurityMode = 16
	// Does not allow root user exception
	DomainSocketSecurityMode_DisqualifyRootUser DomainSocketSecurityMode = 32
)

var DomainSocketSecurityMode_name = map[int32]string{
	0:  "Danger",
	1:  "VerifyPid",
	2:  "DisqualifyPPIDMatch",
	4:  "VerifyEUID",
	8:  "VerifyRUID",
	16: "DisqualifySameUser",
	32: "DisqualifyRootUser",
}
var DomainSocketSecurityMode_value = map[string]int32{
	"Danger":              0,
	"VerifyPid":           1,
	"DisqualifyPPIDMatch": 2,
	"VerifyEUID":          4,
	"VerifyRUID":          8,
	"DisqualifySameUser":  16,
	"DisqualifyRootUser":  32,
}

func (x DomainSocketSecurityMode) String() string {
	return proto.EnumName(DomainSocketSecurityMode_name, int32(x))
}
func (DomainSocketSecurityMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

type DomainSocketSecurity struct {
	// Flag Array Type, User can set an integer to define various configure
	Mode DomainSocketSecurityMode `protobuf:"varint,1,opt,name=Mode,enum=v2ray.core.internet.domainsocket.DomainSocketSecurityMode" json:"Mode,omitempty"`
	// Set pid files to be allowed
	AllowedPid []string `protobuf:"bytes,2,rep,name=AllowedPid" json:"AllowedPid,omitempty"`
	// Set uids to be allowed, either euid or ruid should match one of following
	// uids AllowedUid, or user that v2ray is running or root.
	AllowedUid []uint64 `protobuf:"varint,3,rep,packed,name=AllowedUid" json:"AllowedUid,omitempty"`
}

func (m *DomainSocketSecurity) Reset()                    { *m = DomainSocketSecurity{} }
func (m *DomainSocketSecurity) String() string            { return proto.CompactTextString(m) }
func (*DomainSocketSecurity) ProtoMessage()               {}
func (*DomainSocketSecurity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *DomainSocketSecurity) GetMode() DomainSocketSecurityMode {
	if m != nil {
		return m.Mode
	}
	return DomainSocketSecurityMode_Danger
}

func (m *DomainSocketSecurity) GetAllowedPid() []string {
	if m != nil {
		return m.AllowedPid
	}
	return nil
}

func (m *DomainSocketSecurity) GetAllowedUid() []uint64 {
	if m != nil {
		return m.AllowedUid
	}
	return nil
}

type DomainSocketSettings struct {
	// Path we should listen/dial
	Path     string                `protobuf:"bytes,1,opt,name=Path" json:"Path,omitempty"`
	Security *DomainSocketSecurity `protobuf:"bytes,2,opt,name=Security" json:"Security,omitempty"`
}

func (m *DomainSocketSettings) Reset()                    { *m = DomainSocketSettings{} }
func (m *DomainSocketSettings) String() string            { return proto.CompactTextString(m) }
func (*DomainSocketSettings) ProtoMessage()               {}
func (*DomainSocketSettings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

func (m *DomainSocketSettings) GetPath() string {
	if m != nil {
		return m.Path
	}
	return ""
}

func (m *DomainSocketSettings) GetSecurity() *DomainSocketSecurity {
	if m != nil {
		return m.Security
	}
	return nil
}

func init() {
	proto.RegisterType((*DomainSocketSecurity)(nil), "v2ray.core.internet.domainsocket.DomainSocketSecurity")
	proto.RegisterType((*DomainSocketSettings)(nil), "v2ray.core.internet.domainsocket.DomainSocketSettings")
	proto.RegisterEnum("v2ray.core.internet.domainsocket.DomainSocketSecurityMode", DomainSocketSecurityMode_name, DomainSocketSecurityMode_value)
}

func init() {
	proto.RegisterFile("v2ray.com/core/transport/internet/domainsocket/config.proto", fileDescriptor0)
}

var fileDescriptor0 = []byte{
	// 323 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x41, 0x4b, 0xf3, 0x40,
	0x10, 0x86, 0xbf, 0xb4, 0xa1, 0xb4, 0xf3, 0x69, 0x09, 0xab, 0x68, 0x4e, 0x12, 0x7a, 0x0a, 0x1e,
	0x12, 0xa8, 0xe0, 0x41, 0x4f, 0x4a, 0x3c, 0xf4, 0x50, 0x09, 0x5b, 0xea, 0xc1, 0xdb, 0x9a, 0xdd,
	0xb6, 0x8b, 0xed, 0x4e, 0xdd, 0x4c, 0x95, 0x5e, 0xfc, 0x29, 0x1e, 0xfd, 0x9d, 0xd2, 0x95, 0xd8,
	0x28, 0x8a, 0xe0, 0x2d, 0xf3, 0xe4, 0x9d, 0x87, 0x77, 0x60, 0xe1, 0xfc, 0xb1, 0x6f, 0xc5, 0x3a,
	0x29, 0x70, 0x91, 0x16, 0x68, 0x55, 0x4a, 0x56, 0x98, 0x72, 0x89, 0x96, 0x52, 0x6d, 0x48, 0x59,
	0xa3, 0x28, 0x95, 0xb8, 0x10, 0xda, 0x94, 0x58, 0xdc, 0x2b, 0x4a, 0x0b, 0x34, 0x13, 0x3d, 0x4d,
	0x96, 0x16, 0x09, 0x59, 0x54, 0x2d, 0x5b, 0x95, 0x54, 0xf1, 0xa4, 0x1e, 0xef, 0xbd, 0x7a, 0xb0,
	0x9f, 0x39, 0x30, 0x72, 0x60, 0xa4, 0x8a, 0x95, 0xd5, 0xb4, 0x66, 0xd7, 0xe0, 0x0f, 0x51, 0xaa,
	0xd0, 0x8b, 0xbc, 0xb8, 0xdb, 0x3f, 0x4b, 0x7e, 0x33, 0x25, 0xdf, 0x59, 0x36, 0x06, 0xee, 0x3c,
	0xec, 0x08, 0xe0, 0x62, 0x3e, 0xc7, 0x27, 0x25, 0x73, 0x2d, 0xc3, 0x46, 0xd4, 0x8c, 0x3b, 0xbc,
	0x46, 0x6a, 0xff, 0xc7, 0x5a, 0x86, 0xcd, 0xa8, 0x19, 0xfb, 0xbc, 0x46, 0x7a, 0xcf, 0x5f, 0x7b,
	0x12, 0x69, 0x33, 0x2d, 0x19, 0x03, 0x3f, 0x17, 0x34, 0x73, 0x3d, 0x3b, 0xdc, 0x7d, 0x33, 0x0e,
	0xed, 0xaa, 0x41, 0xd8, 0x88, 0xbc, 0xf8, 0x7f, 0xff, 0xf4, 0x6f, 0xfd, 0xf9, 0x87, 0xe7, 0xf8,
	0xc5, 0x83, 0xf0, 0xa7, 0x13, 0x19, 0x40, 0x2b, 0x13, 0x66, 0xaa, 0x6c, 0xf0, 0x8f, 0xed, 0x42,
	0xe7, 0x46, 0x59, 0x3d, 0x59, 0xe7, 0x5a, 0x06, 0x1e, 0x3b, 0x84, 0xbd, 0x4c, 0x97, 0x0f, 0x2b,
	0x31, 0xdf, 0xa0, 0x7c, 0x90, 0x0d, 0x05, 0x15, 0xb3, 0xa0, 0xc1, 0xba, 0x00, 0xef, 0xb9, 0xab,
	0xf1, 0x20, 0x0b, 0xfc, 0xed, 0xcc, 0x37, 0x73, 0x9b, 0x1d, 0x00, 0xdb, 0x2e, 0x8e, 0xc4, 0x42,
	0x8d, 0x4b, 0x65, 0x83, 0xe0, 0x33, 0xe7, 0x88, 0xe4, 0x78, 0x74, 0xd9, 0xbd, 0xdd, 0xa9, 0xdf,
	0x73, 0xd7, 0x72, 0x4f, 0xe0, 0xe4, 0x2d, 0x00, 0x00, 0xff, 0xff, 0x30, 0xd5, 0x61, 0x90, 0x41,
	0x02, 0x00, 0x00,
}
<|endoftext|>


<commit_before>package server

import (
	"net/http"
	"server/controller"

	"golang.org/x/net/websocket"

	"github.com/fvbock/endless"
	"github.com/gin-gonic/gin"
)

type Server struct {
}

func (s *Server) Run() error {
	go s.startServer()
	return nil
}

func (s *Server) startServer() {
	ctrl := controller.NewController()

	r := gin.Default()

	r.POST("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"pong": "ok",
		})
	})

	r.POST("/registration", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"token": "1234",
		})
	})

	api(&r.RouterGroup, "/login", ctrl.Login)
	api(&r.RouterGroup, "/events", ctrl.GetEvents)
	room := r.Group("/room/:room_id")
	{
		room.GET("/ws_chat", func(c *gin.Context) {
			room_id := c.Param("room_id")
			s := websocket.Server{Handler: websocket.Handler(ctrl.StartChatWS(room_id))}
			s.ServeHTTP(c.Writer, c.Request)
			// handler := websocket.Handler(ctrl.StartChatWS(room_id))
			// handler.ServeHTTP(c.Writer, c.Request)
		})
	}
	endless.ListenAndServe(":19888", r)
}

func (s *Server) Stop() {

}

func api(g *gin.RouterGroup, path string, f func(b controller.Binder) (int, *controller.R)) {
	g.POST(path, func(c *gin.Context) {
		i, r := f(c)
		c.JSON(i, r)
	})
}
<commit_msg>headers in websocket<commit_after>package server

import (
	"net/http"
	"server/controller"

	"golang.org/x/net/websocket"

	"github.com/fvbock/endless"
	"github.com/gin-gonic/gin"
)

type Server struct {
}

func (s *Server) Run() error {
	go s.startServer()
	return nil
}

func (s *Server) startServer() {
	ctrl := controller.NewController()

	r := gin.Default()

	r.POST("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"pong": "ok",
		})
	})

	r.POST("/registration", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"token": "1234",
		})
	})

	api(&r.RouterGroup, "/login", ctrl.Login)
	api(&r.RouterGroup, "/events", ctrl.GetEvents)
	room := r.Group("/room/:room_id")
	{
		room.GET("/ws_chat", func(c *gin.Context) {
			room_id := c.Param("room_id")
			s := websocket.Server{
				Handler: websocket.Handler(ctrl.StartChatWS(room_id)),
				Config: websocket.Config{
					Header: http.Header{
						"Access-Control-Allow-Credentials": []string{"true"},
						"Access-Control-Allow-Headers":     []string{"x-websocket-protocol", "x-websocket-version", "x-websocket-extensions", "content-type", "authorization"},
						"Access-Control-Allow-Origin":      []string{"http://176.112.197.64"},
					},
				},
			}
			s.ServeHTTP(c.Writer, c.Request)
			// handler := websocket.Handler(ctrl.StartChatWS(room_id))
			// handler.ServeHTTP(c.Writer, c.Request)
		})
	}
	endless.ListenAndServe(":19888", r)
}

func (s *Server) Stop() {

}

func api(g *gin.RouterGroup, path string, f func(b controller.Binder) (int, *controller.R)) {
	g.POST(path, func(c *gin.Context) {
		i, r := f(c)
		c.JSON(i, r)
	})
}
<|endoftext|>


<commit_before>package todolist

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
)

type FileStore struct {
	FileLocation string
	Loaded       bool
}

func NewFileStore() *FileStore {
	return &FileStore{FileLocation: "", Loaded: false}
}

func (f *FileStore) Initialize() {
	if f.FileLocation == "" {
		f.FileLocation = ".todos.json"
	}

	_, err := ioutil.ReadFile(f.FileLocation)
	if err == nil {
		fmt.Println("It looks like a .todos.json file already exists!  Doing nothing.")
		os.Exit(0)
	}
	if err := ioutil.WriteFile(f.FileLocation, []byte("[]"), 0644); err != nil {
		fmt.Println("Error writing json file", err)
		os.Exit(1)
	}
	fmt.Println("Todo repo initialized.")
}

func (f *FileStore) Load() ([]*Todo, error) {
	if f.FileLocation == "" {
		f.FileLocation = getLocation()
	}

	data, err := ioutil.ReadFile(f.FileLocation)
	if err != nil {
		fmt.Println("No todo file found!")
		fmt.Println("Initialize a new todo repo by running 'todo init'")
		return nil, err
		os.Exit(0)
	}

	var todos []*Todo
	jerr := json.Unmarshal(data, &todos)
	if jerr != nil {
		fmt.Println("Error reading json data", jerr)
		return nil, jerr
		os.Exit(1)
	}
	f.Loaded = true

	return todos, nil
}

func (f *FileStore) Save(todos []*Todo) {
	data, _ := json.Marshal(todos)
	if err := ioutil.WriteFile(f.FileLocation, []byte(data), 0644); err != nil {
		fmt.Println("Error writing json file", err)
	}
}

func getLocation() string {
	localrepo := ".todos.json"
	usr, _ := user.Current()
	homerepo := fmt.Sprintf("%s/.todos.json", usr.HomeDir)
	_, ferr := os.Stat(localrepo)

	if ferr == nil {
		return localrepo
	} else {
		return homerepo
	}
}

<commit_msg>Remove return statements to silence linter warning<commit_after>package todolist

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
)

type FileStore struct {
	FileLocation string
	Loaded       bool
}

func NewFileStore() *FileStore {
	return &FileStore{FileLocation: "", Loaded: false}
}

func (f *FileStore) Initialize() {
	if f.FileLocation == "" {
		f.FileLocation = ".todos.json"
	}

	_, err := ioutil.ReadFile(f.FileLocation)
	if err == nil {
		fmt.Println("It looks like a .todos.json file already exists!  Doing nothing.")
		os.Exit(0)
	}
	if err := ioutil.WriteFile(f.FileLocation, []byte("[]"), 0644); err != nil {
		fmt.Println("Error writing json file", err)
		os.Exit(1)
	}
	fmt.Println("Todo repo initialized.")
}

func (f *FileStore) Load() ([]*Todo, error) {
	if f.FileLocation == "" {
		f.FileLocation = getLocation()
	}

	data, err := ioutil.ReadFile(f.FileLocation)
	if err != nil {
		fmt.Println("No todo file found!")
		fmt.Println("Initialize a new todo repo by running 'todo init'")
		os.Exit(0)
	}

	var todos []*Todo
	jerr := json.Unmarshal(data, &todos)
	if jerr != nil {
		fmt.Println("Error reading json data", jerr)
		os.Exit(1)
	}
	f.Loaded = true

	return todos, nil
}

func (f *FileStore) Save(todos []*Todo) {
	data, _ := json.Marshal(todos)
	if err := ioutil.WriteFile(f.FileLocation, []byte(data), 0644); err != nil {
		fmt.Println("Error writing json file", err)
	}
}

func getLocation() string {
	localrepo := ".todos.json"
	usr, _ := user.Current()
	homerepo := fmt.Sprintf("%s/.todos.json", usr.HomeDir)
	_, ferr := os.Stat(localrepo)

	if ferr == nil {
		return localrepo
	} else {
		return homerepo
	}
}

<|endoftext|>


<commit_before>package mapstructure

import (
	"reflect"
	"testing"
)

// GH-1
func TestDecode_NilValue(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name   string
		in     interface{}
		target interface{}
		out    interface{}
	}{
		{
			"all nil",
			&map[string]interface{}{
				"vfoo":   nil,
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "", Vother: nil},
		},
		{
			"partial nil",
			&map[string]interface{}{
				"vfoo":   "baz",
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "baz", Vother: nil},
		},
		{
			"missing values",
			&map[string]interface{}{
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "foo", Vother: nil},
		},
	}

	decode := func(m interface{}, rawVal interface{}) error {
		config := &DecoderConfig{
			Metadata:   nil,
			Result:     rawVal,
			ZeroFields: true,
		}

		decoder, err := NewDecoder(config)
		if err != nil {
			return err
		}

		return decoder.Decode(m)
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			err := decode(tc.in, tc.target)

			if err != nil {
				t.Fatalf("should not error: %s", err)
			}

			if !reflect.DeepEqual(tc.out, tc.target) {
				t.Fatalf("%q: TestDecode_NilValue() expected: %#v, got: %#v", tc.name, tc.out, tc.target)
			}
		})
	}
}

// GH-10
func TestDecode_mapInterfaceInterface(t *testing.T) {
	decode := func(m interface{}, rawVal interface{}) error {
		config := &DecoderConfig{
			Metadata:   nil,
			Result:     rawVal,
			ZeroFields: true,
		}

		decoder, err := NewDecoder(config)
		if err != nil {
			return err
		}

		return decoder.Decode(m)
	}

	input := map[interface{}]interface{}{
		"vfoo":   nil,
		"vother": nil,
	}

	result := Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}}
	err := decode(input, &result)
	if err != nil {
		t.Fatalf("should not error: %s", err)
	}

	if result.Vfoo != "" {
		t.Fatalf("value should be default: %s", result.Vfoo)
	}

	if result.Vother != nil {
		t.Fatalf("Vother should be nil: %s", result.Vother)
	}
}

// #48
func TestNestedTypePointerWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	result := NestedPointer{
		Vbar: &Basic{
			Vuint: 42,
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}

	// this is the error
	if result.Vbar.Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
	}

}

type NestedSlice struct {
	Vfoo   string
	Vbars  []Basic
	Vempty []Basic
}

// #48
func TestNestedTypeSliceWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbars": []map[string]interface{}{
			{"vstring": "foo", "vint": 42, "vbool": true},
			{"vint": 42, "vbool": true},
		},
		"vempty": []map[string]interface{}{
			{"vstring": "foo", "vint": 42, "vbool": true},
			{"vint": 42, "vbool": true},
		},
	}

	result := NestedSlice{
		Vbars: []Basic{
			{Vuint: 42},
			{Vstring: "foo"},
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbars[0].Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbars[0].Vstring)
	}
	// this is the error
	if result.Vbars[0].Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint)
	}
}

// #48 workaround
func TestNestedTypeWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	result := Nested{
		Vbar: Basic{
			Vuint: 42,
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}

	// this is the error
	if result.Vbar.Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
	}

}

// #67 panic() on extending slices (decodeSlice with disabled ZeroValues)
func TestDecodeSliceToEmptySliceWOZeroing(t *testing.T) {
	t.Parallel()

	type TestStruct struct {
		Vfoo []string
	}

	decode := func(m interface{}, rawVal interface{}) error {
		config := &DecoderConfig{
			Metadata:   nil,
			Result:     rawVal,
			ZeroFields: false,
		}

		decoder, err := NewDecoder(config)
		if err != nil {
			return err
		}

		return decoder.Decode(m)
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"1"},
		}

		result := &TestStruct{}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"1"},
		}

		result := &TestStruct{
			Vfoo: []string{},
		}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"2", "3"},
		}

		result := &TestStruct{
			Vfoo: []string{"1"},
		}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}
}

// #70
func TestNextSquashMapstructure(t *testing.T) {
	data := &struct {
		Level1 struct {
			Level2 struct {
				Foo string
			} `mapstructure:",squash"`
		} `mapstructure:",squash"`
	}{}
	err := Decode(map[interface{}]interface{}{"foo": "baz"}, &data)
	if err != nil {
		t.Fatalf("should not error: %s", err)
	}
	if data.Level1.Level2.Foo != "baz" {
		t.Fatal("value should be baz")
	}
}
<commit_msg>Refactor tests<commit_after>package mapstructure

import (
	"reflect"
	"testing"
)

// GH-1, GH-10, GH-96
func TestDecode_NilValue(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name   string
		in     interface{}
		target interface{}
		out    interface{}
	}{
		{
			"all nil",
			&map[string]interface{}{
				"vfoo":   nil,
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "", Vother: nil},
		},
		{
			"partial nil",
			&map[string]interface{}{
				"vfoo":   "baz",
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "baz", Vother: nil},
		},
		{
			"partial decode",
			&map[string]interface{}{
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "foo", Vother: nil},
		},
		{
			"map interface all nil",
			&map[interface{}]interface{}{
				"vfoo":   nil,
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "", Vother: nil},
		},
		{
			"map interface partial nil",
			&map[string]interface{}{
				"vfoo":   "baz",
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "baz", Vother: nil},
		},
		{
			"map interface partial decode",
			&map[string]interface{}{
				"vother": nil,
			},
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
			&Map{Vfoo: "foo", Vother: nil},
		},
	}

	decode := func(m interface{}, rawVal interface{}) error {
		config := &DecoderConfig{
			Metadata:   nil,
			Result:     rawVal,
			ZeroFields: true,
		}

		decoder, err := NewDecoder(config)
		if err != nil {
			return err
		}

		return decoder.Decode(m)
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			err := decode(tc.in, tc.target)

			if err != nil {
				t.Fatalf("should not error: %s", err)
			}

			if !reflect.DeepEqual(tc.out, tc.target) {
				t.Fatalf("%q: TestDecode_NilValue() expected: %#v, got: %#v", tc.name, tc.out, tc.target)
			}
		})
	}
}

// #48
func TestNestedTypePointerWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	result := NestedPointer{
		Vbar: &Basic{
			Vuint: 42,
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}

	// this is the error
	if result.Vbar.Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
	}

}

type NestedSlice struct {
	Vfoo   string
	Vbars  []Basic
	Vempty []Basic
}

// #48
func TestNestedTypeSliceWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbars": []map[string]interface{}{
			{"vstring": "foo", "vint": 42, "vbool": true},
			{"vint": 42, "vbool": true},
		},
		"vempty": []map[string]interface{}{
			{"vstring": "foo", "vint": 42, "vbool": true},
			{"vint": 42, "vbool": true},
		},
	}

	result := NestedSlice{
		Vbars: []Basic{
			{Vuint: 42},
			{Vstring: "foo"},
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbars[0].Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbars[0].Vstring)
	}
	// this is the error
	if result.Vbars[0].Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint)
	}
}

// #48 workaround
func TestNestedTypeWithDefaults(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	result := Nested{
		Vbar: Basic{
			Vuint: 42,
		},
	}
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}

	// this is the error
	if result.Vbar.Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
	}

}

// #67 panic() on extending slices (decodeSlice with disabled ZeroValues)
func TestDecodeSliceToEmptySliceWOZeroing(t *testing.T) {
	t.Parallel()

	type TestStruct struct {
		Vfoo []string
	}

	decode := func(m interface{}, rawVal interface{}) error {
		config := &DecoderConfig{
			Metadata:   nil,
			Result:     rawVal,
			ZeroFields: false,
		}

		decoder, err := NewDecoder(config)
		if err != nil {
			return err
		}

		return decoder.Decode(m)
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"1"},
		}

		result := &TestStruct{}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"1"},
		}

		result := &TestStruct{
			Vfoo: []string{},
		}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}

	{
		input := map[string]interface{}{
			"vfoo": []string{"2", "3"},
		}

		result := &TestStruct{
			Vfoo: []string{"1"},
		}

		err := decode(input, &result)
		if err != nil {
			t.Fatalf("got an err: %s", err.Error())
		}
	}
}

// #70
func TestNextSquashMapstructure(t *testing.T) {
	data := &struct {
		Level1 struct {
			Level2 struct {
				Foo string
			} `mapstructure:",squash"`
		} `mapstructure:",squash"`
	}{}
	err := Decode(map[interface{}]interface{}{"foo": "baz"}, &data)
	if err != nil {
		t.Fatalf("should not error: %s", err)
	}
	if data.Level1.Level2.Foo != "baz" {
		t.Fatal("value should be baz")
	}
}
<|endoftext|>