<commit_before>package main

import (
	"bitbucket.org/kardianos/osext"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fgrehm/devstep-cli/devstep"
	"github.com/segmentio/go-prompt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	project devstep.Project
	client  devstep.DockerClient
)

var commands = []cli.Command{
	hackCmd,
	buildCmd,
	bootstrapCmd,
	infoCmd,
	runCmd,
	binstubsCmd,
	cleanCmd,
	pristineCmd,
}

func main() {
	app := cli.NewApp()
	app.Name = "devstep"
	app.Author = "Fábio Rehm"
	app.Email = "fgrehm@gmail.com"
	app.Usage = "development environments made easy"
	app.Version = "0.2.0"
	app.EnableBashCompletion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "log-level, l", Value: "warning", Usage: "log level", EnvVar: "DEVSTEP_LOG"},
	}
	app.Before = func(c *cli.Context) error {
		return devstep.SetLogLevel(c.GlobalString("log-level"))
	}
	app.Commands = commands

	app.RunAndExitOnError()
}

var dockerRunFlags = []cli.Flag{
	cli.StringFlag{Name: "w, working_dir", Usage: "Working directory inside the container"},
	cli.StringSliceFlag{Name: "p, publish", Value: &cli.StringSlice{}, Usage: "Publish a container's port to the host (hostPort:containerPort)"},
	cli.StringSliceFlag{Name: "link", Value: &cli.StringSlice{}, Usage: "Add link to another container (name:alias)"},
	cli.StringSliceFlag{Name: "e, env", Value: &cli.StringSlice{}, Usage: "Set environment variables"},
	cli.BoolFlag{Name: "privileged", Usage: "Give extended privileges to this container"},
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}

	homeDir := os.Getenv("HOME")
	client = devstep.NewClient(dockerHost)
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}

func newProject() devstep.Project {
	config := loadConfig()
	project, _ = devstep.NewProject(config)
	return project
}

var buildCmd = cli.Command{
	Name:  "build",
	Usage: "build a docker image for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		err := newProject().Build(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var bootstrapCmd = cli.Command{
	Name:  "bootstrap",
	Usage: "bootstrap an environment for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		err := newProject().Bootstrap(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var hackCmd = cli.Command{
	Name:  "hack",
	Usage: "start a hacking session for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		runOpts := parseRunOpts(c)
		err := project.Hack(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var runCmd = cli.Command{
	Name:  "run",
	Usage: "Run a one off command against the current base image",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		runOpts := parseRunOpts(c)
		runOpts.Cmd = c.Args()

		// Validate command
		if len(runOpts.Cmd) == 0 {
			fmt.Printf("No command provided to `devstep run`\n\n")
			cli.ShowCommandHelp(c, "run")
			os.Exit(1)
		}

		if cmd, ok := commands[runOpts.Cmd[0]]; ok {
			runOpts = cmd.Merge(runOpts)
			runOpts.Cmd = append(cmd.Cmd, runOpts.Cmd[1:]...)
		}

		// Prepend a `--` so that it doesn't interfere with the current init
		// process args
		runOpts.Cmd = append([]string{"--"}, runOpts.Cmd...)

		result, err := project.Run(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		os.Exit(result.ExitCode)
	},
}

var binstubsCmd = cli.Command{
	Name:  "binstubs",
	Usage: "Generate binstubs for the commands specified on devstep.yml",
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		if len(commands) == 0 {
			fmt.Println("No binstubs specified!")
			os.Exit(0)
		}

		binstubsPath := ".devstep/bin"
		os.MkdirAll("./"+binstubsPath, 0700)

		executable, _ := osext.Executable()

		for _, cmd := range commands {
			script := []byte("#!/usr/bin/env bash\neval \"" + executable + " run -- " + cmd.Name + " $@\"")
			err := ioutil.WriteFile(binstubsPath+"/"+cmd.Name, script, 0755)
			if err != nil {
				fmt.Printf("Error creating binstub '%s'\n%s\n", binstubsPath+"/"+cmd.Name, err)
				os.Exit(1)
			}
			fmt.Printf("Generated binstub for '%s' in '%s'\n", cmd.Name, binstubsPath)
		}
	},
}

var cleanCmd = cli.Command{
	Name:  "clean",
	Usage: "remove previously built images for the current environment",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip confirmation"},
	},
	Action: func(c *cli.Context) {
		if !c.Bool("force") {
			if ok := prompt.Confirm("Are you sure? [N/y] "); !ok {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}

		err := newProject().Clean(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var pristineCmd = cli.Command{
	Name:  "pristine",
	Usage: "rebuild project image from scratch",
	Flags: append(
		[]cli.Flag{cli.BoolFlag{Name: "force, f", Usage: "skip clean confirmation"}},
		dockerRunFlags...,
	),
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		// TODO: Figure out if this is the right way to invoke other CLI actions
		cleanCmd.Action(c)
		buildCmd.Action(c)
	},
}

var infoCmd = cli.Command{
	Name:  "info",
	Usage: "show information about the current environment",
	Action: func(c *cli.Context) {
		config := loadConfig()
		printConfig(config)
	},
}

func printConfig(config *devstep.ProjectConfig) {
	fmt.Println("==> Project info")
	fmt.Printf("Repository:   %s\n", config.RepositoryName)
	fmt.Printf("Source image: %s\n", config.SourceImage)
	fmt.Printf("Base image:   %s\n", config.BaseImage)
	fmt.Printf("Host dir:     %s\n", config.HostDir)
	fmt.Printf("Guest dir:    %s\n", config.GuestDir)
	fmt.Printf("Cache dir:    %s\n", config.CacheDir)

	if config.Defaults != nil {
		fmt.Println("\n==> Default options:")
		printDockerRunOpts(config.Defaults, "")
	}

	if config.HackOpts != nil {
		fmt.Println("\n==> Hack options:")
		printDockerRunOpts(config.HackOpts, "")
	}
	if config.Commands != nil {
		fmt.Println("\n==> Commands:")
		for _, cmd := range config.Commands {
			fmt.Printf("* %s\n", cmd.Name)
			fmt.Printf("  Cmd:        %v\n", cmd.Cmd)
			fmt.Printf("  Publish:    %v\n", cmd.Publish)
			printDockerRunOpts(&cmd.DockerRunOpts, "  ")
		}
	}
}

func printDockerRunOpts(opts *devstep.DockerRunOpts, prefix string) {
	privileged := false
	if opts.Privileged != nil {
		privileged = *opts.Privileged
	}
	fmt.Printf("%sPrivileged: %v\n", prefix, privileged)
	fmt.Printf("%sLinks:      %v\n", prefix, opts.Links)
	fmt.Printf("%sVolumes:    %v\n", prefix, opts.Volumes)
	fmt.Printf("%sEnv:        %v\n", prefix, opts.Env)
}

func parseRunOpts(c *cli.Context) *devstep.DockerRunOpts {
	runOpts := &devstep.DockerRunOpts{
		Publish: c.StringSlice("publish"),
		Links:   c.StringSlice("link"),
		Env:     make(map[string]string),
	}

	// Only set the privileged config if it was provided
	if c.IsSet("privileged") {
		privileged := c.Bool("privileged")
		runOpts.Privileged = &privileged
	}

	// Set working dir directly on the project object so that it get passed
	// along properly
	if workingDir := c.String("working_dir"); workingDir != "" {
		project.Config().GuestDir = workingDir
	}

	// Env vars
	for _, envVar := range c.StringSlice("env") {
		varAndValue := strings.Split(envVar, "=")
		runOpts.Env[varAndValue[0]] = varAndValue[1]
	}

	// Validate ports
	validPort := regexp.MustCompile(`^\d+:\d+$`)
	for _, port := range runOpts.Publish {
		if !validPort.MatchString(port) {
			fmt.Println("Invalid publish arg: " + port)
			os.Exit(1)
		}
	}
	// Validate links
	validLink := regexp.MustCompile(`[^:]+:[^:]+`)
	for _, link := range runOpts.Links {
		if !validLink.MatchString(link) {
			fmt.Println("Invalid link: " + link)
			os.Exit(1)
		}
	}
	return runOpts
}
<commit_msg>Support for `--bootstrap` for the `pristine` cmd<commit_after>package main

import (
	"bitbucket.org/kardianos/osext"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fgrehm/devstep-cli/devstep"
	"github.com/segmentio/go-prompt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	project devstep.Project
	client  devstep.DockerClient
)

var commands = []cli.Command{
	hackCmd,
	buildCmd,
	bootstrapCmd,
	infoCmd,
	runCmd,
	binstubsCmd,
	cleanCmd,
	pristineCmd,
}

func main() {
	app := cli.NewApp()
	app.Name = "devstep"
	app.Author = "Fábio Rehm"
	app.Email = "fgrehm@gmail.com"
	app.Usage = "development environments made easy"
	app.Version = "0.2.0"
	app.EnableBashCompletion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "log-level, l", Value: "warning", Usage: "log level", EnvVar: "DEVSTEP_LOG"},
	}
	app.Before = func(c *cli.Context) error {
		return devstep.SetLogLevel(c.GlobalString("log-level"))
	}
	app.Commands = commands

	app.RunAndExitOnError()
}

var dockerRunFlags = []cli.Flag{
	cli.StringFlag{Name: "w, working_dir", Usage: "Working directory inside the container"},
	cli.StringSliceFlag{Name: "p, publish", Value: &cli.StringSlice{}, Usage: "Publish a container's port to the host (hostPort:containerPort)"},
	cli.StringSliceFlag{Name: "link", Value: &cli.StringSlice{}, Usage: "Add link to another container (name:alias)"},
	cli.StringSliceFlag{Name: "e, env", Value: &cli.StringSlice{}, Usage: "Set environment variables"},
	cli.BoolFlag{Name: "privileged", Usage: "Give extended privileges to this container"},
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}

	homeDir := os.Getenv("HOME")
	client = devstep.NewClient(dockerHost)
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}

func newProject() devstep.Project {
	config := loadConfig()
	project, _ = devstep.NewProject(config)
	return project
}

var buildCmd = cli.Command{
	Name:  "build",
	Usage: "build a docker image for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		err := newProject().Build(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var bootstrapCmd = cli.Command{
	Name:  "bootstrap",
	Usage: "bootstrap an environment for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		err := newProject().Bootstrap(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var hackCmd = cli.Command{
	Name:  "hack",
	Usage: "start a hacking session for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		runOpts := parseRunOpts(c)
		err := project.Hack(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var runCmd = cli.Command{
	Name:  "run",
	Usage: "Run a one off command against the current base image",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		runOpts := parseRunOpts(c)
		runOpts.Cmd = c.Args()

		// Validate command
		if len(runOpts.Cmd) == 0 {
			fmt.Printf("No command provided to `devstep run`\n\n")
			cli.ShowCommandHelp(c, "run")
			os.Exit(1)
		}

		if cmd, ok := commands[runOpts.Cmd[0]]; ok {
			runOpts = cmd.Merge(runOpts)
			runOpts.Cmd = append(cmd.Cmd, runOpts.Cmd[1:]...)
		}

		// Prepend a `--` so that it doesn't interfere with the current init
		// process args
		runOpts.Cmd = append([]string{"--"}, runOpts.Cmd...)

		result, err := project.Run(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		os.Exit(result.ExitCode)
	},
}

var binstubsCmd = cli.Command{
	Name:  "binstubs",
	Usage: "Generate binstubs for the commands specified on devstep.yml",
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		if len(commands) == 0 {
			fmt.Println("No binstubs specified!")
			os.Exit(0)
		}

		binstubsPath := ".devstep/bin"
		os.MkdirAll("./"+binstubsPath, 0700)

		executable, _ := osext.Executable()

		for _, cmd := range commands {
			script := []byte("#!/usr/bin/env bash\neval \"" + executable + " run -- " + cmd.Name + " $@\"")
			err := ioutil.WriteFile(binstubsPath+"/"+cmd.Name, script, 0755)
			if err != nil {
				fmt.Printf("Error creating binstub '%s'\n%s\n", binstubsPath+"/"+cmd.Name, err)
				os.Exit(1)
			}
			fmt.Printf("Generated binstub for '%s' in '%s'\n", cmd.Name, binstubsPath)
		}
	},
}

var cleanCmd = cli.Command{
	Name:  "clean",
	Usage: "remove previously built images for the current environment",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip confirmation"},
	},
	Action: func(c *cli.Context) {
		if !c.Bool("force") {
			if ok := prompt.Confirm("Are you sure? [y/n]"); !ok {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}

		err := newProject().Clean(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var pristineCmd = cli.Command{
	Name:  "pristine",
	Usage: "rebuild project image from scratch",
	Flags: append(
		[]cli.Flag{
			cli.BoolFlag{Name: "force, f", Usage: "skip clean confirmation"},
			cli.BoolFlag{Name: "bootstrap, b", Usage: "manually bootstrap your environment"},
		},
		dockerRunFlags...,
	),
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		// TODO: Figure out if this is the right way to invoke other CLI actions
		cleanCmd.Action(c)
		if c.Bool("bootstrap") {
			bootstrapCmd.Action(c)
		} else {
			buildCmd.Action(c)
		}
	},
}

var infoCmd = cli.Command{
	Name:  "info",
	Usage: "show information about the current environment",
	Action: func(c *cli.Context) {
		config := loadConfig()
		printConfig(config)
	},
}

func printConfig(config *devstep.ProjectConfig) {
	fmt.Println("==> Project info")
	fmt.Printf("Repository:   %s\n", config.RepositoryName)
	fmt.Printf("Source image: %s\n", config.SourceImage)
	fmt.Printf("Base image:   %s\n", config.BaseImage)
	fmt.Printf("Host dir:     %s\n", config.HostDir)
	fmt.Printf("Guest dir:    %s\n", config.GuestDir)
	fmt.Printf("Cache dir:    %s\n", config.CacheDir)

	if config.Defaults != nil {
		fmt.Println("\n==> Default options:")
		printDockerRunOpts(config.Defaults, "")
	}

	if config.HackOpts != nil {
		fmt.Println("\n==> Hack options:")
		printDockerRunOpts(config.HackOpts, "")
	}
	if config.Commands != nil {
		fmt.Println("\n==> Commands:")
		for _, cmd := range config.Commands {
			fmt.Printf("* %s\n", cmd.Name)
			fmt.Printf("  Cmd:        %v\n", cmd.Cmd)
			fmt.Printf("  Publish:    %v\n", cmd.Publish)
			printDockerRunOpts(&cmd.DockerRunOpts, "  ")
		}
	}
}

func printDockerRunOpts(opts *devstep.DockerRunOpts, prefix string) {
	privileged := false
	if opts.Privileged != nil {
		privileged = *opts.Privileged
	}
	fmt.Printf("%sPrivileged: %v\n", prefix, privileged)
	fmt.Printf("%sLinks:      %v\n", prefix, opts.Links)
	fmt.Printf("%sVolumes:    %v\n", prefix, opts.Volumes)
	fmt.Printf("%sEnv:        %v\n", prefix, opts.Env)
}

func parseRunOpts(c *cli.Context) *devstep.DockerRunOpts {
	runOpts := &devstep.DockerRunOpts{
		Publish: c.StringSlice("publish"),
		Links:   c.StringSlice("link"),
		Env:     make(map[string]string),
	}

	// Only set the privileged config if it was provided
	if c.IsSet("privileged") {
		privileged := c.Bool("privileged")
		runOpts.Privileged = &privileged
	}

	// Set working dir directly on the project object so that it get passed
	// along properly
	if workingDir := c.String("working_dir"); workingDir != "" {
		project.Config().GuestDir = workingDir
	}

	// Env vars
	for _, envVar := range c.StringSlice("env") {
		varAndValue := strings.Split(envVar, "=")
		runOpts.Env[varAndValue[0]] = varAndValue[1]
	}

	// Validate ports
	validPort := regexp.MustCompile(`^\d+:\d+$`)
	for _, port := range runOpts.Publish {
		if !validPort.MatchString(port) {
			fmt.Println("Invalid publish arg: " + port)
			os.Exit(1)
		}
	}
	// Validate links
	validLink := regexp.MustCompile(`[^:]+:[^:]+`)
	for _, link := range runOpts.Links {
		if !validLink.MatchString(link) {
			fmt.Println("Invalid link: " + link)
			os.Exit(1)
		}
	}
	return runOpts
}
<|endoftext|>


<commit_before>// Copyright 2016 Jacob Taylor jacob@ablox.io
// License: Apache2 - http://www.apache.org/licenses/LICENSE-2.0
package main

import (
	"fmt"
	"github.com/rjeczalik/notify"
	"github.com/urfave/cli"
	"log"
	"os"
	"path/filepath"
)

// settings for the server
type Settings struct {
	Directory string

}

var globalSettings Settings = Settings{
	Directory: "",
}

func main() {
	fmt.Println("replicat initializing....")

	app := cli.NewApp()
	app.Name = "Replicat"
	app.Usage = "rsync for the cloud"
	app.Action = func(c *cli.Context) error {
		globalSettings.Directory = c.GlobalString("directory")

		if globalSettings.Directory == "" {
			panic("directory is required to serve files\n")
		}

		return nil
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "directory, d",
			Value:  globalSettings.Directory,
			Usage:  "Specify a directory where the files to share are located.",
			EnvVar: "DIRECTORY",
		},
	}

	app.Run(os.Args)

	listOfFileInfo, err := createListOfFolders(globalSettings.Directory)
	if err != nil {
		log.Fatal(err)
	}

	// Make the channel buffered to ensure no event is dropped. Notify will drop
	// an event if the receiver is not able to keep up the sending pace.
	fsEventsChannel := make(chan notify.EventInfo, 1)

	// Set up a watchpoint listening for events within a directory tree rooted at the specified folder
	if err := notify.Watch(globalSettings.Directory + "/...", fsEventsChannel, notify.All); err != nil {
		log.Fatal(err)
	}
	defer notify.Stop(fsEventsChannel)

	fmt.Println("replicat online....")
	defer fmt.Println("End of line")

	fmt.Printf("Now listening on: %d folders under: %s\n", len(listOfFileInfo), globalSettings.Directory)

	totalFiles := 0
	for _, fileInfoList := range listOfFileInfo {
		totalFiles += len(fileInfoList)
	}

	fmt.Printf("Tracking %d folders with %d files\n", len(listOfFileInfo), totalFiles)

	func(c chan notify.EventInfo) {
		for {
			ei := <-c
			log.Println("Got event:", ei)
		}
	}(fsEventsChannel)
}

func createListOfFolders(basePath string) (map[string][]os.FileInfo, error) {
	paths := make([]string, 0, 100)
	pendingPaths := make([]string, 0, 100)
	pendingPaths = append(pendingPaths, basePath)
	listOfFileInfo := make(map[string][]os.FileInfo)

	for len(pendingPaths) > 0 {
		currentPath := pendingPaths[0]
		paths = append(paths, currentPath)
		fileList := make([]os.FileInfo, 0, 100)
		pendingPaths = pendingPaths[1:]

		// Read the directories in the path
		f, err := os.Open(currentPath)
		if err != nil {
			return nil, err
		}
		dirEntries, err := f.Readdir(-1)
		for _, entry := range dirEntries {
			if entry.IsDir() {
				entry.Mode()
				newDirectory := filepath.Join(currentPath, entry.Name())
				pendingPaths = append(pendingPaths, newDirectory)
			} else {
				fileList = append(fileList, entry)
			}
		}
		f.Close()
		if err != nil {
			return nil, err
		}

		listOfFileInfo[currentPath] = fileList
	}

	return listOfFileInfo, nil
}
<commit_msg>allowing short variable name from environment variable<commit_after>// Copyright 2016 Jacob Taylor jacob@ablox.io
// License: Apache2 - http://www.apache.org/licenses/LICENSE-2.0
package main

import (
	"fmt"
	"github.com/rjeczalik/notify"
	"github.com/urfave/cli"
	"log"
	"os"
	"path/filepath"
)

// settings for the server
type Settings struct {
	Directory string

}

var globalSettings Settings = Settings{
	Directory: "",
}

func main() {
	fmt.Println("replicat initializing....")

	app := cli.NewApp()
	app.Name = "Replicat"
	app.Usage = "rsync for the cloud"
	app.Action = func(c *cli.Context) error {
		globalSettings.Directory = c.GlobalString("directory")

		if globalSettings.Directory == "" {
			panic("directory is required to serve files\n")
		}

		return nil
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "directory, d",
			Value:  globalSettings.Directory,
			Usage:  "Specify a directory where the files to share are located.",
			EnvVar: "DIRECTORY, d",
		},
	}

	app.Run(os.Args)

	listOfFileInfo, err := createListOfFolders(globalSettings.Directory)
	if err != nil {
		log.Fatal(err)
	}

	// Make the channel buffered to ensure no event is dropped. Notify will drop
	// an event if the receiver is not able to keep up the sending pace.
	fsEventsChannel := make(chan notify.EventInfo, 1)

	// Set up a watchpoint listening for events within a directory tree rooted at the specified folder
	if err := notify.Watch(globalSettings.Directory + "/...", fsEventsChannel, notify.All); err != nil {
		log.Fatal(err)
	}
	defer notify.Stop(fsEventsChannel)

	fmt.Println("replicat online....")
	defer fmt.Println("End of line")

	fmt.Printf("Now listening on: %d folders under: %s\n", len(listOfFileInfo), globalSettings.Directory)

	totalFiles := 0
	for _, fileInfoList := range listOfFileInfo {
		totalFiles += len(fileInfoList)
	}

	fmt.Printf("Tracking %d folders with %d files\n", len(listOfFileInfo), totalFiles)

	func(c chan notify.EventInfo) {
		for {
			ei := <-c
			log.Println("Got event:", ei)
		}
	}(fsEventsChannel)
}

func createListOfFolders(basePath string) (map[string][]os.FileInfo, error) {
	paths := make([]string, 0, 100)
	pendingPaths := make([]string, 0, 100)
	pendingPaths = append(pendingPaths, basePath)
	listOfFileInfo := make(map[string][]os.FileInfo)

	for len(pendingPaths) > 0 {
		currentPath := pendingPaths[0]
		paths = append(paths, currentPath)
		fileList := make([]os.FileInfo, 0, 100)
		pendingPaths = pendingPaths[1:]

		// Read the directories in the path
		f, err := os.Open(currentPath)
		if err != nil {
			return nil, err
		}
		dirEntries, err := f.Readdir(-1)
		for _, entry := range dirEntries {
			if entry.IsDir() {
				entry.Mode()
				newDirectory := filepath.Join(currentPath, entry.Name())
				pendingPaths = append(pendingPaths, newDirectory)
			} else {
				fileList = append(fileList, entry)
			}
		}
		f.Close()
		if err != nil {
			return nil, err
		}

		listOfFileInfo[currentPath] = fileList
	}

	return listOfFileInfo, nil
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"flag"
	"log"
	"math/rand"
	"net"
	"time"
)

var (
	addr  = flag.String("addr", ":10000", "[ip]:port for TCP server")
	debug = flag.Bool("dbg", false, "(debugging only)")
)

func main() {
	flag.Parse()

	log.SetFlags(0)
	log.SetPrefix("tcp-srv ")

	log.Printf("starting up server on: %v\n", *addr)

	srv, err := net.Listen("tcp", *addr)
	if err != nil {
		log.Fatal(err)
	}

	if *debug {
		go runClient(*addr)
	}

	for {
		conn, err := srv.Accept()
		if err != nil {
			log.Printf("error accepting connection: %v\n", err)
			continue
		}
		go handle(conn)
	}
}

func handle(conn net.Conn) {
	defer conn.Close()

	log.Printf("connection from: %v\n", conn.RemoteAddr())

	data, err := fetchData()
	if err != nil {
		log.Printf("error fetching data: %v\n", err)
		return
	}

	err = json.NewEncoder(conn).Encode(data)
	if err != nil {
		log.Printf("error sending json data: %v\n", err)
	}
}

func fetchData() (Sensors, error) {
	if *debug {
		return genData()
	}
	panic("not implemented")
}

type Sensors struct {
	Timestamp time.Time `json:"timestamp"`
	Tsl       Tsl       `json:"tsl"`
	Sht31     Sht31     `json:"sht31"`
	Si7021    [2]Si7021 `json:"si7021"`
	Bme       Bme       `json:"bme280"`
}

type Tsl struct {
	Lux  float64 `json:"lux"`
	Full float64 `json:"full"`
	IR   float64 `json:"ir"`
}

type Sht31 struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
}

type Si7021 struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
}

type Bme struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
	Pres float64 `json:"pres"`
}

func runClient(addr string) {
	tick := time.NewTicker(3 * time.Second)
	defer tick.Stop()

	for range tick.C {

		conn, err := net.Dial("tcp", addr)
		if err != nil {
			log.Fatalf("client error: %v\n", err)
		}
		var data Sensors
		err = json.NewDecoder(conn).Decode(&data)
		conn.Close()
		if err != nil {
			log.Fatalf("client decoding error: %v\n", err)
		}
		log.Printf("--> recv: %v\n", data)
	}
}

func genData() (Sensors, error) {
	var err error
	data := Sensors{
		Timestamp: time.Now().UTC(),
		Tsl: Tsl{
			Lux:  rand.Float64(),
			Full: rand.Float64(),
			IR:   rand.Float64(),
		},
		Sht31: Sht31{
			Temp: rand.Float64(),
			Hum:  rand.Float64(),
		},
		Si7021: [2]Si7021{
			{
				Temp: rand.Float64(),
				Hum:  rand.Float64(),
			},
			{
				Temp: rand.Float64(),
				Hum:  rand.Float64(),
			},
		},
		Bme: Bme{
			Temp: rand.Float64(),
			Hum:  rand.Float64(),
			Pres: rand.Float64(),
		},
	}
	return data, err
}
<commit_msg>tcp-srv: add tsl2591<commit_after>// Copyright 2017 The tcp-srv Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"encoding/json"
	"flag"
	"log"
	"math/rand"
	"net"
	"time"

	"github.com/go-daq/smbus"
	"github.com/go-daq/smbus/sensor/tsl2591"
)

var (
	addr    = flag.String("addr", ":10000", "[ip]:port for TCP server")
	busID   = flag.Int("bus-id", 0x1, "SMBus ID number (/dev/i2c-[ID]")
	busAddr = flag.Int("bus-addr", 0x70, "SMBus address to read/write")
	debug   = flag.Bool("dbg", false, "(debugging only)")
)

func main() {
	flag.Parse()

	log.SetFlags(0)
	log.SetPrefix("tcp-srv ")

	log.Printf("starting up server on: %v\n", *addr)

	srv, err := net.Listen("tcp", *addr)
	if err != nil {
		log.Fatal(err)
	}

	if *debug {
		go runClient(*addr)
	}

	for {
		conn, err := srv.Accept()
		if err != nil {
			log.Printf("error accepting connection: %v\n", err)
			continue
		}
		go handle(conn)
	}
}

func handle(conn net.Conn) {
	defer conn.Close()

	log.Printf("connection from: %v\n", conn.RemoteAddr())

	data, err := fetchData()
	if err != nil {
		log.Printf("error fetching data: %v\n", err)
		return
	}

	err = json.NewEncoder(conn).Encode(data)
	if err != nil {
		log.Printf("error sending json data: %v\n", err)
	}
}

func fetchData() (Sensors, error) {
	if *debug {
		return genData()
	}
	bus, err := smbus.Open(*busID, uint8(*busAddr))
	if err != nil {
		return Sensors{}, err
	}
	defer bus.Close()

	data := Sensors{Timestamp: time.Now().UTC()}
	err = data.read(bus, uint8(*busAddr))
	if err != nil {
		return data, err
	}

	return data, nil
}

type Sensors struct {
	Timestamp time.Time `json:"timestamp"`
	Tsl       Tsl       `json:"tsl"`
	Sht31     Sht31     `json:"sht31"`
	Si7021    [2]Si7021 `json:"si7021"`
	Bme       Bme       `json:"bme280"`
}

func (s *Sensors) read(bus *smbus.Conn, addr uint8) error {
	var err error
	err = s.Tsl.read(bus, addr, 0x0)
	if err != nil {
		return err
	}
	err = s.Sht31.read(bus, addr, 0x1)
	if err != nil {
		return err
	}
	err = s.Si7021[0].read(bus, addr, 0x2)
	if err != nil {
		return err
	}
	err = s.Si7021[1].read(bus, addr, 0x3)
	if err != nil {
		return err
	}
	err = s.Bme.read(bus, addr, 0x4)
	if err != nil {
		return err
	}
	return err
}

type Tsl struct {
	Lux  float64 `json:"lux"`
	Full uint16  `json:"full"`
	IR   uint16  `json:"ir"`
}

func (tsl *Tsl) read(bus *smbus.Conn, addr uint8, ch int) error {
	var err error
	dev, err := tsl2591.Open(bus, tsl2591.Addr, tsl2591.IntegTime100ms, tsl2591.GainLow)
	if err != nil {
		return err
	}

	full, ir, err := dev.FullLuminosity()
	if err != nil {
		return err
	}

	tsl.Lux = dev.Lux(full, ir)
	tsl.Full = full
	tsl.IR = ir

	return err
}

type Sht31 struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
}

func (sht *Sht31) read(bus *smbus.Conn, addr uint8, ch int) error {
	var err error
	return err
}

type Si7021 struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
}

func (si *Si7021) read(bus *smbus.Conn, addr uint8, ch int) error {
	var err error
	return err
}

type Bme struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
	Pres float64 `json:"pres"`
}

func (bme *Bme) read(bus *smbus.Conn, addr uint8, ch int) error {
	var err error
	return err
}

func runClient(addr string) {
	tick := time.NewTicker(3 * time.Second)
	defer tick.Stop()

	for range tick.C {

		conn, err := net.Dial("tcp", addr)
		if err != nil {
			log.Fatalf("client error: %v\n", err)
		}
		var data Sensors
		err = json.NewDecoder(conn).Decode(&data)
		conn.Close()
		if err != nil {
			log.Fatalf("client decoding error: %v\n", err)
		}
		log.Printf("--> recv: %v\n", data)
	}
}

func genData() (Sensors, error) {
	var err error
	data := Sensors{
		Timestamp: time.Now().UTC(),
		Tsl: Tsl{
			Lux:  rand.Float64(),
			Full: uint16(rand.Uint32()),
			IR:   uint16(rand.Uint32()),
		},
		Sht31: Sht31{
			Temp: rand.Float64(),
			Hum:  rand.Float64(),
		},
		Si7021: [2]Si7021{
			{
				Temp: rand.Float64(),
				Hum:  rand.Float64(),
			},
			{
				Temp: rand.Float64(),
				Hum:  rand.Float64(),
			},
		},
		Bme: Bme{
			Temp: rand.Float64(),
			Hum:  rand.Float64(),
			Pres: rand.Float64(),
		},
	}
	return data, err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

var sock string

func parseAddress(uri string) (scheme, path string, err error) {
	u, err := url.Parse(uri)
	if err != nil {
		return scheme, path, err
	}

	scheme = u.Scheme
	path = u.Path
	if path == "" {
		path = u.Host
	}

	return scheme, path, err
}

func parseBody(r io.Reader) (stats map[string]interface{}, err error) {
	scanner := bufio.NewScanner(r)
	stats = make(map[string]interface{})
	for scanner.Scan() {
		p := strings.Split(scanner.Text(), " ")
		if len(p) == 2 {
			stats[strings.Trim(p[0], ":")], err = strconv.ParseFloat(p[1], 64)
		} else {
			stats[strings.Trim(p[len(p)-2], ":")], err = strconv.ParseFloat(p[len(p)-1], 64)
		}
	}

	return stats, err
}

func parseBodyHttp(uri string) (stats map[string]interface{}, err error) {
	var req *http.Request
	req, err = http.NewRequest("GET", uri, nil)
	if err != nil {
		return stats, err
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return stats, err
	}
	defer resp.Body.Close()

	stats, err = parseBody(resp.Body)

	return stats, err
}

func fakeDial(proto, addr string) (conn net.Conn, err error) {
	return net.Dial("unix", sock)
}

func parseBodyUnix(path string) (stats map[string]interface{}, err error) {
	tr := &http.Transport{
		Dial: fakeDial,
	}

	client := &http.Client{Transport: tr}
	resp, err := client.Get(fmt.Sprintf("http://dummy/%s", strings.TrimLeft(path, "/")))

	if err != nil {
		return stats, err
	}
	defer resp.Body.Close()

	stats, err = parseBody(resp.Body)

	return stats, err
}

type RackStatsPlugin struct {
	Address   string
	Path      string
	MetricKey string
}

// FetchMetrics interface for mackerelplugin
func (u RackStatsPlugin) FetchMetrics() (stats map[string]interface{}, err error) {
	stats, err = u.parseStats()
	return stats, err
}

func (u RackStatsPlugin) parseStats() (stats map[string]interface{}, err error) {
	scheme, path, err := parseAddress(u.Address)

	switch scheme {
	case "http":
		stats, err = parseBodyHttp(fmt.Sprintf("%s/%s", u.Address, strings.TrimLeft(u.Path, "/")))
	case "unix":
		sock = path
		stats, err = parseBodyUnix(u.Path)
	}

	return stats, err
}

// GraphDefinition interface for mackerelplugin
func (u RackStatsPlugin) GraphDefinition() map[string](mp.Graphs) {
	scheme, path, err := parseAddress(u.Address)
	if err != nil {
		log.Fatal(err)
	}

	var label string
	if u.MetricKey == "" {
		switch scheme {
		case "http":
			_, port, _ := net.SplitHostPort(path)
			u.MetricKey = port
			label = fmt.Sprintf("Rack Port %s Stats", port)
		case "unix":
			u.MetricKey = strings.Replace(strings.Replace(path, "/", "_", -1), ".", "_", -1)
			label = fmt.Sprintf("Rack %s Stats", path)
		}
	} else {
		label = fmt.Sprintf("Rack %s Stats", u.MetricKey)
	}

	return map[string](mp.Graphs){
		fmt.Sprintf("%s.rack.stats", u.MetricKey): mp.Graphs{
			Label: label,
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "queued", Label: "Queued", Diff: false},
				mp.Metrics{Name: "active", Label: "Active", Diff: false},
				mp.Metrics{Name: "writing", Label: "Writing", Diff: false},
				mp.Metrics{Name: "calling", Label: "Calling", Diff: false},
			},
		},
	}
}

func main() {
	optAddress := flag.String("address", "http://localhost:8080", "URL or Unix Domain Socket")
	optPath := flag.String("path", "/_raindrops", "Path")
	optMetricKey := flag.String("metric-key", "", "Metric Key")
	optVersion := flag.Bool("version", false, "Version")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	if *optVersion {
		fmt.Println("0.2")
		os.Exit(0)
	}

	var rack RackStatsPlugin
	rack.Address = *optAddress
	rack.Path = *optPath
	rack.MetricKey = *optMetricKey

	helper := mp.NewMackerelPlugin(rack)
	if *optTempfile != "" {
		helper.Tempfile = *optTempfile
	} else {
		helper.Tempfile = fmt.Sprintf("/tmp/mackerel-plugin-rack-stats")
	}

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<commit_msg>Use `MackerelPlugin.Run()`<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

var sock string

func parseAddress(uri string) (scheme, path string, err error) {
	u, err := url.Parse(uri)
	if err != nil {
		return scheme, path, err
	}

	scheme = u.Scheme
	path = u.Path
	if path == "" {
		path = u.Host
	}

	return scheme, path, err
}

func parseBody(r io.Reader) (stats map[string]interface{}, err error) {
	scanner := bufio.NewScanner(r)
	stats = make(map[string]interface{})
	for scanner.Scan() {
		p := strings.Split(scanner.Text(), " ")
		if len(p) == 2 {
			stats[strings.Trim(p[0], ":")], err = strconv.ParseFloat(p[1], 64)
		} else {
			stats[strings.Trim(p[len(p)-2], ":")], err = strconv.ParseFloat(p[len(p)-1], 64)
		}
	}

	return stats, err
}

func parseBodyHttp(uri string) (stats map[string]interface{}, err error) {
	var req *http.Request
	req, err = http.NewRequest("GET", uri, nil)
	if err != nil {
		return stats, err
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return stats, err
	}
	defer resp.Body.Close()

	stats, err = parseBody(resp.Body)

	return stats, err
}

func fakeDial(proto, addr string) (conn net.Conn, err error) {
	return net.Dial("unix", sock)
}

func parseBodyUnix(path string) (stats map[string]interface{}, err error) {
	tr := &http.Transport{
		Dial: fakeDial,
	}

	client := &http.Client{Transport: tr}
	resp, err := client.Get(fmt.Sprintf("http://dummy/%s", strings.TrimLeft(path, "/")))

	if err != nil {
		return stats, err
	}
	defer resp.Body.Close()

	stats, err = parseBody(resp.Body)

	return stats, err
}

type RackStatsPlugin struct {
	Address   string
	Path      string
	MetricKey string
}

// FetchMetrics interface for mackerelplugin
func (u RackStatsPlugin) FetchMetrics() (stats map[string]interface{}, err error) {
	stats, err = u.parseStats()
	return stats, err
}

func (u RackStatsPlugin) parseStats() (stats map[string]interface{}, err error) {
	scheme, path, err := parseAddress(u.Address)

	switch scheme {
	case "http":
		stats, err = parseBodyHttp(fmt.Sprintf("%s/%s", u.Address, strings.TrimLeft(u.Path, "/")))
	case "unix":
		sock = path
		stats, err = parseBodyUnix(u.Path)
	}

	return stats, err
}

// GraphDefinition interface for mackerelplugin
func (u RackStatsPlugin) GraphDefinition() map[string](mp.Graphs) {
	scheme, path, err := parseAddress(u.Address)
	if err != nil {
		log.Fatal(err)
	}

	var label string
	if u.MetricKey == "" {
		switch scheme {
		case "http":
			_, port, _ := net.SplitHostPort(path)
			u.MetricKey = port
			label = fmt.Sprintf("Rack Port %s Stats", port)
		case "unix":
			u.MetricKey = strings.Replace(strings.Replace(path, "/", "_", -1), ".", "_", -1)
			label = fmt.Sprintf("Rack %s Stats", path)
		}
	} else {
		label = fmt.Sprintf("Rack %s Stats", u.MetricKey)
	}

	return map[string](mp.Graphs){
		fmt.Sprintf("%s.rack.stats", u.MetricKey): mp.Graphs{
			Label: label,
			Unit:  "integer",
			Metrics: [](mp.Metrics){
				mp.Metrics{Name: "queued", Label: "Queued", Diff: false},
				mp.Metrics{Name: "active", Label: "Active", Diff: false},
				mp.Metrics{Name: "writing", Label: "Writing", Diff: false},
				mp.Metrics{Name: "calling", Label: "Calling", Diff: false},
			},
		},
	}
}

func main() {
	optAddress := flag.String("address", "http://localhost:8080", "URL or Unix Domain Socket")
	optPath := flag.String("path", "/_raindrops", "Path")
	optMetricKey := flag.String("metric-key", "", "Metric Key")
	optVersion := flag.Bool("version", false, "Version")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	if *optVersion {
		fmt.Println("0.2")
		os.Exit(0)
	}

	var rack RackStatsPlugin
	rack.Address = *optAddress
	rack.Path = *optPath
	rack.MetricKey = *optMetricKey

	helper := mp.NewMackerelPlugin(rack)
	if *optTempfile != "" {
		helper.Tempfile = *optTempfile
	} else {
		helper.Tempfile = fmt.Sprintf("/tmp/mackerel-plugin-rack-stats")
	}

	helper.Run()
}
<|endoftext|>


<commit_before>/* Copyright 2016 Andrew O'Neill

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 (
	"context"
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"k8s.io/client-go/1.5/kubernetes"
	"k8s.io/client-go/1.5/pkg/api"
	"k8s.io/client-go/1.5/pkg/api/v1"
	"k8s.io/client-go/1.5/pkg/labels"
	"k8s.io/client-go/1.5/pkg/selection"
	"k8s.io/client-go/1.5/pkg/util/sets"
	"k8s.io/client-go/1.5/pkg/watch"
	"k8s.io/client-go/1.5/rest"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/foolusion/certs"
	"github.com/pkg/errors"
)

const (
	envNamespace = "NAMESPACE"
	envAWSRegion = "AWS_REGION"
)

var sess *session.Session

func main() {
	log.Println("Starting rt53-updater operator...")

	region := os.Getenv(envAWSRegion)
	if region == "" {
		log.Fatalf("you must supply environment variable %s", envAWSRegion)
	}

	namespace := os.Getenv(envNamespace)
	if namespace == "" {
		log.Println("Using all namespaces")
	}

	sess = session.Must(session.NewSession(&aws.Config{
		HTTPClient: &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					RootCAs: certs.Pool,
				},
			},
		},
		Region: aws.String(region),
	}))

	errCh := make(chan error, 1)
	cancel, err := watchService(namespace, errCh)
	if err != nil {
		close(errCh)
		log.Fatal(err)
	}
	defer cancel()

	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	for {
		select {
		case err := <-errCh:
			switch e := errors.Cause(err).(type) {
			case *fatalErr:
				log.Println(e)
				close(sigCh)
				cancel()
				os.Exit(1)
			default:
				log.Println(e)
			}
		case <-sigCh:
			log.Println("Shutdown signal recieved, exiting...")
			close(errCh)
			cancel()
			os.Exit(0)
		}
	}
}

type fatalErr struct {
	err error
}

func (f *fatalErr) Error() string {
	return fmt.Sprintf("fatal error: %s", f.err.Error())
}

func watchService(namespace string, errCh chan<- error) (context.CancelFunc, error) {
	config, err := rest.InClusterConfig()
	if err != nil {
		return nil, errors.Wrap(err, "could not get in cluster config")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "could not create a new in cluster client")
	}

	ls := labels.NewSelector()
	req, err := labels.NewRequirement("route53", selection.Equals, sets.NewString("loadBalancer"))
	if err != nil {
		return nil, errors.Wrap(err, "could not create label requirements")
	}
	ls = ls.Add(*req)
	watcher, err := clientset.Core().Services(namespace).Watch(api.ListOptions{
		LabelSelector: ls,
	})
	if err != nil {
		return nil, errors.Wrap(err, "could not create service watcher")
	}

	ctx, cancel := context.WithCancel(context.Background())

	go serviceWatcher(ctx, watcher, errCh)
	return cancel, nil
}

func serviceWatcher(ctx context.Context, w watch.Interface, errCh chan<- error) {
	for {
		select {
		case ev := <-w.ResultChan():
			err := handleEvent(ev)
			if err != nil {
				errCh <- errors.Wrap(err, "unable to handle event")
			}
		case <-ctx.Done():
			log.Println("recieved cancel on Service watcher")
			return
		}
	}
}

func handleEvent(ev watch.Event) error {
	switch ev.Type {
	case watch.Added, watch.Modified:
		s := ev.Object.(*v1.Service)
		rt, err := updateRoute53(s)
		if err != nil {
			return errors.Wrap(err, "could not get route53 details")
		}
		err = setRoute53(rt)
		if err != nil {
			return errors.Wrap(err, "could not update route53")
		}
		return nil
	default:
		log.Printf("useless event %s", ev)
		return nil
	}
}

func updateRoute53(s *v1.Service) (rt53Config, error) {
	ann := s.GetAnnotations()
	name, ok := ann["foolusion-aws-route53-name"]
	if !ok {
		return rt53Config{}, errors.Errorf("service %s missing annotation %s", s.GetName(), "foolusion-aws-route53-name")
	}

	hostedZone, ok := ann["foolusion-aws-route53-hostedZone"]
	if !ok {
		return rt53Config{}, errors.Errorf("service %s missing annotation %s", s.GetName(), "foolusion-aws-route53-hostedZone")
	}

	rt53Route := route{
		dnsName:      name,
		hostedZoneID: hostedZone,
	}

	if len(s.Status.LoadBalancer.Ingress) != 1 {
		return rt53Config{}, errors.Errorf("LoadBalancer.Ingress != 1 got %v", len(s.Status.LoadBalancer.Ingress))
	}
	loadBalancerHostname := s.Status.LoadBalancer.Ingress[0].Hostname
	if loadBalancerHostname == "" {
		return rt53Config{}, errors.Errorf("service %s missing LoadBalancer.Ingress", s.GetName())
	}

	loadBalancerName := strings.Split(loadBalancerHostname, "-")[1]

	loadBalancerHostedZoneID, err := getLoadBalancerHostedZone(loadBalancerName)
	if err != nil {
		return rt53Config{}, errors.WithMessage(err, "could not get hosted zone ID from load balancer")
	}

	loadBalancerRoute := route{
		dnsName:      loadBalancerHostname,
		hostedZoneID: loadBalancerHostedZoneID,
	}

	return rt53Config{
		rt53:         rt53Route,
		loadBalancer: loadBalancerRoute,
	}, nil
}

type route struct {
	dnsName      string
	hostedZoneID string
}

type rt53Config struct {
	rt53         route
	loadBalancer route
}

func getLoadBalancerHostedZone(name string) (string, error) {
	svc := elb.New(sess)

	params := &elb.DescribeLoadBalancersInput{
		LoadBalancerNames: []*string{
			aws.String(name),
		},
	}
	resp, err := svc.DescribeLoadBalancers(params)
	if err != nil {
		return "", errors.WithMessage(err, "could not describe load balancers")
	}

	if len(resp.LoadBalancerDescriptions) != 1 {
		return "", errors.Wrapf(err, "length of LoadBalancerDescriptions != 1 got %v", len(resp.LoadBalancerDescriptions))
	}

	hostedZoneID := resp.LoadBalancerDescriptions[0].CanonicalHostedZoneNameID
	if hostedZoneID == nil {
		return "", errors.WithMessage(err, "LoadBalancer hostedZoneID is not set")
	}

	return *hostedZoneID, nil
}

func setRoute53(r rt53Config) error {
	svc := route53.New(sess)

	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: []*route53.Change{
				{
					Action: aws.String(route53.ChangeActionCreate),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(r.rt53.dnsName),
						Type: aws.String(route53.RRTypeA),
						AliasTarget: &route53.AliasTarget{
							DNSName:              aws.String(r.loadBalancer.dnsName),
							HostedZoneId:         aws.String(r.loadBalancer.hostedZoneID),
							EvaluateTargetHealth: aws.Bool(false),
						},
					},
				},
			},
		},
		HostedZoneId: aws.String(r.rt53.hostedZoneID),
	}

	resp, err := svc.ChangeResourceRecordSets(params)
	if err != nil {
		return errors.Wrap(err, "could not change record set")
	}

	log.Println(resp)
	return nil
}
<commit_msg>catch watch chan closing<commit_after>/* Copyright 2016 Andrew O'Neill

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 (
	"context"
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"k8s.io/client-go/1.5/kubernetes"
	"k8s.io/client-go/1.5/pkg/api"
	"k8s.io/client-go/1.5/pkg/api/v1"
	"k8s.io/client-go/1.5/pkg/labels"
	"k8s.io/client-go/1.5/pkg/selection"
	"k8s.io/client-go/1.5/pkg/util/sets"
	"k8s.io/client-go/1.5/pkg/watch"
	"k8s.io/client-go/1.5/rest"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/foolusion/certs"
	"github.com/pkg/errors"
)

const (
	envNamespace = "NAMESPACE"
	envAWSRegion = "AWS_REGION"
)

var sess *session.Session

func main() {
	log.Println("Starting rt53-updater operator...")

	region := os.Getenv(envAWSRegion)
	if region == "" {
		log.Fatalf("you must supply environment variable %s", envAWSRegion)
	}

	namespace := os.Getenv(envNamespace)
	if namespace == "" {
		log.Println("Using all namespaces")
	}

	sess = session.Must(session.NewSession(&aws.Config{
		HTTPClient: &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					RootCAs: certs.Pool,
				},
			},
		},
		Region: aws.String(region),
	}))

	errCh := make(chan error, 1)
	cancel, err := watchService(namespace, errCh)
	if err != nil {
		close(errCh)
		log.Fatal(err)
	}
	defer cancel()

	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	for {
		select {
		case err := <-errCh:
			switch e := errors.Cause(err).(type) {
			case *fatalErr:
				log.Println(e)
				close(sigCh)
				cancel()
				os.Exit(1)
			default:
				log.Println(e)
			}
		case <-sigCh:
			log.Println("Shutdown signal recieved, exiting...")
			close(errCh)
			cancel()
			os.Exit(0)
		}
	}
}

type fatalErr struct {
	err error
}

func (f *fatalErr) Error() string {
	return fmt.Sprintf("fatal error: %s", f.err.Error())
}

func watchService(namespace string, errCh chan<- error) (context.CancelFunc, error) {
	config, err := rest.InClusterConfig()
	if err != nil {
		return nil, errors.Wrap(err, "could not get in cluster config")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "could not create a new in cluster client")
	}

	ls := labels.NewSelector()
	req, err := labels.NewRequirement("route53", selection.Equals, sets.NewString("loadBalancer"))
	if err != nil {
		return nil, errors.Wrap(err, "could not create label requirements")
	}
	ls = ls.Add(*req)
	watcher, err := clientset.Core().Services(namespace).Watch(api.ListOptions{
		LabelSelector: ls,
	})
	if err != nil {
		return nil, errors.Wrap(err, "could not create service watcher")
	}

	ctx, cancel := context.WithCancel(context.Background())

	go serviceWatcher(ctx, watcher, errCh)
	return cancel, nil
}

func serviceWatcher(ctx context.Context, w watch.Interface, errCh chan<- error) {
	go func() {
		<-ctx.Done()
		w.Stop()
	}()

	for ev := range w.ResultChan() {
		err := handleEvent(ev)
		if err != nil {
			errCh <- errors.Wrap(err, "unable to handle event")
		}
	}
	errCh <- &fatalErr{
		err: fmt.Errorf("watch chan closed"),
	}
}

func handleEvent(ev watch.Event) error {
	switch ev.Type {
	case watch.Added, watch.Modified:
		s := ev.Object.(*v1.Service)
		rt, err := updateRoute53(s)
		if err != nil {
			return errors.Wrap(err, "could not get route53 details")
		}
		err = setRoute53(rt)
		if err != nil {
			return errors.Wrap(err, "could not update route53")
		}
		return nil
	default:
		log.Printf("useless event %s", ev)
		return nil
	}
}

func updateRoute53(s *v1.Service) (rt53Config, error) {
	ann := s.GetAnnotations()
	name, ok := ann["foolusion-aws-route53-name"]
	if !ok {
		return rt53Config{}, errors.Errorf("service %s missing annotation %s", s.GetName(), "foolusion-aws-route53-name")
	}

	hostedZone, ok := ann["foolusion-aws-route53-hostedZone"]
	if !ok {
		return rt53Config{}, errors.Errorf("service %s missing annotation %s", s.GetName(), "foolusion-aws-route53-hostedZone")
	}

	rt53Route := route{
		dnsName:      name,
		hostedZoneID: hostedZone,
	}

	if len(s.Status.LoadBalancer.Ingress) != 1 {
		return rt53Config{}, errors.Errorf("LoadBalancer.Ingress != 1 got %v", len(s.Status.LoadBalancer.Ingress))
	}
	loadBalancerHostname := s.Status.LoadBalancer.Ingress[0].Hostname
	if loadBalancerHostname == "" {
		return rt53Config{}, errors.Errorf("service %s missing LoadBalancer.Ingress", s.GetName())
	}

	loadBalancerName := strings.Split(loadBalancerHostname, "-")[1]

	loadBalancerHostedZoneID, err := getLoadBalancerHostedZone(loadBalancerName)
	if err != nil {
		return rt53Config{}, errors.WithMessage(err, "could not get hosted zone ID from load balancer")
	}

	loadBalancerRoute := route{
		dnsName:      loadBalancerHostname,
		hostedZoneID: loadBalancerHostedZoneID,
	}

	return rt53Config{
		rt53:         rt53Route,
		loadBalancer: loadBalancerRoute,
	}, nil
}

type route struct {
	dnsName      string
	hostedZoneID string
}

type rt53Config struct {
	rt53         route
	loadBalancer route
}

func getLoadBalancerHostedZone(name string) (string, error) {
	svc := elb.New(sess)

	params := &elb.DescribeLoadBalancersInput{
		LoadBalancerNames: []*string{
			aws.String(name),
		},
	}
	resp, err := svc.DescribeLoadBalancers(params)
	if err != nil {
		return "", errors.WithMessage(err, "could not describe load balancers")
	}

	if len(resp.LoadBalancerDescriptions) != 1 {
		return "", errors.Wrapf(err, "length of LoadBalancerDescriptions != 1 got %v", len(resp.LoadBalancerDescriptions))
	}

	hostedZoneID := resp.LoadBalancerDescriptions[0].CanonicalHostedZoneNameID
	if hostedZoneID == nil {
		return "", errors.WithMessage(err, "LoadBalancer hostedZoneID is not set")
	}

	return *hostedZoneID, nil
}

func setRoute53(r rt53Config) error {
	svc := route53.New(sess)

	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: []*route53.Change{
				{
					Action: aws.String(route53.ChangeActionCreate),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(r.rt53.dnsName),
						Type: aws.String(route53.RRTypeA),
						AliasTarget: &route53.AliasTarget{
							DNSName:              aws.String(r.loadBalancer.dnsName),
							HostedZoneId:         aws.String(r.loadBalancer.hostedZoneID),
							EvaluateTargetHealth: aws.Bool(false),
						},
					},
				},
			},
		},
		HostedZoneId: aws.String(r.rt53.hostedZoneID),
	}

	resp, err := svc.ChangeResourceRecordSets(params)
	if err != nil {
		return errors.Wrap(err, "could not change record set")
	}

	log.Println(resp)
	return nil
}
<|endoftext|>


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

// A simple drum machine app.
//
// Note: This demo is an early preview of Go 1.5. In order to build this
// program as an Android APK using the gomobile tool, you need to install
// Go 1.5 from the source.
//
// Clone the source from the tip under $HOME/go directory. On Windows,
// you may like to clone the repo to your user folder, %USERPROFILE%\go.
//
//   $ git clone https://go.googlesource.com/go $HOME/go
//
// Go 1.5 requires Go 1.4. Read more about this requirement at
// http://golang.org/s/go15bootstrap.
// Set GOROOT_BOOTSTRAP to the GOROOT of your existing 1.4 installation or
// follow the steps below to checkout go1.4 from the source and build.
//
//   $ git clone https://go.googlesource.com/go $HOME/go1.4
//   $ cd $HOME/go1.4
//   $ git checkout go1.4.1
//   $ cd src && ./make.bash
//
// If you clone Go 1.4 to a different destination, set GOROOT_BOOTSTRAP
// environmental variable accordingly.
//
// Build Go 1.5 and add Go 1.5 bin to your path.
//
//   $ cd $HOME/go/src && ./make.bash
//   $ export PATH=$PATH:$HOME/go/bin
//
// Set a GOPATH if no GOPATH is set, add $GOPATH/bin to your path.
//
//   $ export GOPATH=$HOME
//   $ export PATH=$PATH:$GOPATH/bin
//
// Get the gomobile tool and initialize.
//
//   $ go get golang.org/x/mobile/cmd/gomobile
//   $ gomobile init
//
// It may take a while to initialize gomobile, please wait.
//
// Get the drum machine example and use gomobile to build or install it on your device.
//
//   $ go get -d github.com/rakyll/drummachine
//   $ gomobile build github.com/rakyll/drummachine # will build an APK
//
//   # plug your Android device to your computer or start an Android emulator.
//   # if you have adb installed on your machine, use gomobile install to
//   # build and deploy the APK to an Android target.
//   $ gomobile install github.com/rakyll/drummachine
//
// Switch to your device or emulator to start the Drum Machine application from
// the launcher.
// You can also run the application on your desktop by running the command
// below. (Note: It currently doesn't work on Windows.)
//   $ go install github.com/rakyll/drummachine && drummachine
package main

import (
	"image"
	"io"
	"log"
	"time"

	_ "image/jpeg"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/audio"
	"golang.org/x/mobile/event"
	"golang.org/x/mobile/f32"
	"golang.org/x/mobile/gl"
	"golang.org/x/mobile/sprite"
	"golang.org/x/mobile/sprite/clock"
	"golang.org/x/mobile/sprite/glsprite"
)

var (
	startClock = time.Now()
	lastClock  = clock.Time(-1)
	eng        = glsprite.Engine()

	texs []sprite.SubTex

	board *sprite.Node
)

const numDrums = 6

var (
	samples [numDrums]io.Closer
	players [numDrums]*audio.Player
)

func main() {
	// TODO(jbd): Handle touch to turn on/off the beats.
	app.Run(app.Callbacks{
		Start: start,
		Stop:  stop,
		Draw:  draw,
		Touch: touch,
	})
}

func touch(t event.Touch) {
	x, y := float32(t.Loc.X), float32(t.Loc.Y)
	i := int((x - offsetX) / (buttonW + 10))
	j := int((y - offsetY) / (buttonH + 10))
	if i < 0 || i > 3 || j < 0 || j > 3 {
		return
	}
	if t.Type == event.TouchStart {
		buttons[i][j] = true
	}
	go func() {
		time.Sleep(300 * time.Millisecond)
		buttons[i][j] = false
	}()
}

func start() {

}

func stop() {
	for _, p := range players {
		p.Close()
	}
	for _, s := range samples {
		s.Close()
	}
}

const (
	offsetX = 20
	offsetY = 20
	buttonW = 50
	buttonH = 50
)

var buttons [4][4]bool

func draw() {
	if texs == nil {
		texs = loadTextures()
	}

	now := clock.Time(time.Since(startClock) * 60 / time.Second)
	if now == lastClock {
		// TODO: figure out how to limit draw callbacks to 60Hz instead of
		// burning the CPU as fast as possible.
		// TODO: (relatedly??) sync to vblank?
		return
	}
	lastClock = now
	gl.ClearColor(1, 1, 1, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT)

	cfg := app.GetConfig()
	board = &sprite.Node{}
	eng.Register(board)
	eng.SetTransform(board, f32.Affine{
		{1, 0, 0},
		{0, 1, 0},
	})

	n := newNode()
	eng.SetSubTex(n, texs[texBG])
	eng.SetTransform(n, f32.Affine{
		{float32(cfg.Width), 0, 0},
		{0, float32(cfg.Height), 0},
	})
	for i := 0; i < 4; i++ {
		for j := 0; j < 4; j++ {
			drawButton(i, j)
		}
	}
	eng.Render(board, now)
}

func drawButton(i, j int) {
	n := newNode()
	if buttons[i][j] {
		eng.SetSubTex(n, texs[texButtonOn])
	} else {
		eng.SetSubTex(n, texs[texButtonOff])
	}
	eng.SetTransform(n, f32.Affine{
		{buttonW, 0, float32(offsetX + i*(buttonW+10))},
		{0, buttonH, float32(offsetY + j*(buttonW+10))},
	})
}

func newNode() *sprite.Node {
	n := &sprite.Node{}
	eng.Register(n)
	board.AppendChild(n)
	return n
}

const (
	texBG = iota
	texButtonOn
	texButtonOff
	texBrand
	texModel
	texOthers
)

func loadTextures() []sprite.SubTex {
	a, err := app.Open("sprite.jpg")
	if err != nil {
		log.Fatal(err)
	}
	defer a.Close()

	img, _, err := image.Decode(a)
	if err != nil {
		log.Fatal(err)
	}
	t, err := eng.LoadTexture(img)
	if err != nil {
		log.Fatal(err)
	}

	return []sprite.SubTex{
		texBG:        sprite.SubTex{t, image.Rect(0, 0, 26, 860)},
		texButtonOff: sprite.SubTex{t, image.Rect(94, 242, 94+150, 242+151)},
		texButtonOn:  sprite.SubTex{t, image.Rect(94, 413, 94+150, 413+151)},
		texBrand:     sprite.SubTex{t, image.Rect(94, 31, 94+227, 31+88)},
		texModel:     sprite.SubTex{t, image.Rect(162, 120, 162+140, 120+90)},
		texOthers:    sprite.SubTex{t, image.Rect(162, 120, 162+140, 120+90)},
	}
}
<commit_msg>add todo.<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// A simple drum machine app.
//
// Note: This demo is an early preview of Go 1.5. In order to build this
// program as an Android APK using the gomobile tool, you need to install
// Go 1.5 from the source.
//
// Clone the source from the tip under $HOME/go directory. On Windows,
// you may like to clone the repo to your user folder, %USERPROFILE%\go.
//
//   $ git clone https://go.googlesource.com/go $HOME/go
//
// Go 1.5 requires Go 1.4. Read more about this requirement at
// http://golang.org/s/go15bootstrap.
// Set GOROOT_BOOTSTRAP to the GOROOT of your existing 1.4 installation or
// follow the steps below to checkout go1.4 from the source and build.
//
//   $ git clone https://go.googlesource.com/go $HOME/go1.4
//   $ cd $HOME/go1.4
//   $ git checkout go1.4.1
//   $ cd src && ./make.bash
//
// If you clone Go 1.4 to a different destination, set GOROOT_BOOTSTRAP
// environmental variable accordingly.
//
// Build Go 1.5 and add Go 1.5 bin to your path.
//
//   $ cd $HOME/go/src && ./make.bash
//   $ export PATH=$PATH:$HOME/go/bin
//
// Set a GOPATH if no GOPATH is set, add $GOPATH/bin to your path.
//
//   $ export GOPATH=$HOME
//   $ export PATH=$PATH:$GOPATH/bin
//
// Get the gomobile tool and initialize.
//
//   $ go get golang.org/x/mobile/cmd/gomobile
//   $ gomobile init
//
// It may take a while to initialize gomobile, please wait.
//
// Get the drum machine example and use gomobile to build or install it on your device.
//
//   $ go get -d github.com/rakyll/drummachine
//   $ gomobile build github.com/rakyll/drummachine # will build an APK
//
//   # plug your Android device to your computer or start an Android emulator.
//   # if you have adb installed on your machine, use gomobile install to
//   # build and deploy the APK to an Android target.
//   $ gomobile install github.com/rakyll/drummachine
//
// Switch to your device or emulator to start the Drum Machine application from
// the launcher.
// You can also run the application on your desktop by running the command
// below. (Note: It currently doesn't work on Windows.)
//   $ go install github.com/rakyll/drummachine && drummachine
package main

import (
	"image"
	"io"
	"log"
	"time"

	_ "image/jpeg"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/audio"
	"golang.org/x/mobile/event"
	"golang.org/x/mobile/f32"
	"golang.org/x/mobile/gl"
	"golang.org/x/mobile/sprite"
	"golang.org/x/mobile/sprite/clock"
	"golang.org/x/mobile/sprite/glsprite"
)

var (
	startClock = time.Now()
	lastClock  = clock.Time(-1)
	eng        = glsprite.Engine()

	texs []sprite.SubTex

	board *sprite.Node
)

const numDrums = 6

var (
	samples [numDrums]io.Closer
	players [numDrums]*audio.Player
)

func main() {
	// TODO(jbd): Handle touch to turn on/off the beats.
	app.Run(app.Callbacks{
		Start: start,
		Stop:  stop,
		Draw:  draw,
		Touch: touch,
	})
}

func touch(t event.Touch) {
	x, y := float32(t.Loc.X), float32(t.Loc.Y)
	i := int((x - offsetX) / (buttonW + 10))
	j := int((y - offsetY) / (buttonH + 10))
	if i < 0 || i > 3 || j < 0 || j > 3 {
		return
	}
	if t.Type == event.TouchStart {
		buttons[i][j] = true
	}
	go func() {
		time.Sleep(300 * time.Millisecond)
		buttons[i][j] = false
	}()
}

func start() {

}

func stop() {
	for _, p := range players {
		p.Close()
	}
	for _, s := range samples {
		s.Close()
	}
}

// TODO(jbd): Dynamically calculate the width and the height
// depending on the size of the screen.
const (
	offsetX = 20
	offsetY = 20
	buttonW = 50
	buttonH = 50
)

var buttons [4][4]bool

func draw() {
	if texs == nil {
		texs = loadTextures()
	}

	now := clock.Time(time.Since(startClock) * 60 / time.Second)
	if now == lastClock {
		// TODO: figure out how to limit draw callbacks to 60Hz instead of
		// burning the CPU as fast as possible.
		// TODO: (relatedly??) sync to vblank?
		return
	}
	lastClock = now
	gl.ClearColor(1, 1, 1, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT)

	cfg := app.GetConfig()
	board = &sprite.Node{}
	eng.Register(board)
	eng.SetTransform(board, f32.Affine{
		{1, 0, 0},
		{0, 1, 0},
	})

	n := newNode()
	eng.SetSubTex(n, texs[texBG])
	eng.SetTransform(n, f32.Affine{
		{float32(cfg.Width), 0, 0},
		{0, float32(cfg.Height), 0},
	})
	for i := 0; i < 4; i++ {
		for j := 0; j < 4; j++ {
			drawButton(i, j)
		}
	}
	eng.Render(board, now)
}

func drawButton(i, j int) {
	n := newNode()
	if buttons[i][j] {
		eng.SetSubTex(n, texs[texButtonOn])
	} else {
		eng.SetSubTex(n, texs[texButtonOff])
	}
	eng.SetTransform(n, f32.Affine{
		{buttonW, 0, float32(offsetX + i*(buttonW+10))},
		{0, buttonH, float32(offsetY + j*(buttonW+10))},
	})
}

func newNode() *sprite.Node {
	n := &sprite.Node{}
	eng.Register(n)
	board.AppendChild(n)
	return n
}

const (
	texBG = iota
	texButtonOn
	texButtonOff
	texBrand
	texModel
	texOthers
)

func loadTextures() []sprite.SubTex {
	a, err := app.Open("sprite.jpg")
	if err != nil {
		log.Fatal(err)
	}
	defer a.Close()

	img, _, err := image.Decode(a)
	if err != nil {
		log.Fatal(err)
	}
	t, err := eng.LoadTexture(img)
	if err != nil {
		log.Fatal(err)
	}

	return []sprite.SubTex{
		texBG:        sprite.SubTex{t, image.Rect(0, 0, 26, 860)},
		texButtonOff: sprite.SubTex{t, image.Rect(94, 242, 94+150, 242+151)},
		texButtonOn:  sprite.SubTex{t, image.Rect(94, 413, 94+150, 413+151)},
		texBrand:     sprite.SubTex{t, image.Rect(94, 31, 94+227, 31+88)},
		texModel:     sprite.SubTex{t, image.Rect(162, 120, 162+140, 120+90)},
		texOthers:    sprite.SubTex{t, image.Rect(162, 120, 162+140, 120+90)},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net"
	"os"
	"strconv"
	"strings"

	//"github.com/hashicorp/serf/client"
	"github.com/hashicorp/serf/command"
	"github.com/hashicorp/serf/command/agent"
	"github.com/hashicorp/serf/serf"
)

var (
	c                          = serf.DefaultConfig()
	mode           instaceMode = SlaveMode
	masterAddress  string
	listenAddress  string // this is the interface that serf runs on
	rpcAddress     string // this is the interface that serf's RPC runs on (localhost:7373)
	name           string
	defaultName, _ = os.Hostname()
	rpcAuthKey     = ""
)

type instaceMode int

const (
	MasterMode instaceMode = iota
	SlaveMode
	DeployMode
)

func init() {
	flag.StringVar(&masterAddress, "master", "mymaster.company.net:7946", "Join the cluster by coordinating with this master")
	flag.StringVar(&listenAddress, "listen", "localhost:7946", "Listen on the address for serf communication")
	flag.StringVar(&rpcAddress, "rpc", "localhost:7373", "RPC address of the serfbort master")
	flag.StringVar(&name, "name", defaultName, "Name to use in serf protocol")
	flag.Parse()
}

func main() {
	c.Tags = map[string]string{
		"role": "web",
		"env":  "dev",
	}
	c.NodeName = name

	fields := strings.Split(listenAddress, ":")
	if len(fields) != 2 {
		log.Fatalf("-listen requires host:port! %s is not valid", listenAddress)
	}
	bindAddr := fields[0]
	bindPort, err := strconv.Atoi(fields[1])
	if err != nil {
		log.Fatalf("Unable to parse %s into port", fields[1])
	}
	c.MemberlistConfig.BindAddr = bindAddr
	c.MemberlistConfig.BindPort = bindPort
	//TODO advertiseaddr and advertiseport
	//c.MemberlistConfig.AdvertiseAddr = x
	//c.MemberlistConfig.AdvertisePort = y

	evtCh := make(chan serf.Event, 64)
	c.EventCh = evtCh

	args := flag.Args()
	if len(args) > 0 {
		switch args[0] {
		case "master":
			mode = MasterMode
		case "deploy":
			mode = DeployMode
		default:
			mode = SlaveMode
		}
	}

	log.Print("Running...")
	switch mode {
	case SlaveMode:
		log.Print("Starting node")
		s := joinCluster()
		defer leaveCluster()
		slave := Slave{s, evtCh}
		slave.Run()
	case MasterMode:
		log.Printf("Starting master on %s", listenAddress)
		s := joinCluster()
		defer leaveCluster()
		master := Master{s, evtCh}

		log.Printf("Starting master RPC listener on %s", rpcAddress)
		//TODO we should create an agent with agent.Create instead of this!
		logOutput := os.Stdout
		logWriter := agent.NewLogWriter(123)
		a := agent.Agent{}
		rpcListener, err := net.Listen("tcp", rpcAddress)
		if err != nil {
			log.Fatal("Error starting RPC listener: %s", err)
		}
		agent.NewAgentIPC(&a, rpcAuthKey, rpcListener, logOutput, logWriter)

		master.Run()
	case DeployMode:
		/*
			clientCfg := client.Config{
				Addr:    listenAddress,
				AuthKey: "",
			} */
		//rpcclient, err := client.NewRPCClient(listenAddress)
		rpcclient, err := command.RPCClient(rpcAddress, rpcAuthKey)
		if err != nil {
			log.Fatalf("Unable to connect to master at %s: %s", rpcAddress, err)
		}

		log.Printf("Sending event to cluster...")
		err = rpcclient.UserEvent("deploy", []byte{}, false)
		if err != nil {
			log.Fatal(err)
		}

	}

}

func joinCluster() *serf.Serf {
	s, err := serf.Create(c)
	if err != nil {
		log.Fatalf("Error creating Serf: %s", err)
	}

	log.Printf("Joining cluster by way of %s", masterAddress)
	n, err := s.Join([]string{masterAddress}, true)
	if n > 0 {
		log.Printf("Cluster joined; %d nodes participating", n)
	}
	if err != nil {
		log.Fatalf("unable to join cluster: %s", err)
	}

	members := s.Members()
	log.Printf("%d nodes currently in cluster:", len(members))
	for _, m := range members {
		/*
		   Name   string
		   Addr   net.IP
		   Port   uint16
		   Tags   map[string]string
		   Status MemberStatus
		*/
		log.Printf("  %s %s:%d %v %s", m.Name, m.Addr, m.Port, m.Tags, m.Status)
	}
	return s

}
func leaveCluster() {
	//TODO this defer isnt running when ctrl-c'd
	/*
			go func() {
		    sig := <-sigChan
		        log.Printf("Cleaning up registered callback after signal %s\n", sig)
		                              os.Exit(0)
				log.Print("fuck")
				if s != nil {
					log.Print("Leaving cluster")
					err := s.Leave()
					if err != nil {
						log.Print(err)
						return
					}
					log.Print("Shutting down")
					err = s.Shutdown()
					if err != nil {
						log.Print(err)
						return
					}

				}
			}()
	*/
}
<commit_msg>fuck, deploy is causing a panic<commit_after>package main

import (
	"flag"
	"log"
	"net"
	"os"
	"strconv"
	"strings"

	//"github.com/hashicorp/serf/client"
	"github.com/hashicorp/serf/command"
	"github.com/hashicorp/serf/command/agent"
	"github.com/hashicorp/serf/serf"
)

var (
	c                          = serf.DefaultConfig()
	mode           instaceMode = SlaveMode
	masterAddress  string
	listenAddress  string // this is the interface that serf runs on
	rpcAddress     string // this is the interface that serf's RPC runs on (localhost:7373)
	name           string
	defaultName, _ = os.Hostname()
	rpcAuthKey     = ""
)

type instaceMode int

const (
	MasterMode instaceMode = iota
	SlaveMode
	DeployMode
)

func init() {
	flag.StringVar(&masterAddress, "master", "localhost:7946", "Join the cluster by coordinating with this master")
	flag.StringVar(&listenAddress, "listen", "localhost:7946", "Listen on the address for serf communication")
	flag.StringVar(&rpcAddress, "rpc", "localhost:7373", "RPC address of the serfbort master")
	flag.StringVar(&name, "name", defaultName, "Name to use in serf protocol")
	flag.Parse()
}

func main() {
	c.Tags = map[string]string{
		"role": "web",
		"env":  "dev",
	}
	c.NodeName = name

	fields := strings.Split(listenAddress, ":")
	if len(fields) != 2 {
		log.Fatalf("-listen requires host:port! %s is not valid", listenAddress)
	}
	bindAddr := fields[0]
	bindPort, err := strconv.Atoi(fields[1])
	if err != nil {
		log.Fatalf("Unable to parse %s into port", fields[1])
	}
	c.MemberlistConfig.BindAddr = bindAddr
	c.MemberlistConfig.BindPort = bindPort
	//TODO advertiseaddr and advertiseport
	//c.MemberlistConfig.AdvertiseAddr = x
	//c.MemberlistConfig.AdvertisePort = y

	evtCh := make(chan serf.Event, 64)
	c.EventCh = evtCh

	args := flag.Args()
	if len(args) > 0 {
		switch args[0] {
		case "master":
			mode = MasterMode
		case "deploy":
			mode = DeployMode
		default:
			mode = SlaveMode
		}
	}

	log.Print("Running...")
	switch mode {
	case SlaveMode:
		log.Print("Starting node")
		s := joinCluster()
		defer leaveCluster()
		slave := Slave{s, evtCh}
		slave.Run()
	case MasterMode:
		log.Printf("Starting master on %s", listenAddress)
		s := joinCluster()
		defer leaveCluster()
		master := Master{s, evtCh}

		log.Printf("Starting master RPC listener on %s", rpcAddress)
		//Create(agentConf *Config, conf *serf.Config, logOutput io.Writer) (*Agent, error)
		logOutput := os.Stdout
		logWriter := agent.NewLogWriter(123)
		a, err := agent.Create(agent.DefaultConfig(), c, logWriter)
		if err != nil {
			log.Fatalf("Unable to create agent: %s", err)
		}
		//TODO we should create an agent with agent.Create instead of this!
		//a := agent.Agent{}
		rpcListener, err := net.Listen("tcp", rpcAddress)
		if err != nil {
			log.Fatal("Error starting RPC listener: %s", err)
		}
		ipc := agent.NewAgentIPC(a, rpcAuthKey, rpcListener, logOutput, logWriter)
		log.Printf("Running IPC: %s", ipc)

		master.Run()
	case DeployMode:
		/*
			clientCfg := client.Config{
				Addr:    listenAddress,
				AuthKey: "",
			} */
		//rpcclient, err := client.NewRPCClient(listenAddress)
		rpcclient, err := command.RPCClient(rpcAddress, rpcAuthKey)
		if err != nil {
			log.Fatalf("Unable to connect to master at %s: %s", rpcAddress, err)
		}

		log.Printf("Sending event to cluster...")
		err = rpcclient.UserEvent("deploy", []byte("fuck"), false)
		if err != nil {
			log.Fatal(err)
		}

	}

}

func joinCluster() *serf.Serf {
	s, err := serf.Create(c)
	if err != nil {
		log.Fatalf("Error creating Serf: %s", err)
	}

	log.Printf("Joining cluster by way of %s", masterAddress)
	n, err := s.Join([]string{masterAddress}, true)
	if n > 0 {
		log.Printf("Cluster joined; %d nodes participating", n)
	}
	if err != nil {
		log.Fatalf("unable to join cluster: %s", err)
	}

	members := s.Members()
	log.Printf("%d nodes currently in cluster:", len(members))
	for _, m := range members {
		/*
		   Name   string
		   Addr   net.IP
		   Port   uint16
		   Tags   map[string]string
		   Status MemberStatus
		*/
		log.Printf("  %s %s:%d %v %s", m.Name, m.Addr, m.Port, m.Tags, m.Status)
	}
	return s

}
func leaveCluster() {
	//TODO this defer isnt running when ctrl-c'd
	/*
			go func() {
		    sig := <-sigChan
		        log.Printf("Cleaning up registered callback after signal %s\n", sig)
		                              os.Exit(0)
				log.Print("fuck")
				if s != nil {
					log.Print("Leaving cluster")
					err := s.Leave()
					if err != nil {
						log.Print(err)
						return
					}
					log.Print("Shutting down")
					err = s.Shutdown()
					if err != nil {
						log.Print(err)
						return
					}

				}
			}()
	*/
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"runtime"
	"strconv"
)

type Base36Url struct {
	Root string
}

func (s *Base36Url) Init(root string) {
	s.Root = root
	os.MkdirAll(s.Root, 0744)
}

func (s *Base36Url) Path(code string) string {
	return s.Root + code
}

func (s *Base36Url) Save(url string) string {
	files, _ := ioutil.ReadDir(s.Path(""))
	code := strconv.FormatUint(uint64(len(files)+1), 36)

	ioutil.WriteFile(s.Path(code), []byte(url), 0744)
	return code
}

func (s *Base36Url) EncodeHandler(w http.ResponseWriter, r *http.Request) {
	url := r.FormValue("url")
	if url != "" {
		fmt.Fprintf(w, s.Save(url))
	}
}

func (s *Base36Url) DecodeHandler(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	code := params["code"]
	url, err := ioutil.ReadFile(s.Path(code))

	if err == nil {
		fmt.Fprintf(w, string(url))
	} else {
		fmt.Fprintf(w, "Error: %v", err)
	}
}

func (s *Base36Url) RedirectHandler(w http.ResponseWriter, r *http.Request) {
	code := mux.Vars(r)["code"]
	url, err := ioutil.ReadFile(s.Path(code))

	if err == nil {
		http.Redirect(w, r, string(url), 301)
	}
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	usr, _ := user.Current()
	storage := &Base36Url{}
	storage.Init(usr.HomeDir + "/shawty/")

	r := mux.NewRouter()
	r.HandleFunc("/", storage.EncodeHandler).Methods("POST")
	r.HandleFunc("/dec/{code}", storage.DecodeHandler).Methods("GET")
	r.HandleFunc("/red/{code}", storage.RedirectHandler).Methods("GET")
	http.Handle("/", r)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>Use filepath to eliminate the need of s.Path(). ListenAndServe can support a Mux already.<commit_after>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"strconv"
)

type Base36Url struct {
	Root string
}

func (s *Base36Url) Init(root string) {
	s.Root = root
	os.MkdirAll(s.Root, 0744)
}

func (s *Base36Url) Save(url string) string {
	files, _ := ioutil.ReadDir(s.Root)
	code := strconv.FormatUint(uint64(len(files)+1), 36)

	ioutil.WriteFile(filepath.Join(s.Root, code), []byte(url), 0744)
	return code
}

func (s *Base36Url) EncodeHandler(w http.ResponseWriter, r *http.Request) {
	url := r.FormValue("url")
	if url != "" {
		fmt.Fprintf(w, s.Save(url))
	}
}

func (s *Base36Url) DecodeHandler(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	code := params["code"]
	url, err := ioutil.ReadFile(filepath.Join(s.Root, code))

	if err == nil {
		fmt.Fprintf(w, string(url))
	} else {
		fmt.Fprintf(w, "Error: %v", err)
	}
}

func (s *Base36Url) RedirectHandler(w http.ResponseWriter, r *http.Request) {
	code := mux.Vars(r)["code"]
	url, err := ioutil.ReadFile(filepath.Join(s.Root, code))

	if err == nil {
		http.Redirect(w, r, string(url), 301)
	}
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	usr, _ := user.Current()
	storage := &Base36Url{}
	storage.Init(usr.HomeDir + "/shawty/")

	r := mux.NewRouter()
	r.HandleFunc("/", storage.EncodeHandler).Methods("POST")
	r.HandleFunc("/dec/{code}", storage.DecodeHandler).Methods("GET")
	r.HandleFunc("/red/{code}", storage.RedirectHandler).Methods("GET")

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	http.ListenAndServe(":"+port, r)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"runtime"

	"github.com/getfider/fider/app/cmd"
	"github.com/getfider/fider/app/models"
	"github.com/getfider/fider/app/pkg/env"
	_ "github.com/lib/pq"
)

// replaced during CI build
var buildtime = ""
var buildnumber = "local"

// Use this for non-stable releases
// var version = "x.y.z-" + buildnumber

// Use this for stable releases
// var version = "x.y.z"

var version = "0.15.0-"

func main() {
	settings := &models.SystemSettings{
		BuildTime:       buildtime,
		Version:         version,
		Compiler:        runtime.Version(),
		Environment:     env.Current(),
		GoogleAnalytics: env.GetEnvOrDefault("GOOGLE_ANALYTICS", ""),
		Mode:            env.Mode(),
		Domain:          env.MultiTenantDomain(),
		HasLegal:        env.HasLegal(),
	}

	args := os.Args[1:]
	if len(args) > 0 && args[0] == "ping" {
		os.Exit(cmd.RunPing())
	} else if len(args) > 0 && args[0] == "migrate" {
		os.Exit(cmd.RunMigrate())
	} else {
		os.Exit(cmd.RunServer(settings))
	}
}
<commit_msg>chore: remove buildnumber for 0.15 (#505)<commit_after>package main

import (
	"os"
	"runtime"

	"github.com/getfider/fider/app/cmd"
	"github.com/getfider/fider/app/models"
	"github.com/getfider/fider/app/pkg/env"
	_ "github.com/lib/pq"
)

// replaced during CI build
var buildtime = ""
var buildnumber = "local"

// Use this for non-stable releases
// var version = "x.y.z-" + buildnumber

// Use this for stable releases
// var version = "x.y.z"

var version = "0.15.0"

func main() {
	settings := &models.SystemSettings{
		BuildTime:       buildtime,
		Version:         version,
		Compiler:        runtime.Version(),
		Environment:     env.Current(),
		GoogleAnalytics: env.GetEnvOrDefault("GOOGLE_ANALYTICS", ""),
		Mode:            env.Mode(),
		Domain:          env.MultiTenantDomain(),
		HasLegal:        env.HasLegal(),
	}

	args := os.Args[1:]
	if len(args) > 0 && args[0] == "ping" {
		os.Exit(cmd.RunPing())
	} else if len(args) > 0 && args[0] == "migrate" {
		os.Exit(cmd.RunMigrate())
	} else {
		os.Exit(cmd.RunServer(settings))
	}
}
<|endoftext|>


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

package main

import (
	. "github.com/kahing/goofys/internal"

	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"golang.org/x/net/context"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"

	"github.com/codegangsta/cli"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"

	"github.com/kardianos/osext"

	"github.com/Sirupsen/logrus"

	daemon "github.com/sevlyar/go-daemon"
)

var log = GetLogger("main")

func registerSIGINTHandler(mountPoint string) {
	// Register for SIGINT.
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

	// Start a goroutine that will unmount when the signal is received.
	go func() {
		for {
			s := <-signalChan
			log.Infof("Received %v, attempting to unmount...", s)

			err := fuse.Unmount(mountPoint)
			if err != nil {
				log.Errorf("Failed to unmount in response to %v: %v", s, err)
			} else {
				log.Printf("Successfully unmounted %v in response to %v", s, mountPoint)
				return
			}
		}
	}()
}

// Mount the file system based on the supplied arguments, returning a
// fuse.MountedFileSystem that can be joined to wait for unmounting.
func mount(
	ctx context.Context,
	bucketName string,
	mountPoint string,
	flags *FlagStorage) (mfs *fuse.MountedFileSystem, err error) {

	var creds *credentials.Credentials
	if len(flags.Profile) > 0 {
		creds = credentials.NewSharedCredentials(os.Getenv("HOME")+"/.aws/credentials", flags.Profile)
	}

	awsConfig := &aws.Config{
		Region:      &flags.Region,
		Logger:      GetLogger("s3"),
		Credentials: creds,
		//LogLevel: aws.LogLevel(aws.LogDebug),
	}
	if len(flags.Endpoint) > 0 {
		awsConfig.Endpoint = &flags.Endpoint
	}

	// deprecate flags.UsePathRequest
	if flags.UsePathRequest {
		log.Infoln("--use-path-request is deprecated, it's always on")
	}
	awsConfig.S3ForcePathStyle = aws.Bool(true)

	goofys := NewGoofys(bucketName, awsConfig, flags)
	if goofys == nil {
		err = fmt.Errorf("Mount: initialization failed")
		return
	}
	server := fuseutil.NewFileSystemServer(goofys)

	fuseLog := GetLogger("fuse")

	// Mount the file system.
	mountCfg := &fuse.MountConfig{
		FSName:                  bucketName,
		Options:                 flags.MountOptions,
		ErrorLogger:             GetStdLogger(NewLogger("fuse"), logrus.ErrorLevel),
		DisableWritebackCaching: true,
	}

	if flags.DebugFuse {
		fuseLog.Level = logrus.DebugLevel
		log.Level = logrus.DebugLevel
		mountCfg.DebugLogger = GetStdLogger(fuseLog, logrus.DebugLevel)
	}

	mfs, err = fuse.Mount(mountPoint, server, mountCfg)
	if err != nil {
		err = fmt.Errorf("Mount: %v", err)
		return
	}

	return
}

func massagePath() {
	for _, e := range os.Environ() {
		if strings.HasPrefix(e, "PATH=") {
			return
		}
	}

	// mount -a seems to run goofys without PATH
	// usually fusermount is in /bin
	os.Setenv("PATH", "/bin")
}

func massageArg0() {
	var err error
	os.Args[0], err = osext.Executable()
	if err != nil {
		panic(fmt.Sprintf("Unable to discover current executable: %v", err))
	}
}

func main() {
	app := NewApp()
	app.Action = func(c *cli.Context) (err error) {
		// We should get two arguments exactly. Otherwise error out.
		if len(c.Args()) != 2 {
			fmt.Fprintf(
				os.Stderr,
				"Error: %s takes exactly two arguments.\n\n",
				app.Name)
			cli.ShowAppHelp(c)
			os.Exit(1)
		}

		// Populate and parse flags.
		bucketName := c.Args()[0]
		mountPoint := c.Args()[1]
		flags := PopulateFlags(c)

		InitLoggers(!flags.Foreground)

		massagePath()

		if !flags.Foreground {
			massageArg0()

			ctx := new(daemon.Context)
			var child *os.Process
			child, err = ctx.Reborn()

			if err != nil {
				panic(fmt.Sprintf("unable to daemonize: %v", err))
			}

			if child != nil {
				return
			} else {
				defer ctx.Release()
			}

		}

		// Mount the file system.
		var mfs *fuse.MountedFileSystem
		mfs, err = mount(
			context.Background(),
			bucketName,
			mountPoint,
			flags)

		if err != nil {
			log.Fatalf("Mounting file system: %v", err)
		}

		log.Println("File system has been successfully mounted.")

		// Let the user unmount with Ctrl-C (SIGINT).
		registerSIGINTHandler(mfs.Dir())

		// Wait for the file system to be unmounted.
		err = mfs.Join(context.Background())
		if err != nil {
			err = fmt.Errorf("MountedFileSystem.Join: %v", err)
			return
		}

		log.Println("Successfully exiting.")
		return
	}

	err := app.Run(MassageMountFlags(os.Args))
	if err != nil {
		log.Fatalln(err)
	}
}
<commit_msg>restoring default credentials object to "a chain of credential providers to search for credentials in environment variables, shared credential file, and EC2 Instance Roles"<commit_after>// Copyright 2015 Ka-Hing Cheung
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	. "github.com/kahing/goofys/internal"

	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"golang.org/x/net/context"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"

	"github.com/codegangsta/cli"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"

	"github.com/kardianos/osext"

	"github.com/Sirupsen/logrus"

	daemon "github.com/sevlyar/go-daemon"
)

var log = GetLogger("main")

func registerSIGINTHandler(mountPoint string) {
	// Register for SIGINT.
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

	// Start a goroutine that will unmount when the signal is received.
	go func() {
		for {
			s := <-signalChan
			log.Infof("Received %v, attempting to unmount...", s)

			err := fuse.Unmount(mountPoint)
			if err != nil {
				log.Errorf("Failed to unmount in response to %v: %v", s, err)
			} else {
				log.Printf("Successfully unmounted %v in response to %v", s, mountPoint)
				return
			}
		}
	}()
}

// Mount the file system based on the supplied arguments, returning a
// fuse.MountedFileSystem that can be joined to wait for unmounting.
func mount(
	ctx context.Context,
	bucketName string,
	mountPoint string,
	flags *FlagStorage) (mfs *fuse.MountedFileSystem, err error) {

	awsConfig := &aws.Config{
		Region:      &flags.Region,
		Logger:      GetLogger("s3"),
		//LogLevel: aws.LogLevel(aws.LogDebug),
	}

	if len(flags.Profile) > 0 {
		awsConfig.Credentials = credentials.NewSharedCredentials(os.Getenv("HOME")+"/.aws/credentials", flags.Profile)
	}

	if len(flags.Endpoint) > 0 {
		awsConfig.Endpoint = &flags.Endpoint
	}

	// deprecate flags.UsePathRequest
	if flags.UsePathRequest {
		log.Infoln("--use-path-request is deprecated, it's always on")
	}
	awsConfig.S3ForcePathStyle = aws.Bool(true)

	goofys := NewGoofys(bucketName, awsConfig, flags)
	if goofys == nil {
		err = fmt.Errorf("Mount: initialization failed")
		return
	}
	server := fuseutil.NewFileSystemServer(goofys)

	fuseLog := GetLogger("fuse")

	// Mount the file system.
	mountCfg := &fuse.MountConfig{
		FSName:                  bucketName,
		Options:                 flags.MountOptions,
		ErrorLogger:             GetStdLogger(NewLogger("fuse"), logrus.ErrorLevel),
		DisableWritebackCaching: true,
	}

	if flags.DebugFuse {
		fuseLog.Level = logrus.DebugLevel
		log.Level = logrus.DebugLevel
		mountCfg.DebugLogger = GetStdLogger(fuseLog, logrus.DebugLevel)
	}

	mfs, err = fuse.Mount(mountPoint, server, mountCfg)
	if err != nil {
		err = fmt.Errorf("Mount: %v", err)
		return
	}

	return
}

func massagePath() {
	for _, e := range os.Environ() {
		if strings.HasPrefix(e, "PATH=") {
			return
		}
	}

	// mount -a seems to run goofys without PATH
	// usually fusermount is in /bin
	os.Setenv("PATH", "/bin")
}

func massageArg0() {
	var err error
	os.Args[0], err = osext.Executable()
	if err != nil {
		panic(fmt.Sprintf("Unable to discover current executable: %v", err))
	}
}

func main() {
	app := NewApp()
	app.Action = func(c *cli.Context) (err error) {
		// We should get two arguments exactly. Otherwise error out.
		if len(c.Args()) != 2 {
			fmt.Fprintf(
				os.Stderr,
				"Error: %s takes exactly two arguments.\n\n",
				app.Name)
			cli.ShowAppHelp(c)
			os.Exit(1)
		}

		// Populate and parse flags.
		bucketName := c.Args()[0]
		mountPoint := c.Args()[1]
		flags := PopulateFlags(c)

		InitLoggers(!flags.Foreground)

		massagePath()

		if !flags.Foreground {
			massageArg0()

			ctx := new(daemon.Context)
			var child *os.Process
			child, err = ctx.Reborn()

			if err != nil {
				panic(fmt.Sprintf("unable to daemonize: %v", err))
			}

			if child != nil {
				return
			} else {
				defer ctx.Release()
			}

		}

		// Mount the file system.
		var mfs *fuse.MountedFileSystem
		mfs, err = mount(
			context.Background(),
			bucketName,
			mountPoint,
			flags)

		if err != nil {
			log.Fatalf("Mounting file system: %v", err)
		}

		log.Println("File system has been successfully mounted.")

		// Let the user unmount with Ctrl-C (SIGINT).
		registerSIGINTHandler(mfs.Dir())

		// Wait for the file system to be unmounted.
		err = mfs.Join(context.Background())
		if err != nil {
			err = fmt.Errorf("MountedFileSystem.Join: %v", err)
			return
		}

		log.Println("Successfully exiting.")
		return
	}

	err := app.Run(MassageMountFlags(os.Args))
	if err != nil {
		log.Fatalln(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/nlopes/slack"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/watch"
)

// Sends a message to the Slack channel about the Event.
func sendMessage(e *api.Event, color string) error {
	api := slack.New(os.Getenv("SLACK_TOKEN"))
	params := slack.PostMessageParameters{}
	metadata := e.GetObjectMeta()
	attachment := slack.Attachment{
		// The fallback message shows in clients such as IRC or OS X notifications.
		Fallback: e.Message,
		Fields: []slack.AttachmentField{
			slack.AttachmentField{
				Title: "Message",
				Value: e.Message,
			},
			slack.AttachmentField{
				Title: "Object",
				Value: e.InvolvedObject.Kind,
				Short: true,
			},
			slack.AttachmentField{
				Title: "Name",
				Value: metadata.GetName(),
				Short: true,
			},
			slack.AttachmentField{
				Title: "Reason",
				Value: e.Reason,
				Short: true,
			},
			slack.AttachmentField{
				Title: "Component",
				Value: e.Source.Component,
				Short: true,
			},
		},
	}

	// Use a color if provided, otherwise try to guess.
	if color != "" {
		attachment.Color = color
	} else if strings.HasPrefix(e.Reason, "Success") {
		attachment.Color = "good"
	} else if strings.HasPrefix(e.Reason, "Fail") {
		attachment.Color = "danger"
	}
	params.Attachments = []slack.Attachment{attachment}

	channelID, timestamp, err := api.PostMessage(os.Getenv("SLACK_CHANNEL"), "", params)
	if err != nil {
		fmt.Printf("%s\n", err)
		return err
	}

	log.Printf("Message successfully sent to channel %s at %s", channelID, timestamp)
	return nil
}

func main() {

	kubeClient, err := client.NewInCluster()
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// Setup a watcher for pods
	eventClient := kubeClient.Events(api.NamespaceAll)
	options := api.ListOptions{LabelSelector: labels.Everything()}
	w, err := eventClient.Watch(options)
	if err != nil {
		log.Fatalf("Failed to set up watch: %v", err)
	}
	select {
	case watchEvent, _ := <-w.ResultChan():
		send := false
		color := ""
		if watchEvent.Type == watch.Added {
			send = true
			color = "good"
		} else if watchEvent.Type == watch.Deleted {
			send = true
			color = "warning"
		}
		fmt.Printf("%+v\n", watchEvent)

		if send {
			event, _ := watchEvent.Object.(*api.Event)
			err = sendMessage(event, color)
			if err != nil {
				log.Fatal("sendMessage: ", err)
			}
		}
	}
}
<commit_msg>log all events.<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/nlopes/slack"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/watch"
)

// Sends a message to the Slack channel about the Event.
func sendMessage(e *api.Event, color string) error {
	api := slack.New(os.Getenv("SLACK_TOKEN"))
	params := slack.PostMessageParameters{}
	metadata := e.GetObjectMeta()
	attachment := slack.Attachment{
		// The fallback message shows in clients such as IRC or OS X notifications.
		Fallback: e.Message,
		Fields: []slack.AttachmentField{
			slack.AttachmentField{
				Title: "Message",
				Value: e.Message,
			},
			slack.AttachmentField{
				Title: "Object",
				Value: e.InvolvedObject.Kind,
				Short: true,
			},
			slack.AttachmentField{
				Title: "Name",
				Value: metadata.GetName(),
				Short: true,
			},
			slack.AttachmentField{
				Title: "Reason",
				Value: e.Reason,
				Short: true,
			},
			slack.AttachmentField{
				Title: "Component",
				Value: e.Source.Component,
				Short: true,
			},
		},
	}

	// Use a color if provided, otherwise try to guess.
	if color != "" {
		attachment.Color = color
	} else if strings.HasPrefix(e.Reason, "Success") {
		attachment.Color = "good"
	} else if strings.HasPrefix(e.Reason, "Fail") {
		attachment.Color = "danger"
	}
	params.Attachments = []slack.Attachment{attachment}

	channelID, timestamp, err := api.PostMessage(os.Getenv("SLACK_CHANNEL"), "", params)
	if err != nil {
		fmt.Printf("%s\n", err)
		return err
	}

	log.Printf("Message successfully sent to channel %s at %s", channelID, timestamp)
	return nil
}

func main() {

	kubeClient, err := client.NewInCluster()
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// Setup a watcher for events.
	eventClient := kubeClient.Events(api.NamespaceAll)
	options := api.ListOptions{LabelSelector: labels.Everything()}
	w, err := eventClient.Watch(options)
	if err != nil {
		log.Fatalf("Failed to set up watch: %v", err)
	}
	select {
	case watchEvent, _ := <-w.ResultChan():

		// Log all events for now.
		log.Printf("Reason: %s\nMessage: %s\nCount: %s\nFirstTimestamp: %s\nLastTimestamp: %s\n\n", e.Reason, e.Message, strconv.Itoa(e.Count), e.FirstTimestamp, e.LastTimestamp)

		send := false
		color := ""
		if watchEvent.Type == watch.Added {
			send = true
			color = "good"
		} else if watchEvent.Type == watch.Deleted {
			send = true
			color = "warning"
		}
		if send {
			event, _ := watchEvent.Object.(*api.Event)
			err = sendMessage(event, color)
			if err != nil {
				log.Fatalf("sendMessage: %v", err)
			}
		}
	}
}
<|endoftext|>