<commit_before>package main

import (
	// "bufio"
	"fmt"
	"github.com/docker/docker/pkg/mflag"
	"github.com/mattes/fugu/file"
	"github.com/mattes/fugu/run"
	_ "io"
	"os"
	"os/exec"
	"path"
	_ "strings"
)

var fileNamePaths = []string{"fugu.yml", "fugu.yaml", ".fugu.yml", ".fugu.yaml"}

// fugu run [fugu.yml-path] [label] [docker-run-options + --image] [command] [args]
// fugu build [fugu.yml-path] [label] [docker-build-options] [path=pwd|url|-]

func main() {
	if len(fileNamePaths) == 0 {
		panic("Specify at least one fileNamePath!")
	}

	args := os.Args
	argsLen := len(args)

	if argsLen <= 1 {
		fmt.Println("no cmd")
		os.Exit(1)
	}

	command := args[1]
	fugufilePath := ""
	fugufilePathGiven := false
	label := ""
	labelGiven := false

	// extract fugufile and label if given
	args1 := make([]string, 0)
	if argsLen >= 4 {
		args1 = args[2:4]
	} else if argsLen >= 3 {
		args1 = args[2:3]
	}

	// check if fugufile
	exts := fileExtensions(fileNamePaths)
	for _, f := range args1 {
		if isFuguFile(f, exts) {
			fugufilePath = f
			fugufilePathGiven = true
			break
		}
	}

	if fugufilePath == "" {
		for _, f := range fileNamePaths {
			if fileExists(f) {
				fugufilePath = f
				break
			}
		}
		if fugufilePath == "" {
			fmt.Printf("%s not found\n", fileNamePaths[0])
			os.Exit(1)
		}

	} else {
		if !fileExists(fugufilePath) {
			fmt.Printf("%s not found\n", fugufilePath)
			os.Exit(1)
		}
	}

	// get all labels
	labels, err := file.GetLabels(fugufilePath)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// check if label
	// dont worry here, if no label is found
	for _, l := range args1 {
		if isLabel(l, labels) {
			label = l
			labelGiven = true
			break
		}
	}

	// load fugu config
	fuguConfig, err := file.GetConfig(fugufilePath, label)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// now do docker option parsing
	offsetCount := 2
	if fugufilePathGiven {
		offsetCount += 1
	}
	if labelGiven {
		offsetCount += 1
	}

	remainingArgs := []string{}
	options := make(map[string]interface{})
	rf := &mflag.FlagSet{}
	if argsLen >= offsetCount {
		options, rf, err = run.Parse(args[offsetCount:])
		if err != nil {
			fmt.Println(err)
			os.Exit(2)
		}
		remainingArgs = rf.Args()
	}

	// merge config from fugufile
	for k, v := range options {
		switch v.(type) {
		case []string:
			if len(v.([]string)) > 0 {
				fuguConfig[k] = v
			}

		case string:
			if v.(string) != "" {
				fuguConfig[k] = v
			}

		default:
			fuguConfig[k] = v
		}
	}

	if len(remainingArgs) > 0 {
		fuguConfig["command"] = remainingArgs[0]
	}

	if len(remainingArgs) > 1 {
		fuguConfig["args"] = remainingArgs[1:]
	}

	switch command {
	case "run":

		execArgs := []string{"run"}

		for k, v := range fuguConfig {

			if k != "image" && k != "args" && k != "command" {
				switch v.(type) {
				default:
					execArgs = append(execArgs, fmt.Sprintf(`--%s="%v"`, k, v))

				case []string:
					for _, v2 := range v.([]string) {
						execArgs = append(execArgs, fmt.Sprintf(`--%s="%v"`, k, v2))
					}

				case bool:
					execArgs = append(execArgs, fmt.Sprintf(`--%s=%v`, k, v.(bool)))
				}
			}
		}

		// execArgs = append([]string{dockerImage}, execArgs...)
		execArgs = append(execArgs, fuguConfig["image"].(string))

		if _, ok := fuguConfig["command"]; ok {
			execArgs = append(execArgs, fuguConfig["command"].(string))
		}

		if _, ok := fuguConfig["args"]; ok {
			switch fuguConfig["args"].(type) {
			case []string:
				execArgs = append(execArgs, fuguConfig["args"].([]string)...)

			case []interface{}:
				for _, v := range fuguConfig["args"].([]interface{}) {
					switch v.(type) {
					case string:
						execArgs = append(execArgs, v.(string))

					default:
						panic(fmt.Sprintf("unknown type %#v", v))
					}
				}

			case string:
				execArgs = append(execArgs, fuguConfig["args"].(string))

			default:
				panic(fmt.Sprintf("unknown type %#v", fuguConfig["args"]))
			}
		}

		fmt.Printf("docker run %s\n\n", execArgs)

		cmd := exec.Command("docker", execArgs...)

		// // in, _ := cmd.StdinPipe()
		// // out, _ := cmd.StdoutPipe()
		// // err, _ := cmd.StderrPipe()

		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Stdin = os.Stdin

		// //read := bufio.NewReader(os.Stdin)
		// //cmd.Stdin = read

		cmd.Run()

		// cmd.Wait()

		// go io.Copy(os.Stdout, out)
		// io.Copy(writer, os.Stdin)
		// // writer.WriteString("echo hello")
		// cmd.Wait()

		// cwd, _ := os.Getwd()

		// pa := os.ProcAttr{
		// 	Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
		// 	Dir:   cwd,
		// }

		// proc, err := os.StartProcess("/usr/bin/env", []string{"gelo"}, &pa)
		// if err != nil {
		// 	fmt.Println(err)
		// 	os.Exit(3)
		// }

		// proc.Wait()

	case "build":
		fmt.Println("@todo")
		// os.Exit(2)
	default:
		// os.Exit(1)
	}
}

func isFuguFile(file string, extensions []string) bool {
	for _, ext := range extensions {
		if path.Ext(file) == ext {
			return true
		}
	}
	return false
}

func fileExists(filePath string) bool {
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func isLabel(label string, search []string) bool {
	for _, l := range search {
		if label == l {
			return true
		}
	}
	return false
}

func fileExtensions(s []string) []string {
	su := make([]string, 0)
	exts := make(map[string]bool)
	for _, v := range s {
		ext := path.Ext(v)
		if _, ok := exts[ext]; !ok {
			exts[ext] = true
			su = append(su, ext)
		}
	}
	return su
}
<commit_msg>cleanup<commit_after>package main

import (
	// "bufio"
	"fmt"
	"github.com/docker/docker/pkg/mflag"
	"github.com/mattes/fugu/file"
	"github.com/mattes/fugu/run"
	_ "io"
	"os"
	"os/exec"
	"path"
	_ "strings"
)

var fileNamePaths = []string{"fugu.yml", "fugu.yaml", ".fugu.yml", ".fugu.yaml"}

// fugu run [fugu.yml-path] [label] [docker-run-options + --image] [command] [args]
// fugu build [fugu.yml-path] [label] [docker-build-options] [path=pwd|url|-]

func main() {
	if len(fileNamePaths) == 0 {
		panic("Specify at least one fileNamePath!")
	}

	args := os.Args
	argsLen := len(args)

	if argsLen <= 1 {
		fmt.Println("no cmd")
		os.Exit(1)
	}

	command := args[1]
	fugufilePath := ""
	fugufilePathGiven := false
	label := ""
	labelGiven := false

	// extract fugufile and label if given
	args1 := make([]string, 0)
	if argsLen >= 4 {
		args1 = args[2:4]
	} else if argsLen >= 3 {
		args1 = args[2:3]
	}

	// check if fugufile
	exts := fileExtensions(fileNamePaths)
	for _, f := range args1 {
		if isFuguFile(f, exts) {
			fugufilePath = f
			fugufilePathGiven = true
			break
		}
	}

	if fugufilePath == "" {
		for _, f := range fileNamePaths {
			if fileExists(f) {
				fugufilePath = f
				break
			}
		}
		if fugufilePath == "" {
			fmt.Printf("%s not found\n", fileNamePaths[0])
			os.Exit(1)
		}

	} else {
		if !fileExists(fugufilePath) {
			fmt.Printf("%s not found\n", fugufilePath)
			os.Exit(1)
		}
	}

	// get all labels
	labels, err := file.GetLabels(fugufilePath)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// check if label
	// dont worry here, if no label is found
	for _, l := range args1 {
		if isLabel(l, labels) {
			label = l
			labelGiven = true
			break
		}
	}

	// load fugu config
	fuguConfig, err := file.GetConfig(fugufilePath, label)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// now do docker option parsing
	offsetCount := 2
	if fugufilePathGiven {
		offsetCount += 1
	}
	if labelGiven {
		offsetCount += 1
	}

	remainingArgs := []string{}
	options := make(map[string]interface{})
	rf := &mflag.FlagSet{}
	if argsLen >= offsetCount {
		options, rf, err = run.Parse(args[offsetCount:])
		if err != nil {
			fmt.Println(err)
			os.Exit(2)
		}
		remainingArgs = rf.Args()
	}

	// merge config from fugufile
	for k, v := range options {
		switch v.(type) {
		case []string:
			if len(v.([]string)) > 0 {
				fuguConfig[k] = v
			}

		case string:
			if v.(string) != "" {
				fuguConfig[k] = v
			}

		default:
			fuguConfig[k] = v
		}
	}

	if len(remainingArgs) > 0 {
		fuguConfig["command"] = remainingArgs[0]
	}

	if len(remainingArgs) > 1 {
		fuguConfig["args"] = remainingArgs[1:]
	}

	switch command {
	case "run":

		execArgs := []string{"run"}

		for k, v := range fuguConfig {

			if k != "image" && k != "args" && k != "command" {
				switch v.(type) {
				default:
					execArgs = append(execArgs, fmt.Sprintf(`--%s="%v"`, k, v))

				case []string:
					for _, v2 := range v.([]string) {
						execArgs = append(execArgs, fmt.Sprintf(`--%s="%v"`, k, v2))
					}

				case bool:
					execArgs = append(execArgs, fmt.Sprintf(`--%s=%v`, k, v.(bool)))
				}
			}
		}

		// execArgs = append([]string{dockerImage}, execArgs...)
		execArgs = append(execArgs, fuguConfig["image"].(string))

		if _, ok := fuguConfig["command"]; ok {
			execArgs = append(execArgs, fuguConfig["command"].(string))
		}

		if _, ok := fuguConfig["args"]; ok {
			switch fuguConfig["args"].(type) {
			case []string:
				execArgs = append(execArgs, fuguConfig["args"].([]string)...)

			case []interface{}:
				for _, v := range fuguConfig["args"].([]interface{}) {
					switch v.(type) {
					case string:
						execArgs = append(execArgs, v.(string))

					default:
						panic(fmt.Sprintf("unknown type %#v", v))
					}
				}

			case string:
				execArgs = append(execArgs, fuguConfig["args"].(string))

			default:
				panic(fmt.Sprintf("unknown type %#v", fuguConfig["args"]))
			}
		}

		fmt.Printf("docker run %s\n\n", execArgs)

		cmd := exec.Command("docker", execArgs...)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Stdin = os.Stdin
		cmd.Run()

	case "build":
		fmt.Println("@todo")
		// os.Exit(2)
	default:
		// os.Exit(1)
	}
}

func isFuguFile(file string, extensions []string) bool {
	for _, ext := range extensions {
		if path.Ext(file) == ext {
			return true
		}
	}
	return false
}

func fileExists(filePath string) bool {
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func isLabel(label string, search []string) bool {
	for _, l := range search {
		if label == l {
			return true
		}
	}
	return false
}

func fileExtensions(s []string) []string {
	su := make([]string, 0)
	exts := make(map[string]bool)
	for _, v := range s {
		ext := path.Ext(v)
		if _, ok := exts[ext]; !ok {
			exts[ext] = true
			su = append(su, ext)
		}
	}
	return su
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"

	"code.cloudfoundry.org/cli/cf/manifest"
	"code.cloudfoundry.org/cli/plugin"
	"strings"
)

var PluginVersion string

type CfPlugin struct {
	Connection plugin.CliConnection
	Deployer   BlueGreenDeployer
}

func (p *CfPlugin) Run(cliConnection plugin.CliConnection, args []string) {
	if len(args) > 0 && args[0] == "CLI-MESSAGE-UNINSTALL" {
		return
	}

	p.Connection = cliConnection

	defaultCfDomain, err := p.DefaultCfDomain()
	if err != nil {
		fmt.Println("Failed to get default shared domain")
		os.Exit(1)
	}

	p.Deployer.Setup(cliConnection)

	if len(args) < 2 {
		fmt.Println("App name must be provided")
		os.Exit(1)
	}

	if !p.Deploy(defaultCfDomain, manifest.DiskRepository{}, args) {
		fmt.Println("Smoke tests failed")
		os.Exit(1)
	}
}

func (p *CfPlugin) Deploy(defaultCfDomain string, repo manifest.Repository, args []string) bool {
	appName := args[1]

	p.Deployer.DeleteAllAppsExceptLiveApp(appName)
	liveAppName, liveAppRoutes := p.Deployer.LiveApp(appName)

	newAppName := appName + "-new"
	tempRoute := Route{Host: newAppName, Domain: Domain{Name: defaultCfDomain}}
	p.Deployer.PushNewApp(newAppName, tempRoute)

	promoteNewApp := true
	smokeTestScript := ExtractIntegrationTestScript(args)
	if smokeTestScript != "" {
		promoteNewApp = p.Deployer.RunSmokeTests(smokeTestScript, tempRoute.FQDN())
	}

	newAppRoutes := p.GetNewAppRoutes(appName, defaultCfDomain, repo, liveAppRoutes)

	p.Deployer.UnmapRoutesFromApp(newAppName, tempRoute)

	if promoteNewApp {
		if liveAppName != "" {
			p.Deployer.MapRoutesToApp(newAppName, newAppRoutes...)
			p.Deployer.RenameApp(liveAppName, appName+"-old")
			p.Deployer.RenameApp(newAppName, appName)
			p.Deployer.UnmapRoutesFromApp(appName+"-old", liveAppRoutes...)
		} else {
			p.Deployer.MapRoutesToApp(newAppName, newAppRoutes...)
			p.Deployer.RenameApp(newAppName, appName)
		}
		return true
	} else {
		p.Deployer.RenameApp(newAppName, appName+"-failed")
		return false
	}
}

func (p *CfPlugin) GetNewAppRoutes(appName string, defaultCfDomain string, repo manifest.Repository, liveAppRoutes []Route) []Route {
	newAppRoutes := []Route{}
	f := ManifestAppFinder{AppName: appName, Repo: repo}
	if manifestRoutes := f.RoutesFromManifest(defaultCfDomain); manifestRoutes != nil {
		newAppRoutes = append(newAppRoutes, manifestRoutes...)
	}
	uniqueRoutes := p.UnionRouteLists(newAppRoutes, liveAppRoutes)

	if len(uniqueRoutes) == 0 {
		uniqueRoutes = append(uniqueRoutes, Route{Host: appName, Domain: Domain{Name: defaultCfDomain}})
	}
	return uniqueRoutes
}

func (p *CfPlugin) UnionRouteLists(listA []Route, listB []Route) []Route {
	duplicateList := append(listA, listB...)

	routesSet := make(map[Route]struct{})

	for _, route := range duplicateList {
		routesSet[route] = struct{}{}
	}

	uniqueRoutes := []Route{}
	for route := range routesSet {
		uniqueRoutes = append(uniqueRoutes, route)
	}
	return uniqueRoutes
}

func (p *CfPlugin) GetMetadata() plugin.PluginMetadata {
	var major, minor, build int
	fmt.Sscanf(PluginVersion, "%d.%d.%d", &major, &minor, &build)

	return plugin.PluginMetadata{
		Name: "blue-green-deploy",
		Version: plugin.VersionType{
			Major: major,
			Minor: minor,
			Build: build,
		},
		Commands: []plugin.Command{
			{
				Name:     "blue-green-deploy",
				Alias:    "bgd",
				HelpText: "Zero-downtime deploys with smoke tests",
				UsageDetails: plugin.Usage{
					Usage: "blue-green-deploy APP_NAME [--smoke-test TEST_SCRIPT]",
					Options: map[string]string{
						"smoke-test": "The test script to run.",
					},
				},
			},
		},
	}
}

func (p *CfPlugin) DefaultCfDomain() (domain string, err error) {
	var res []string
	if res, err = p.Connection.CliCommandWithoutTerminalOutput("curl", "/v2/shared_domains"); err != nil {
		return
	}

	response := struct {
		Resources []struct {
			Entity struct {
				Name string
			}
		}
	}{}

	var json_string string
	json_string = strings.Join(res, "\n")

	if err = json.Unmarshal([]byte(json_string), &response); err != nil {
		return
	}

	domain = response.Resources[0].Entity.Name
	return
}

func ExtractIntegrationTestScript(args []string) string {
	f := flag.NewFlagSet("blue-green-deploy", flag.ExitOnError)
	script := f.String("smoke-test", "", "")
	f.Parse(args[2:])
	return *script
}

func main() {
	p := CfPlugin{
		Deployer: &BlueGreenDeploy{
			ErrorFunc: func(message string, err error) {
				fmt.Printf("%v - %v\n", message, err)
				os.Exit(1)
			},
			Out: os.Stdout,
		},
	}

	plugin.Start(&p)
}
<commit_msg>Reinstate code to assign i18n.T to a translate function, to avoid NPE in cf cli internals<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"

	"code.cloudfoundry.org/cli/cf/i18n"
	"code.cloudfoundry.org/cli/cf/manifest"
	"code.cloudfoundry.org/cli/plugin"
	go_i18n "github.com/nicksnyder/go-i18n/i18n"
	"strings"
)

var PluginVersion string

type CfPlugin struct {
	Connection plugin.CliConnection
	Deployer   BlueGreenDeployer
}

func (p *CfPlugin) Run(cliConnection plugin.CliConnection, args []string) {
	if len(args) > 0 && args[0] == "CLI-MESSAGE-UNINSTALL" {
		return
	}

	p.Connection = cliConnection

	defaultCfDomain, err := p.DefaultCfDomain()
	if err != nil {
		fmt.Println("Failed to get default shared domain")
		os.Exit(1)
	}

	p.Deployer.Setup(cliConnection)

	if len(args) < 2 {
		fmt.Println("App name must be provided")
		os.Exit(1)
	}

	if !p.Deploy(defaultCfDomain, manifest.DiskRepository{}, args) {
		fmt.Println("Smoke tests failed")
		os.Exit(1)
	}
}

func (p *CfPlugin) Deploy(defaultCfDomain string, repo manifest.Repository, args []string) bool {
	appName := args[1]

	p.Deployer.DeleteAllAppsExceptLiveApp(appName)
	liveAppName, liveAppRoutes := p.Deployer.LiveApp(appName)

	newAppName := appName + "-new"
	tempRoute := Route{Host: newAppName, Domain: Domain{Name: defaultCfDomain}}
	p.Deployer.PushNewApp(newAppName, tempRoute)

	promoteNewApp := true
	smokeTestScript := ExtractIntegrationTestScript(args)
	if smokeTestScript != "" {
		promoteNewApp = p.Deployer.RunSmokeTests(smokeTestScript, tempRoute.FQDN())
	}

	newAppRoutes := p.GetNewAppRoutes(appName, defaultCfDomain, repo, liveAppRoutes)

	p.Deployer.UnmapRoutesFromApp(newAppName, tempRoute)

	if promoteNewApp {
		if liveAppName != "" {
			p.Deployer.MapRoutesToApp(newAppName, newAppRoutes...)
			p.Deployer.RenameApp(liveAppName, appName+"-old")
			p.Deployer.RenameApp(newAppName, appName)
			p.Deployer.UnmapRoutesFromApp(appName+"-old", liveAppRoutes...)
		} else {
			p.Deployer.MapRoutesToApp(newAppName, newAppRoutes...)
			p.Deployer.RenameApp(newAppName, appName)
		}
		return true
	} else {
		p.Deployer.RenameApp(newAppName, appName+"-failed")
		return false
	}
}

func (p *CfPlugin) GetNewAppRoutes(appName string, defaultCfDomain string, repo manifest.Repository, liveAppRoutes []Route) []Route {
	newAppRoutes := []Route{}
	f := ManifestAppFinder{AppName: appName, Repo: repo}
	if manifestRoutes := f.RoutesFromManifest(defaultCfDomain); manifestRoutes != nil {
		newAppRoutes = append(newAppRoutes, manifestRoutes...)
	}
	uniqueRoutes := p.UnionRouteLists(newAppRoutes, liveAppRoutes)

	if len(uniqueRoutes) == 0 {
		uniqueRoutes = append(uniqueRoutes, Route{Host: appName, Domain: Domain{Name: defaultCfDomain}})
	}
	return uniqueRoutes
}

func (p *CfPlugin) UnionRouteLists(listA []Route, listB []Route) []Route {
	duplicateList := append(listA, listB...)

	routesSet := make(map[Route]struct{})

	for _, route := range duplicateList {
		routesSet[route] = struct{}{}
	}

	uniqueRoutes := []Route{}
	for route := range routesSet {
		uniqueRoutes = append(uniqueRoutes, route)
	}
	return uniqueRoutes
}

func (p *CfPlugin) GetMetadata() plugin.PluginMetadata {
	var major, minor, build int
	fmt.Sscanf(PluginVersion, "%d.%d.%d", &major, &minor, &build)

	return plugin.PluginMetadata{
		Name: "blue-green-deploy",
		Version: plugin.VersionType{
			Major: major,
			Minor: minor,
			Build: build,
		},
		Commands: []plugin.Command{
			{
				Name:     "blue-green-deploy",
				Alias:    "bgd",
				HelpText: "Zero-downtime deploys with smoke tests",
				UsageDetails: plugin.Usage{
					Usage: "blue-green-deploy APP_NAME [--smoke-test TEST_SCRIPT]",
					Options: map[string]string{
						"smoke-test": "The test script to run.",
					},
				},
			},
		},
	}
}

func (p *CfPlugin) DefaultCfDomain() (domain string, err error) {
	var res []string
	if res, err = p.Connection.CliCommandWithoutTerminalOutput("curl", "/v2/shared_domains"); err != nil {
		return
	}

	response := struct {
		Resources []struct {
			Entity struct {
				Name string
			}
		}
	}{}

	var json_string string
	json_string = strings.Join(res, "\n")

	if err = json.Unmarshal([]byte(json_string), &response); err != nil {
		return
	}

	domain = response.Resources[0].Entity.Name
	return
}

func ExtractIntegrationTestScript(args []string) string {
	f := flag.NewFlagSet("blue-green-deploy", flag.ExitOnError)
	script := f.String("smoke-test", "", "")
	f.Parse(args[2:])
	return *script
}

func main() {
	// T needs to point to a translate func, otherwise cf internals blow up
	i18n.T, _ = go_i18n.Tfunc("")

	p := CfPlugin{
		Deployer: &BlueGreenDeploy{
			ErrorFunc: func(message string, err error) {
				fmt.Printf("%v - %v\n", message, err)
				os.Exit(1)
			},
			Out: os.Stdout,
		},
	}

	plugin.Start(&p)
}
<|endoftext|>


<commit_before>// +build windows

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/StackExchange/wmi"
)

// Win32_Volume - wmic volume where DriveType=3 list brief
// https://msdn.microsoft.com/en-us/library/aa394515(v=vs.85).aspx
type Win32_Volume struct {
	Capacity   uint64
	DriveType  uint32
	FileSystem string
	FreeSpace  uint64
	Label      *string
	Name       string
}

// Win32_ComputerSystem - wmic ComputerSystem
// https://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx
type Win32_ComputerSystem struct {
	TotalPhysicalMemory uint64
}

// Win32_OperatingSystem - blah blah
// https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx
type Win32_OperatingSystem struct {
	FreePhysicalMemory     uint64
	FreeVirtualMemory      uint64
	NumberOfProcesses      uint64
	TotalVirtualMemorySize uint64
	TotalVisibleMemorySize uint64
}

// Stat represents stats to send to graphite
type Stat struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	DT    int64  `json:"dt"`
}

func schedule(what func(), delay time.Duration) chan bool {
	stop := make(chan bool)

	go func() {
		for {
			what()
			select {
			case <-time.After(delay):
			case <-stop:
				return
			}
		}
	}()

	return stop
}

func getOperatingSystemStats() (stats []Stat) {
	var dst []Win32_OperatingSystem

	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	stats = append(stats, Stat{"mem.physical.free", strconv.FormatUint(dst[0].FreePhysicalMemory, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.virtual.free", strconv.FormatUint(dst[0].FreeVirtualMemory, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.virtual.total", strconv.FormatUint(dst[0].TotalVirtualMemorySize, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.visible.total", strconv.FormatUint(dst[0].TotalVisibleMemorySize, 10), time.Now().Unix()})
	stats = append(stats, Stat{"processes.total", strconv.FormatUint(dst[0].NumberOfProcesses, 10), time.Now().Unix()})

	return
}

func getComputerSystemStats() (stats []Stat) {
	var dst []Win32_ComputerSystem

	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	stats = append(stats, Stat{"mem.physical.total", strconv.FormatUint(dst[0].TotalPhysicalMemory, 10), time.Now().Unix()})
	return
}

func getDiskStats() (stats []Stat) {
	var dst []Win32_Volume
	nonAlphaNumReg, _ := regexp.Compile("[^A-Za-z0-9]+")

	q := wmi.CreateQuery(&dst, "Where DriveType=3 and NOT Label='System Reserved'")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	for _, v := range dst {
		keyPrefix := fmt.Sprintf("disk.%s", nonAlphaNumReg.ReplaceAllLiteralString(v.Name, "_"))
		percent := int64(100 * (float64(v.FreeSpace) / float64(v.Capacity)))

		stats = append(stats, Stat{fmt.Sprintf("%s.percent_used", keyPrefix), strconv.FormatInt(percent, 10), time.Now().Unix()})
		stats = append(stats, Stat{fmt.Sprintf("%s.free", keyPrefix), strconv.FormatUint(v.FreeSpace, 10), time.Now().Unix()})
		stats = append(stats, Stat{fmt.Sprintf("%s.avail", keyPrefix), strconv.FormatUint(v.Capacity, 10), time.Now().Unix()})
	}

	return
}
func getCPUStats() (stats []Stat) {
	var out bytes.Buffer
	cmd := exec.Command("typeperf", "-sc", "1", "processor(_total)\\% processor time")
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	chunks := strings.Split(out.String(), ",")
	chunks = strings.Split(chunks[2], "\"")
	stats = append(stats, Stat{"cpu", chunks[1], time.Now().Unix()})
	return
}

func getStats() (stats []Stat) {
	stats = append(stats, getCPUStats()...)
	stats = append(stats, getDiskStats()...)
	stats = append(stats, getComputerSystemStats()...)
	stats = append(stats, getOperatingSystemStats()...)
	return
}

func main() {
	var stats []Stat
	getStatsInterval := func() {
		newStats := getStats()
		stats = append(stats, newStats...)
	}
	outputStatsInterval := func() {
		var stat Stat
		for len(stats) != 0 {
			stat, stats = stats[len(stats)-1], stats[:len(stats)-1]
			b, _ := json.Marshal(stat)
			log.Printf("Output: %s", string(b))
		}
	}
	/*stopGet := */ schedule(getStatsInterval, 5*time.Second)
	/*stopOutput := */ schedule(outputStatsInterval, 5*time.Millisecond)
	for {
		time.Sleep(100 * time.Second)
	}
}
<commit_msg>badly named function, but get me some sweet sweet disk io stats<commit_after>// +build windows

package main

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/StackExchange/wmi"
)

// Win32_Volume - wmic volume where DriveType=3 list brief
// https://msdn.microsoft.com/en-us/library/aa394515(v=vs.85).aspx
type Win32_Volume struct {
	Capacity   uint64
	DriveType  uint32
	FileSystem string
	FreeSpace  uint64
	Label      *string
	Name       string
}

// Win32_ComputerSystem - wmic ComputerSystem
// https://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx
type Win32_ComputerSystem struct {
	TotalPhysicalMemory uint64
}

// Win32_OperatingSystem - blah blah
// https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx
type Win32_OperatingSystem struct {
	FreePhysicalMemory     uint64
	FreeVirtualMemory      uint64
	NumberOfProcesses      uint64
	TotalVirtualMemorySize uint64
	TotalVisibleMemorySize uint64
}

// Stat represents stats to send to graphite
type Stat struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	DT    int64  `json:"dt"`
}

func schedule(what func(), delay time.Duration) chan bool {
	stop := make(chan bool)

	go func() {
		for {
			what()
			select {
			case <-time.After(delay):
			case <-stop:
				return
			}
		}
	}()

	return stop
}

func getOperatingSystemStats() (stats []Stat) {
	var dst []Win32_OperatingSystem

	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	stats = append(stats, Stat{"mem.physical.free", strconv.FormatUint(dst[0].FreePhysicalMemory, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.virtual.free", strconv.FormatUint(dst[0].FreeVirtualMemory, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.virtual.total", strconv.FormatUint(dst[0].TotalVirtualMemorySize, 10), time.Now().Unix()})
	stats = append(stats, Stat{"mem.visible.total", strconv.FormatUint(dst[0].TotalVisibleMemorySize, 10), time.Now().Unix()})
	stats = append(stats, Stat{"processes.total", strconv.FormatUint(dst[0].NumberOfProcesses, 10), time.Now().Unix()})

	return
}

func getComputerSystemStats() (stats []Stat) {
	var dst []Win32_ComputerSystem

	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	stats = append(stats, Stat{"mem.physical.total", strconv.FormatUint(dst[0].TotalPhysicalMemory, 10), time.Now().Unix()})
	return
}

var nonAlphaNumReg = regexp.MustCompile("[^A-Za-z0-9]+")

func happyDriveName(driveLetter string) string {
	return nonAlphaNumReg.ReplaceAllLiteralString(driveLetter, "")
}

func getDiskStats() (stats []Stat) {
	var dst []Win32_Volume

	q := wmi.CreateQuery(&dst, "Where DriveType=3 and NOT Label='System Reserved'")
	err := wmi.Query(q, &dst)
	if err != nil {
		log.Fatal(err)
	}
	for _, v := range dst {
		keyPrefix := fmt.Sprintf("disk.%s", happyDriveName(v.Name))
		percent := int64(100 * (float64(v.FreeSpace) / float64(v.Capacity)))

		stats = append(stats, Stat{fmt.Sprintf("%s.percent_used", keyPrefix), strconv.FormatInt(percent, 10), time.Now().Unix()})
		stats = append(stats, Stat{fmt.Sprintf("%s.free", keyPrefix), strconv.FormatUint(v.FreeSpace, 10), time.Now().Unix()})
		stats = append(stats, Stat{fmt.Sprintf("%s.avail", keyPrefix), strconv.FormatUint(v.Capacity, 10), time.Now().Unix()})
	}

	return
}

func callTypePerf(fields []string) (headers []string, records [][]string) {
	var (
		cmdOut []byte
		err    error
	)
	cmdName := "typeperf"
	cmdArgs := []string{
		"-sc",
		"1",
	}
	cmdArgs = append(cmdArgs, fields...)
	if cmdOut, err = exec.Command(cmdName, cmdArgs...).Output(); err != nil {
		fmt.Fprintln(os.Stderr, "There was an error running typeperf command: ", err)
		os.Exit(1)
	}
	var lines []string
	for _, line := range strings.Split(string(cmdOut), "\n") {
		if strings.HasPrefix(line, "\"") {
			lines = append(lines, line)
		}
	}

	r := csv.NewReader(strings.NewReader(strings.Join(lines, "\n")))
	records, err = r.ReadAll()
	if err != nil {
		log.Fatal(err)
	}

	headers, records = records[0], records[1:]
	return
}

var logicalDiskRegex = regexp.MustCompile("^LogicalDisk\\(([^)]+)\\)$")
var logicalDiskStatMap = map[string]string{
	"Avg. Disk sec/Read":  "disk_read_io",
	"Avg. Disk sec/Write": "disk_write_io",
}

func getCPUStats() (stats []Stat) {
	headers, records := callTypePerf([]string{
		"processor(_total)\\% processor time",
		"LogicalDisk(*)\\Avg. Disk sec/Read",
		"LogicalDisk(*)\\Avg. Disk sec/Write",
	})
	for headerNum, header := range headers[1:] {
		headerParts := strings.Split(header, "\\")
		headers[headerNum] = strings.Join(headerParts[3:len(headerParts)], "\\")
	}
	for _, row := range records {
		for colNum, col := range row[1:] {
			headerParts := strings.Split(headers[colNum], "\\")

			if strings.HasPrefix(headerParts[0], "processor(") {
				stats = append(stats, Stat{"cpu", col, time.Now().Unix()})
				continue
			}

			if results := logicalDiskRegex.FindStringSubmatch(headerParts[0]); results != nil {
				if results[1] == "_Total" {
					continue
				}
				if strings.HasPrefix(results[1], "HarddiskVolume") {
					continue
				}

				keyPrefix := fmt.Sprintf("disk.%s", happyDriveName(results[1]))
				fieldName, ok := logicalDiskStatMap[strings.Join(headerParts[1:], "/")]
				if ok {
					stats = append(stats, Stat{
						fmt.Sprintf("%s.%s", keyPrefix, fieldName),
						col,
						time.Now().Unix(),
					})
					continue
				}
			}

			// happyDriveName
			log.Printf("%s = %s", headers[colNum], col)
		}
	}
	return
}

func getStats() (stats []Stat) {
	stats = append(stats, getCPUStats()...)
	stats = append(stats, getDiskStats()...)
	stats = append(stats, getComputerSystemStats()...)
	stats = append(stats, getOperatingSystemStats()...)
	return
}

func main() {
	var stats []Stat
	getStatsInterval := func() {
		newStats := getStats()
		stats = append(stats, newStats...)
	}
	outputStatsInterval := func() {
		var stat Stat
		for len(stats) != 0 {
			stat, stats = stats[0], stats[1:]
			b, _ := json.Marshal(stat)
			log.Printf("Output: %s", string(b))
		}
	}
	/*stopGet := */ schedule(getStatsInterval, 5*time.Second)
	/*stopOutput := */ schedule(outputStatsInterval, 5*time.Millisecond)
	for {
		time.Sleep(100 * time.Second)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/koron/go-arch"
)

// TODO: better messaging

const (
	urlWin32     = "http://files.kaoriya.net/vim/vim74-kaoriya-win32.zip"
	urlWin64     = "http://files.kaoriya.net/vim/vim74-kaoriya-win64.zip"
	urlWin32Test = "http://files.kaoriya.net/vim/vim74-kaoriya-win32-test.zip"
	urlWin64Test = "http://files.kaoriya.net/vim/vim74-kaoriya-win64-test.zip"
)

var (
	errNotModified     = errors.New("not modified")
	errUnsupportedArch = errors.New("unsupported architecture")
)

var (
	help    = flag.Bool("h", false, "show this message")
	target  = flag.String("t", mustGetwd(), "target dir to upgrade/install")
	restore = flag.Bool("r", false, "restore all files (WIP)")
	beta    = flag.Bool("b", false, "use beta release")
)

func mustGetwd() string {
	d, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return d
}

func determineSourceURL(c *config) (string, error) {
	if *beta {
		switch c.cpu {
		case arch.X86:
			return urlWin32Test, nil
		case arch.AMD64:
			return urlWin64Test, nil
		default:
			return "", errUnsupportedArch
		}
	}
	switch c.cpu {
	case arch.X86:
		return urlWin32, nil
	case arch.AMD64:
		return urlWin64, nil
	default:
		return "", errUnsupportedArch
	}
}

func download(url, outpath string, pivot time.Time) error {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	if !pivot.IsZero() {
		t := pivot.UTC().Format(http.TimeFormat)
		req.Header.Set("If-Modified-Since", t)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case http.StatusOK:
		f, err := os.Create(outpath)
		if err != nil {
			return err
		}
		defer f.Close()
		if _, err := io.Copy(f, resp.Body); err != nil {
			return err
		}

	case http.StatusNotModified:
		return errNotModified

	default:
		return fmt.Errorf("unexpected response: %s", resp.Status)
	}
	return nil
}

func saveFileInfo(fname string, t fileInfoTable) error {
	f, err := os.Create(fname)
	if err != nil {
		return nil
	}
	defer f.Close()
	for _, v := range t {
		fmt.Fprintf(f, fileInfoFormat, v.name, v.size, v.hash)
	}
	return f.Sync()
}

// cleanFiles removes unused/untracked files.
func cleanFiles(dir string, prev, curr fileInfoTable) {
	for _, p := range prev {
		if _, ok := curr[p.name]; ok {
			continue
		}
		fpath := filepath.Join(dir, p.name)
		if r, _ := p.compareWithFile(fpath); r != fileIsMatch {
			continue
		}
		os.Remove(fpath)
	}
}

func extract(dir, zipName, recipeName string) error {
	prev, err := loadFileInfo(recipeName)
	if err != nil {
		log.Printf("WARN: failed to load recipe: %s", err)
		log.Println("INFO: try to extract all files")
		prev = make(fileInfoTable)
	}
	curr, err := extractZip(zipName, dir, 1, prev)
	if err != nil {
		return err
	}
	if err := saveFileInfo(recipeName, curr); err != nil {
		log.Printf("WARN: failed to save recipe: %s", err)
	}
	cleanFiles(dir, prev, curr)
	return nil
}

func update(c *config) error {
	return update2(c)
}

func update1(c *config) error {
	srcURL, err := determineSourceURL(c)
	if err != nil {
		return err
	}
	dp, err := c.downloadPath(srcURL)
	if err != nil {
		return err
	}
	anchor, err := c.anchor()
	if err != nil {
		return err
	}
	if err := download(srcURL, dp, anchor); err != nil {
		if err == errNotModified {
			return nil
		}
		return err
	}
	anchor = time.Now()
	if err := extract(c.targetDir, dp, c.recipePath()); err != nil {
		return err
	}
	if err := c.updateAnchor(anchor); err != nil {
		os.Remove(c.anchorPath())
		return err
	}
	if err := os.Remove(dp); err != nil {
		log.Printf("WARN: failed to remove: %s", err)
	}
	return nil
}

func update2(c *config) error {
	t, err := c.anchor()
	if err != nil {
		return err
	}
	s, err := determineSource(c.source, c.cpu)
	if err != nil {
		return err
	}
	p, err := s.download(c.tmpDir, t)
	if err != nil {
		if err == errSourceNotModified {
			err = nil
		}
		return err
	}
	// capture anchor's new value.
	t = time.Now()
	if err := extract(c.targetDir, p, c.recipePath()); err != nil {
		return err
	}
	if err := c.updateAnchor(t); err != nil {
		os.Remove(c.anchorPath())
		return err
	}
	if err := os.Remove(p); err != nil {
		log.Printf("WARN: failed to remove: %s", err)
	}
	return nil
}

func showHelp() {
	fmt.Fprintf(os.Stderr, `%[1]s is tool to upgrade/install Vim (+kaoriya) in/to target dir.

Usage: %[1]s [options]

Options are:
`, filepath.Base(os.Args[0]))
	flag.PrintDefaults()
}

func main() {
	flag.Parse()
	if *help {
		showHelp()
		os.Exit(1)
	}
	c, err := newConfig(*target)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.prepare(); err != nil {
		log.Fatal(err)
	}
	if err := update(c); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>remove unused codes<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
)

// TODO: better messaging

var (
	help    = flag.Bool("h", false, "show this message")
	target  = flag.String("t", mustGetwd(), "target dir to upgrade/install")
	restore = flag.Bool("r", false, "restore all files (WIP)")
	beta    = flag.Bool("b", false, "use beta release")
)

func mustGetwd() string {
	d, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return d
}

func saveFileInfo(fname string, t fileInfoTable) error {
	f, err := os.Create(fname)
	if err != nil {
		return nil
	}
	defer f.Close()
	for _, v := range t {
		fmt.Fprintf(f, fileInfoFormat, v.name, v.size, v.hash)
	}
	return f.Sync()
}

// cleanFiles removes unused/untracked files.
func cleanFiles(dir string, prev, curr fileInfoTable) {
	for _, p := range prev {
		if _, ok := curr[p.name]; ok {
			continue
		}
		fpath := filepath.Join(dir, p.name)
		if r, _ := p.compareWithFile(fpath); r != fileIsMatch {
			continue
		}
		os.Remove(fpath)
	}
}

func extract(dir, zipName, recipeName string) error {
	prev, err := loadFileInfo(recipeName)
	if err != nil {
		log.Printf("WARN: failed to load recipe: %s", err)
		log.Println("INFO: try to extract all files")
		prev = make(fileInfoTable)
	}
	curr, err := extractZip(zipName, dir, 1, prev)
	if err != nil {
		return err
	}
	if err := saveFileInfo(recipeName, curr); err != nil {
		log.Printf("WARN: failed to save recipe: %s", err)
	}
	cleanFiles(dir, prev, curr)
	return nil
}

func update(c *config) error {
	t, err := c.anchor()
	if err != nil {
		return err
	}
	s, err := determineSource(c.source, c.cpu)
	if err != nil {
		return err
	}
	p, err := s.download(c.tmpDir, t)
	if err != nil {
		if err == errSourceNotModified {
			err = nil
		}
		return err
	}
	// capture anchor's new value.
	t = time.Now()
	if err := extract(c.targetDir, p, c.recipePath()); err != nil {
		return err
	}
	if err := c.updateAnchor(t); err != nil {
		os.Remove(c.anchorPath())
		return err
	}
	if err := os.Remove(p); err != nil {
		log.Printf("WARN: failed to remove: %s", err)
	}
	return nil
}

func showHelp() {
	fmt.Fprintf(os.Stderr, `%[1]s is tool to upgrade/install Vim (+kaoriya) in/to target dir.

Usage: %[1]s [options]

Options are:
`, filepath.Base(os.Args[0]))
	flag.PrintDefaults()
}

func main() {
	flag.Parse()
	if *help {
		showHelp()
		os.Exit(1)
	}
	c, err := newConfig(*target)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.prepare(); err != nil {
		log.Fatal(err)
	}
	if err := update(c); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rsa"
	"crypto/x509"
	"database/sql"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"github.com/auth0/go-jwt-middleware"
	"github.com/dgrijalva/jwt-go"
	"github.com/gorilla/context"
	"github.com/gorilla/mux"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/patrickmn/go-cache"
	"github.com/pquerna/cachecontrol"
	"github.com/rs/cors"
	"github.com/urfave/negroni"
	"log"
	"net/http"
	"os"
	"sort"
	"strconv"
	"time"
)

var myClient = &http.Client{Timeout: 10 * time.Second}
var myCache = cache.New(5*time.Hour, 10*time.Minute)

func getKey(kid string) (*rsa.PublicKey, error) {
	pemData, found := myCache.Get(kid)
	if found {
		log.Printf("Public key found in cache: %s", kid)
	} else {
		log.Printf("No public key found in cache: %s", kid)

		// Get the new public keys (pem data) from google
		req, _ := http.NewRequest("GET", "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com", nil)
		res, err := http.DefaultClient.Do(req)
		if err != nil {
			return nil, err
		}

		// The response contains multiple PEMs
		decoder := json.NewDecoder(res.Body)
		personMap := make(map[string]interface{})
		err = decoder.Decode(&personMap)
		if err != nil {
			return nil, err
		}

		// Try to cache the values for next requests
		reasons, expires, _ := cachecontrol.CachableResponse(req, res, cachecontrol.Options{})
		if len(reasons) == 0 {
			timeUntilExpiration := time.Until(expires)
			log.Println("Caching public keys for: ", timeUntilExpiration)

			// Save all the identities
			for id, publicKeyData := range personMap {
				myCache.Set(id, publicKeyData, timeUntilExpiration)
			}
		} else {
			log.Println("Unable to cache public key:", reasons)
		}

		pemData = personMap[kid]
	}

	block, _ := pem.Decode([]byte(pemData.(string)))
	var cert *x509.Certificate
	cert, _ = x509.ParseCertificate(block.Bytes)
	rsaPublicKey := cert.PublicKey.(*rsa.PublicKey)
	return rsaPublicKey, nil
}

func parseMeasurements(r *http.Request) ([]Measurement, error) {
	decoder := json.NewDecoder(r.Body)
	var measurements []Measurement
	err := decoder.Decode(&measurements)
	if err != nil {
		return measurements, err
	}
	defer r.Body.Close()
	return measurements, nil
}

func mapMeasurements(measurements []Measurement) []PlotData {
	dates := make(map[time.Time]PlotData)
	for _, measurement := range measurements {
		_, ok := dates[measurement.Timestamp.Time]
		if !ok {
			values := make(map[string]float64)
			plot := PlotData{Date: measurement.Timestamp.Time, Values: values}
			dates[measurement.Timestamp.Time] = plot
		}
		plot, ok := dates[measurement.Timestamp.Time]
		plot.Values[measurement.Name] = measurement.Value
	}

	var plots = []PlotData{}
	for _, plot := range dates {
		plots = append(plots, plot)
	}

	sort.Slice(plots, func(i, j int) bool {
		return plots[i].Date.Sub(plots[j].Date) < 0
	})
	return plots
}

func getUser(r *http.Request) string {
	return context.Get(r, "user").(string)
	//return "CzWRnH3U5TUV4CLFniC4NfMyYlC3"

}

type Env struct {
	db *Database
}

func (env *Env) addMeasurements(w http.ResponseWriter, r *http.Request) {
	user := getUser(r)
	measurements, err := parseMeasurements(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	err = env.db.saveMeasurements(measurements, user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusCreated)
}

func (env *Env) getAllData(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readDataFromPlot(user, plotId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	plots := mapMeasurements(measurements)

	jsonData, err := json.Marshal(plots)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getHourlyData(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readHourlyDataFromPlot(user, plotId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	plots := mapMeasurements(measurements)
	jsonData, err := json.Marshal(plots)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getLatestData(w http.ResponseWriter, r *http.Request) {
	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readLatestDataFromPlot(user, plotId)
	if err != nil {
		if err == sql.ErrNoRows {
			http.Error(w, "Color not found", http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}

	plots := mapMeasurements(measurements)

	jsonData, err := json.Marshal(plots[0])
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getPlots(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	plots, err := env.db.getPlots(user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	jsonData, err := json.Marshal(plots)
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getPlot(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)
	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	plot, err := env.db.getPlot(plotId, user)
	if err != nil {
		if err == sql.ErrNoRows {
			http.Error(w, "Plot not found", http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}

	instruments, err := env.db.getInstruments(plotId)
	plot.Instruments = instruments

	jsonData, err := json.Marshal(plot)
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func parsePlot(r *http.Request) (Plot, error) {

	decoder := json.NewDecoder(r.Body)
	var plot Plot
	err := decoder.Decode(&plot)
	if err != nil {
		return Plot{}, err
	}
	defer r.Body.Close()
	return plot, nil
}

func (env *Env) addPlot(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	plot, err := parsePlot(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	updated_plot, err := env.db.savePlot(plot, user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	jsonData, _ := json.Marshal(updated_plot)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	w.Write(jsonData)

}

func (env *Env) getKey(w http.ResponseWriter, r *http.Request) {
	userId := getUser(r)
	key, err := env.db.getkeyForUser(userId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	user := User{Key: key}
	jsonData, _ := json.Marshal(user)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(jsonData)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Pitilt :)\n")
}

func main() {

	var err error

	//setup database
	var dbUri = os.Getenv("DATABASE_URI")
	if dbUri == "" {
		dbUri = "postgres://tilt:password@localhost:15432/tilt"
	}

	db, err := sqlx.Open("postgres", dbUri)
	if err != nil {
		log.Fatalln(err)
	}
	database := &Database{db: db}
	env := &Env{db: database}

	//create middleware for authing on google jwt from firebase
	jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
			key, err := getKey(token.Header["kid"].(string))
			return key, err
		},
		SigningMethod: jwt.SigningMethodRS256,
	})

	jwtCheckHandler := &JwtCheckHandler{db: database, jwtMiddleware: jwtMiddleware}
	keyCheckHandler := &KeyCheckHandler{db: database}

	//define routes
	router := mux.NewRouter()
	router.HandleFunc("/", hello).Methods("GET")

	measurementRouter := mux.NewRouter()
	measurementRouter.HandleFunc("/measurements/", env.addMeasurements).Methods("POST")
	router.PathPrefix("/measurements").Handler(negroni.New(
		keyCheckHandler,
		negroni.Wrap(measurementRouter),
	))

	plotsRouter := mux.NewRouter()
	plotsRouter.HandleFunc("/plots/{plotId}/data/all/", env.getAllData).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}/data/latest/", env.getLatestData).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}/data/hourly/", env.getHourlyData).Methods("GET")

	plotsRouter.HandleFunc("/plots/", env.getPlots).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}", env.getPlot).Methods("GET")
	plotsRouter.HandleFunc("/plots/", env.addPlot).Methods("POST")

	router.PathPrefix("/plots").Handler(negroni.New(
		jwtCheckHandler,
		negroni.Wrap(plotsRouter),
	))

	// Setup CORS-handling
	c := cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedHeaders: []string{"Content-Type", "Authorization"},
		AllowedMethods: []string{"GET", "HEAD", "POST", "PUT", "OPTIONS"},
	})

	n := negroni.New()
	n.Use(c)
	n.UseHandler(router)

	http.ListenAndServe(":8080", n)
}
<commit_msg>Add structured logging using logrus.<commit_after>package main

import (
	"crypto/rsa"
	"crypto/x509"
	"database/sql"
	"encoding/json"
	"encoding/pem"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/auth0/go-jwt-middleware"
	"github.com/dgrijalva/jwt-go"
	"github.com/gorilla/context"
	"github.com/gorilla/mux"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/meatballhat/negroni-logrus"
	"github.com/patrickmn/go-cache"
	"github.com/pquerna/cachecontrol"
	"github.com/rs/cors"
	"github.com/urfave/negroni"
	"net/http"
	"os"
	"sort"
	"strconv"
	"time"
)

var myClient = &http.Client{Timeout: 10 * time.Second}
var myCache = cache.New(5*time.Hour, 10*time.Minute)

func getKey(kid string) (*rsa.PublicKey, error) {
	pemData, found := myCache.Get(kid)
	if found {
		log.WithFields(log.Fields{"id": kid}).Info("Public key found in cache")
	} else {
		log.WithFields(log.Fields{"id": kid}).Info("No public key found in cache")

		// Get the new public keys (pem data) from google
		req, _ := http.NewRequest("GET", "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com", nil)
		res, err := http.DefaultClient.Do(req)
		if err != nil {
			return nil, err
		}

		// The response contains multiple PEMs
		decoder := json.NewDecoder(res.Body)
		personMap := make(map[string]interface{})
		err = decoder.Decode(&personMap)
		if err != nil {
			return nil, err
		}

		// Try to cache the values for next requests
		reasons, expires, _ := cachecontrol.CachableResponse(req, res, cachecontrol.Options{})
		if len(reasons) == 0 {
			timeUntilExpiration := time.Until(expires)
			log.WithFields(log.Fields{"timeUntilExpiry": timeUntilExpiration}).Info("Caching publice keys")

			// Save all the identities
			for id, publicKeyData := range personMap {
				myCache.Set(id, publicKeyData, timeUntilExpiration)
			}
		} else {
			log.Println("Unable to cache public key:", reasons)
		}

		pemData = personMap[kid]
	}

	block, _ := pem.Decode([]byte(pemData.(string)))
	var cert *x509.Certificate
	cert, _ = x509.ParseCertificate(block.Bytes)
	rsaPublicKey := cert.PublicKey.(*rsa.PublicKey)
	return rsaPublicKey, nil
}

func parseMeasurements(r *http.Request) ([]Measurement, error) {
	decoder := json.NewDecoder(r.Body)
	var measurements []Measurement
	err := decoder.Decode(&measurements)
	if err != nil {
		return measurements, err
	}
	defer r.Body.Close()
	return measurements, nil
}

func mapMeasurements(measurements []Measurement) []PlotData {
	dates := make(map[time.Time]PlotData)
	for _, measurement := range measurements {
		_, ok := dates[measurement.Timestamp.Time]
		if !ok {
			values := make(map[string]float64)
			plot := PlotData{Date: measurement.Timestamp.Time, Values: values}
			dates[measurement.Timestamp.Time] = plot
		}
		plot, ok := dates[measurement.Timestamp.Time]
		plot.Values[measurement.Name] = measurement.Value
	}

	var plots = []PlotData{}
	for _, plot := range dates {
		plots = append(plots, plot)
	}

	sort.Slice(plots, func(i, j int) bool {
		return plots[i].Date.Sub(plots[j].Date) < 0
	})
	return plots
}

func getUser(r *http.Request) string {
	return context.Get(r, "user").(string)
	//return "CzWRnH3U5TUV4CLFniC4NfMyYlC3"

}

type Env struct {
	db *Database
}

func (env *Env) addMeasurements(w http.ResponseWriter, r *http.Request) {
	user := getUser(r)
	measurements, err := parseMeasurements(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	err = env.db.saveMeasurements(measurements, user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusCreated)
}

func (env *Env) getAllData(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readDataFromPlot(user, plotId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	plots := mapMeasurements(measurements)

	jsonData, err := json.Marshal(plots)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getHourlyData(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readHourlyDataFromPlot(user, plotId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	plots := mapMeasurements(measurements)
	jsonData, err := json.Marshal(plots)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getLatestData(w http.ResponseWriter, r *http.Request) {
	user := getUser(r)

	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	measurements, err := env.db.readLatestDataFromPlot(user, plotId)
	if err != nil {
		if err == sql.ErrNoRows {
			http.Error(w, "Color not found", http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}

	plots := mapMeasurements(measurements)

	jsonData, err := json.Marshal(plots[0])
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getPlots(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	plots, err := env.db.getPlots(user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	jsonData, err := json.Marshal(plots)
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func (env *Env) getPlot(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)
	vars := mux.Vars(r)
	plotId, err := strconv.Atoi(vars["plotId"])

	plot, err := env.db.getPlot(plotId, user)
	if err != nil {
		if err == sql.ErrNoRows {
			http.Error(w, "Plot not found", http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}

	instruments, err := env.db.getInstruments(plotId)
	plot.Instruments = instruments

	jsonData, err := json.Marshal(plot)
	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func parsePlot(r *http.Request) (Plot, error) {

	decoder := json.NewDecoder(r.Body)
	var plot Plot
	err := decoder.Decode(&plot)
	if err != nil {
		return Plot{}, err
	}
	defer r.Body.Close()
	return plot, nil
}

func (env *Env) addPlot(w http.ResponseWriter, r *http.Request) {

	user := getUser(r)

	plot, err := parsePlot(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	updated_plot, err := env.db.savePlot(plot, user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	jsonData, _ := json.Marshal(updated_plot)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	w.Write(jsonData)

}

func (env *Env) getKey(w http.ResponseWriter, r *http.Request) {
	userId := getUser(r)
	key, err := env.db.getkeyForUser(userId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	user := User{Key: key}
	jsonData, _ := json.Marshal(user)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(jsonData)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Pitilt :)\n")
}

func main() {

	var err error

	//setup database
	var dbUri = os.Getenv("DATABASE_URI")
	if dbUri == "" {
		dbUri = "postgres://tilt:password@localhost:15432/tilt"
	}

	db, err := sqlx.Open("postgres", dbUri)
	if err != nil {
		log.Fatalln(err)
	}
	database := &Database{db: db}
	env := &Env{db: database}

	//create middleware for authing on google jwt from firebase
	jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
			key, err := getKey(token.Header["kid"].(string))
			return key, err
		},
		SigningMethod: jwt.SigningMethodRS256,
	})

	jwtCheckHandler := &JwtCheckHandler{db: database, jwtMiddleware: jwtMiddleware}
	keyCheckHandler := &KeyCheckHandler{db: database}

	//define routes
	router := mux.NewRouter()
	router.HandleFunc("/", hello).Methods("GET")

	measurementRouter := mux.NewRouter()
	measurementRouter.HandleFunc("/measurements/", env.addMeasurements).Methods("POST")
	router.PathPrefix("/measurements").Handler(negroni.New(
		keyCheckHandler,
		negroni.Wrap(measurementRouter),
	))

	plotsRouter := mux.NewRouter()
	plotsRouter.HandleFunc("/plots/{plotId}/data/all/", env.getAllData).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}/data/latest/", env.getLatestData).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}/data/hourly/", env.getHourlyData).Methods("GET")

	plotsRouter.HandleFunc("/plots/", env.getPlots).Methods("GET")
	plotsRouter.HandleFunc("/plots/{plotId}", env.getPlot).Methods("GET")
	plotsRouter.HandleFunc("/plots/", env.addPlot).Methods("POST")

	router.PathPrefix("/plots").Handler(negroni.New(
		jwtCheckHandler,
		negroni.Wrap(plotsRouter),
	))

	// Setup CORS-handling
	c := cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedHeaders: []string{"Content-Type", "Authorization"},
		AllowedMethods: []string{"GET", "HEAD", "POST", "PUT", "OPTIONS"},
	})

	n := negroni.New()
	n.Use(negronilogrus.NewMiddleware())
	n.Use(c)
	n.UseHandler(router)

	http.ListenAndServe(":8080", n)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"
)

var regex = regexp.MustCompile("(?m)[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}")
var verbose = false

var urls = []string{
	"myipinfo.net",
	"myip.dnsomatic.com",
	"icanhazip.com",
	"checkip.dyndns.org",
	"www.myipnumber.com",
	"checkmyip.com",
	"myexternalip.com",
	"www.ipchicken.com",
	"ipecho.net/plain",
	"bot.whatismyipaddress.com",
	"ipv4.ipogre.com",
	"smart-ip.net/myip",
	"checkip.amazonaws.com",
	"www.checkip.org",
}

func main() {
	var interactive = false
	var currentIp net.IP = nil

	if len(os.Args) > 1 {
		for _, arg := range os.Args[1:] {
			switch arg {
			case "-v", "--version":
				verbose = true
			case "-i", "--interactive":
				interactive = true
			case "-h", "--help":
				fmt.Print(`
Usage: myip [options]
where options include:
	--local, -l		returns the local IP address(es)
	--verbose, -v		enable verbose output
	--interactive, -i	enable interactive mode
	--help, -h		print this help message
`)
				return
			case "-l", "--local":
				listLocalIP()
				return
			}
		}
	}

	if interactive {
		fmt.Println("Select a url from the list:")
		for i, url := range urls {
			fmt.Printf("	[%v] %v\n", i+1, url)
		}
		fmt.Printf("	[%v] custom url\n", len(urls)+1)

		var number int
		_, err := fmt.Scanln(&number)
		if err != nil || number <= 0 || number > (len(urls)+1) {
			fmt.Println("Incorrect value has been entered.")
			return
		}

		var url string
		if number == len(urls)+1 {
			fmt.Println("Enter url:")
			_, err := fmt.Scanln(&url)
			if err != nil {
				fmt.Println("Incorrect url has been entered.")
				return
			}
			if url == "" {
				return
			}

		} else {
			url = urls[number-1]
		}
		currentIp = getExternalIPByURL(url)
	} else {
		rand.Seed(time.Now().UTC().UnixNano())
		currentIp = getExternalIP()
	}

	if currentIp == nil {
		fmt.Println("No external IP address found.")
		return
	}
	fmt.Println(currentIp.String())
}

func listLocalIP() {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		if verbose {
			fmt.Printf("%v\n", err)
		}

		return
	}

	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				fmt.Println(ipnet.IP.String())
			}
		}
	}
}

func getExternalIP() net.IP {
	var currentIp net.IP
	for _, i := range rand.Perm(len(urls)) {
		if verbose {
			fmt.Printf("Connecting to %v...\n", urls[i])
		}

		url := "http://" + urls[i]

		content, err := getResponse(url)
		if err != nil {
			if verbose {
				fmt.Printf("%v\n", err)
			}
			continue
		}

		ip := regex.FindString(content)

		currentIp = net.ParseIP(ip)

		if currentIp != nil {
			return currentIp
		}

		fmt.Println("No valid IP address could be parsed from response.")
	}

	return currentIp
}

func getExternalIPByURL(url string) net.IP {
	if verbose {
		fmt.Printf("Connecting to %v...\n", url)
	}

	if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
		url = "http://" + url
	}

	content, err := getResponse(url)
	if err != nil {
		if verbose {
			fmt.Printf("%v\n", err)
		}
		return nil
	}

	ip := regex.FindString(content)

	currentIp := net.ParseIP(ip)

	if currentIp != nil {
		return currentIp
	}

	return nil
}

func getResponse(url string) (string, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", err
	}

	client := &http.Client{
		Timeout: time.Duration(3 * time.Second),
	}
	response, err := client.Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

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

	return string(content), nil
}
<commit_msg>Added check for invalid option.<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"
)

var regex = regexp.MustCompile("(?m)[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}")
var verbose = false

var urls = []string{
	"myipinfo.net",
	"myip.dnsomatic.com",
	"icanhazip.com",
	"checkip.dyndns.org",
	"www.myipnumber.com",
	"checkmyip.com",
	"myexternalip.com",
	"www.ipchicken.com",
	"ipecho.net/plain",
	"bot.whatismyipaddress.com",
	"ipv4.ipogre.com",
	"smart-ip.net/myip",
	"checkip.amazonaws.com",
	"www.checkip.org",
}

func main() {
	var interactive = false
	var currentIp net.IP = nil

	if len(os.Args) > 1 {
		for _, arg := range os.Args[1:] {
			switch arg {
			case "-v", "--version":
				verbose = true
			case "-i", "--interactive":
				interactive = true
			case "-h", "--help":
				fmt.Print(`
Usage: myip [options]
where options include:
	--local, -l		returns the local IP address(es)
	--verbose, -v		enable verbose output
	--interactive, -i	enable interactive mode
	--help, -h		print this help message
`)
				return
			case "-l", "--local":
				listLocalIP()
				return
			default:
				fmt.Print(`Invalid option: '` + arg + `'`)
				return
			}
		}
	}

	if interactive {
		fmt.Println("Select a url from the list:")
		for i, url := range urls {
			fmt.Printf("	[%v] %v\n", i + 1, url)
		}
		fmt.Printf("	[%v] custom url\n", len(urls) + 1)

		var number int
		_, err := fmt.Scanln(&number)
		if err != nil || number <= 0 || number > (len(urls) + 1) {
			fmt.Println("Incorrect value has been entered.")
			return
		}

		var url string
		if number == len(urls) + 1 {
			fmt.Println("Enter url:")
			_, err := fmt.Scanln(&url)
			if err != nil {
				fmt.Println("Incorrect url has been entered.")
				return
			}
			if url == "" {
				return
			}

		} else {
			url = urls[number - 1]
		}
		currentIp = getExternalIPByURL(url)
	} else {
		rand.Seed(time.Now().UTC().UnixNano())
		currentIp = getExternalIP()
	}

	if currentIp == nil {
		fmt.Println("No external IP address found.")
		return
	}
	fmt.Println(currentIp.String())
}

func listLocalIP() {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		if verbose {
			fmt.Printf("%v\n", err)
		}

		return
	}

	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				fmt.Println(ipnet.IP.String())
			}
		}
	}
}

func getExternalIP() net.IP {
	var currentIp net.IP
	for _, i := range rand.Perm(len(urls)) {
		if verbose {
			fmt.Printf("Connecting to %v...\n", urls[i])
		}

		url := "http://" + urls[i]

		content, err := getResponse(url)
		if err != nil {
			if verbose {
				fmt.Printf("%v\n", err)
			}
			continue
		}

		ip := regex.FindString(content)

		currentIp = net.ParseIP(ip)

		if currentIp != nil {
			return currentIp
		}

		fmt.Println("No valid IP address could be parsed from response.")
	}

	return currentIp
}

func getExternalIPByURL(url string) net.IP {
	if verbose {
		fmt.Printf("Connecting to %v...\n", url)
	}

	if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
		url = "http://" + url
	}

	content, err := getResponse(url)
	if err != nil {
		if verbose {
			fmt.Printf("%v\n", err)
		}
		return nil
	}

	ip := regex.FindString(content)

	currentIp := net.ParseIP(ip)

	if currentIp != nil {
		return currentIp
	}

	return nil
}

func getResponse(url string) (string, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", err
	}

	client := &http.Client{
		Timeout: time.Duration(3 * time.Second),
	}
	response, err := client.Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

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

	return string(content), nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	gltext "github.com/4ydx/gltext"
	glfw "github.com/go-gl/glfw3"
	gl32 "github.com/go-gl/glow/gl-core/3.2/gl"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"os"
	"runtime"
)

var useStrictCoreProfile = (runtime.GOOS == "darwin")

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func findCenter(windowWidth int, windowHeight int, x1, x2 gltext.Point) (lowerLeft gltext.Point) {
	widthHalf := windowWidth / 2
	heightHalf := windowHeight / 2

	lineWidthHalf := (x2.X - x1.X) / 2
	lineHeightHalf := (x2.Y - x1.Y) / 2

	lowerLeft.X = float32(widthHalf) - lineWidthHalf
	lowerLeft.Y = float32(heightHalf) - lineHeightHalf
	return
}

func main() {
	runtime.LockOSThread()

	glfw.SetErrorCallback(errorCallback)
	if !glfw.Init() {
		panic("glfw error")
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	if useStrictCoreProfile {
		glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True)
		glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile)
	}
	glfw.WindowHint(glfw.OpenglDebugContext, glfw.True)

	window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}
	if err := gl32.Init(); err != nil {
		fmt.Println("could not initialize GL 3.2")
	}
	version := gl.GoStr(gl.GetString(gl.VERSION))
	fmt.Println("Opengl version", version)

	fd, err := os.Open("font/luximr.ttf")
	if err != nil {
		panic(err)
	}
	defer fd.Close()

	scale := int32(32)
	line, err := gltext.LoadTruetype(fd, scale, 32, 127)
	if err != nil {
		panic(err)
	}
	width, height := window.GetSize()

	line.ResizeWindow(float32(width), float32(height))

	str := ">-- I am Batman --<"
	x1, x2 := line.SetString(str)

	// find the center of the string based on the bounding box
	fmt.Printf("bounding box %v %v\n", x1, x2)
	lowerLeft := findCenter(width, height, x1, x2)
	line.SetPosition(lowerLeft.X, lowerLeft.Y)
	line.SetTextLowerBound(0.5)
	// alpha == 1 means no opacity
	line.SetColor(1, 1, 1, 1)

	//gl.ClearColor(1, 1, 1, 0.0)
	flow := float32(1)
	color := float32(0.0)
	gl.ClearColor(0, 1, 1, 0.0)
	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT)

		color += flow * 0.01
		if color > 1.0 {
			color = 1
			flow = -1
		}
		if color < 0.0 {
			color = 0
			flow = +1
		}
		line.SetColor(color, color, color, 1)
		line.Draw()

		window.SwapBuffers()
		glfw.PollEvents()
	}
	line.Release()
}
<commit_msg>Slighly more appealing colors for the example.<commit_after>package main

import (
	"fmt"
	gltext "github.com/4ydx/gltext"
	glfw "github.com/go-gl/glfw3"
	gl32 "github.com/go-gl/glow/gl-core/3.2/gl"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"os"
	"runtime"
)

var useStrictCoreProfile = (runtime.GOOS == "darwin")

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func findCenter(windowWidth int, windowHeight int, x1, x2 gltext.Point) (lowerLeft gltext.Point) {
	widthHalf := windowWidth / 2
	heightHalf := windowHeight / 2

	lineWidthHalf := (x2.X - x1.X) / 2
	lineHeightHalf := (x2.Y - x1.Y) / 2

	lowerLeft.X = float32(widthHalf) - lineWidthHalf
	lowerLeft.Y = float32(heightHalf) - lineHeightHalf
	return
}

func main() {
	runtime.LockOSThread()

	glfw.SetErrorCallback(errorCallback)
	if !glfw.Init() {
		panic("glfw error")
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	if useStrictCoreProfile {
		glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True)
		glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile)
	}
	glfw.WindowHint(glfw.OpenglDebugContext, glfw.True)

	window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}
	if err := gl32.Init(); err != nil {
		fmt.Println("could not initialize GL 3.2")
	}
	version := gl.GoStr(gl.GetString(gl.VERSION))
	fmt.Println("Opengl version", version)

	fd, err := os.Open("font/luximr.ttf")
	if err != nil {
		panic(err)
	}
	defer fd.Close()

	scale := int32(32)
	line, err := gltext.LoadTruetype(fd, scale, 32, 127)
	if err != nil {
		panic(err)
	}
	width, height := window.GetSize()

	line.ResizeWindow(float32(width), float32(height))

	str := ">-- I am Batman --<"
	x1, x2 := line.SetString(str)

	// find the center of the string based on the bounding box
	fmt.Printf("bounding box %v %v\n", x1, x2)
	lowerLeft := findCenter(width, height, x1, x2)
	line.SetPosition(lowerLeft.X, lowerLeft.Y)
	line.SetTextLowerBound(0.5)
	// alpha == 1 means no opacity
	line.SetColor(0, 0, 0, 1)

	flow := float32(1)
	color := float32(0.0)
	gl.ClearColor(0.4, 0.4, 0.4, 0.0)
	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT)

		color += flow * 0.01
		if color > 1.0 {
			color = 1
			flow = -1
		}
		if color < 0.0 {
			color = 0
			flow = +1
		}
		line.SetColor(color, color, color, 1)
		line.Draw()

		window.SwapBuffers()
		glfw.PollEvents()
	}
	line.Release()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup
var wga sync.WaitGroup

type alarm struct {
	bool
	*sync.Mutex
}

func (a *alarm) Set(value bool) {
	a.Lock()
	a.bool = value
	a.Unlock()
}

type person struct {
	Name    string
	AllDone bool
	*sync.Mutex
}

func (p *person) setAllDone(value bool) {
	defer p.Unlock()
	p.Lock()
	p.AllDone = value
}

type people []person

type household struct {
	people
	*sync.Mutex
}

var alrm = alarm{false, &sync.Mutex{}}
var hsld = household{[]person{}, &sync.Mutex{}}

func main() {
	fmt.Println("Let's go for walk!")
	Bob := person{"Bob", false, &sync.Mutex{}}
	Alice := person{"Alice", false, &sync.Mutex{}}
	hsld.people = []person{Bob, Alice}

	for k := range hsld.people {
		wg.Add(1)
		go hsld.people[k].dotask("getting ready", 1, 3, false)
	}
	wg.Wait()

	wga.Add(1)
	go setAlarm(5)

	for k := range hsld.people {
		wg.Add(1)
		go hsld.people[k].dotask("putting on shoes", 1, 3, true)
	}
	wg.Wait()
	alrm.Lock()
	if alrm.bool {
		fmt.Println("Crap!  The alarm is already set.")
	} else {
		fmt.Println("Exiting and locking door.")
	}
	alrm.Unlock()
	wga.Wait()
}

func setAlarm(delay int) {
	fmt.Println("Arming alarm.")
	fmt.Println("Alarm is counting down.")
	time.Sleep(time.Duration(delay) * time.Second)
	alrm.Set(true)
	fmt.Println("Alarm armed.")
	for _, v := range hsld.people {
		v.Lock()
		if v.AllDone == false {
			fmt.Printf("Alarm set before %v was ready.\n", v.Name)
		}
		v.Unlock()
	}
	defer func() {
		wga.Done()
	}()
}

func (p *person) dotask(task string, min int, max int, setdone bool) {
	defer wg.Done()
	s := random(min, max)
	fmt.Println(p.Name, "started", task)
	time.Sleep(time.Duration(s) * time.Second)
	fmt.Println(p.Name, "spent", s, "seconds", task)
	if setdone {
		p.setAllDone(true)
	}
}

func random(min, max int) int {
	rand.Seed(time.Now().Unix())
	time.Sleep(10 * time.Microsecond)
	return rand.Intn(max-min) + min
}
<commit_msg>got rid of mutex and struct<commit_after>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup
var wga sync.WaitGroup

type alarm struct {
	bool
	*sync.Mutex
}

func (a *alarm) Set(value bool) {
	a.Lock()
	a.bool = value
	a.Unlock()
}

type person struct {
	Name    string
	AllDone bool
	*sync.Mutex
}

func (p *person) setAllDone(value bool) {
	defer p.Unlock()
	p.Lock()
	p.AllDone = value
}

type people []person

var alrm = alarm{false, &sync.Mutex{}}
var hsld = []person{}

func main() {
	fmt.Println("Let's go for walk!")
	Bob := person{"Bob", false, &sync.Mutex{}}
	Alice := person{"Alice", false, &sync.Mutex{}}
	hsld = []person{Bob, Alice}

	for k := range hsld {
		wg.Add(1)
		go hsld[k].dotask("getting ready", 1, 3, false)
	}
	wg.Wait()

	wga.Add(1)
	go setAlarm(5)

	for k := range hsld {
		wg.Add(1)
		go hsld[k].dotask("putting on shoes", 1, 3, true)
	}
	wg.Wait()
	alrm.Lock()
	if alrm.bool {
		fmt.Println("Crap!  The alarm is already set.")
	} else {
		fmt.Println("Exiting and locking door.")
	}
	alrm.Unlock()
	wga.Wait()
}

func setAlarm(delay int) {
	fmt.Println("Arming alarm.")
	fmt.Println("Alarm is counting down.")
	time.Sleep(time.Duration(delay) * time.Second)
	alrm.Set(true)
	fmt.Println("Alarm armed.")
	for _, v := range hsld {
		v.Lock()
		if v.AllDone == false {
			fmt.Printf("Alarm set before %v was ready.\n", v.Name)
		}
		v.Unlock()
	}
	defer func() {
		wga.Done()
	}()
}

func (p *person) dotask(task string, min int, max int, setdone bool) {
	defer wg.Done()
	s := random(min, max)
	fmt.Println(p.Name, "started", task)
	time.Sleep(time.Duration(s) * time.Second)
	fmt.Println(p.Name, "spent", s, "seconds", task)
	if setdone {
		p.setAllDone(true)
	}
}

func random(min, max int) int {
	rand.Seed(time.Now().Unix())
	time.Sleep(10 * time.Microsecond)
	return rand.Intn(max-min) + min
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"strings"
	"time"
)

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT DEMO")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = false
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func getNamesAndImagesOfRunning(cl *dockerClient.DockerClient) ([]string, []string) {
	containers, _ := cl.ListContainers(goDocker.ListContainersOptions{})
	names := make([]string, len(containers))
	images := make([]string, len(containers))
	for i, cont := range containers {
		names[i] = strings.Join(cont.Names, "")
		images[i] = cont.Image
	}
	return names, images
}

func main() {

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	p := createExitBar()

	containerListOfNames := createContainerList()
	containerListOfImages := createContainerList()

	lc := createDockerLineChart()

	lc.Data = make([]float64, 0, 0)

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(6, 0, p),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListOfNames),
			ui.NewCol(3, 0, containerListOfImages),
		),
	)

	// calculate layout
	ui.Body.Align()

	draw := func(t int) {

		names, images := getNamesAndImagesOfRunning(docker)
		containerListOfNames.Items = names
		containerListOfImages.Items = images
		containerListOfNames.Height = len(names) + 1
		containerListOfImages.Height = len(images) + 1

		lc.Data = append(lc.Data, float64(len(names)))
		ui.Render(p, containerListOfNames, containerListOfImages, lc)
	}

	evt := ui.EventCh()

	i := 0
	for {
		select {
		case e := <-evt:
			if e.Type == ui.EventKey && e.Ch == 'q' {
				return
			}
			if e.Type == ui.EventResize {
				ui.Body.Width = ui.TermWidth()
				ui.Body.Align()
				go func() { evt <- ui.Event{} }()
			}
		default:
			draw(i)
			i++
			time.Sleep(time.Second / 2)
		}
	}
}
<commit_msg>Added more with stats<commit_after>package main

import (
	"fmt"
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"strings"
	"time"
)

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createErrorBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorRed
	p.HasBorder = false
	return
}

func createStatusBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorGreen
	p.HasBorder = true
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = true
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func getNamesAndImagesOfRunning(cl *dockerClient.DockerClient, containerChan chan<- []goDocker.APIContainers) ([]string, []string) {
	containers, _ := cl.ListContainers(goDocker.ListContainersOptions{})
	names := make([]string, len(containers))
	images := make([]string, len(containers))
	for i, cont := range containers {
		names[i] = strings.TrimLeft(strings.Join(cont.Names, ""), "/")
		images[i] = strings.Replace(cont.Image, "dockerregistry.pagero.local", "d.p.l", 1)
	}
	containerChan <- containers
	return names, images
}

func updateStatisticsRoutines(cl *dockerClient.DockerClient, event *goDocker.APIEvents, deadContainerChan chan<- string, startedContainerChan chan<- string, statsChan chan *goDocker.Stats, errChan chan<- string) {
	switch event.Status {
	case "die":
		go stopGettingStats(cl, event.ID, errChan)
	case "start":
		go startGettingStats(cl, event.ID, statsChan, errChan)
	}
}

func startGettingStats(cl *dockerClient.DockerClient, id string, statsChan chan *goDocker.Stats, errChan chan<- string) {
	if err := cl.Stats(goDocker.StatsOptions{id, statsChan, true, nil, 0}); err != nil {
		errChan <- err.Error()
	}
}

func stopGettingStats(cl *dockerClient.DockerClient, id string, errChan chan<- string) {

}

func main() {

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	exitBar := createExitBar()
	errorBar := createErrorBar()
	statusBar := createStatusBar()

	containerListOfNames := createContainerList()
	containerListOfNames.Border.Label = "Name"
	containerListOfImages := createContainerList()
	containerListOfImages.Border.Label = "Image"

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(12, 0, exitBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, errorBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, statusBar),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListOfNames),
			ui.NewCol(9, 0, containerListOfImages),
		),
	)

	// calculate layout
	ui.Body.Align()

	errChan := make(chan string, 10)
	eventsChan := make(chan *goDocker.APIEvents, 10)
	containersChan := make(chan []goDocker.APIContainers, 10)
	deadContainerChan := make(chan string, 10)
	startedContainerChan := make(chan string, 10)
	statsChan := make(chan *goDocker.Stats)

	defer func() {
		if err := docker.RemoveEventListener(eventsChan); err != nil {
			panic(err)
		}
	}()

	err = docker.AddEventListener(eventsChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	drawContainerList := func(t int) {

		names, images := getNamesAndImagesOfRunning(docker, containersChan)
		containerListOfNames.Items = names
		containerListOfImages.Items = images
		containerListOfNames.Height = len(names) + 1
		containerListOfImages.Height = len(images) + 1

		//lc.Data = append(lc.Data, float64(len(names)))
		ui.Render(ui.Body)

	}
	drawContainerList(0)

	containers, _ := docker.ListContainers(goDocker.ListContainersOptions{})
	for _, cont := range containers {
		startedContainerChan <- cont.ID
	}

	evt := ui.EventCh()

	i := 0
	for {
		select {
		case stats := <-statsChan:
			statusBar.Text = "Got stats"
			errChan <- fmt.Sprintf("%f", stats.CPUStats.SystemCPUUsage)
		case e := <-evt:
			statusBar.Text = "Got ui event"
			if e.Type == ui.EventKey && e.Ch == 'q' {
				return
			}
			if e.Type == ui.EventResize {
				ui.Body.Width = ui.TermWidth()
				ui.Body.Align()
			}
		case err := <-errChan:
			statusBar.Text = "Got error"
			errorBar.Text = err
		case e := <-eventsChan:
			statusBar.Text = "Got docker event"
			updateStatisticsRoutines(docker, e, deadContainerChan, startedContainerChan, statsChan, errChan)
			drawContainerList(i)
			i++
			time.Sleep(time.Second / 2)
		default:
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
)

const addr = "localhost:12345"

func main() {
	err := http.ListenAndServe(addr, &RedirectHandler{})
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Fixing package import<commit_after>package main

import (
	"log"
	"net/http"

	"github.com/guilhermef/go-shortener/handler"
)

const addr = "localhost:12345"

func main() {
	err := http.ListenAndServe(addr, &handler.RedirectHandler{})
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, "usage: px86 filename")
		return
	}

	fileName := os.Args[1]

	f, err := os.Open(fileName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%sファイルが開けません: %v", fileName, err)
		return
	}
	defer f.Close()

	emu := newEmulator()
	if err := emu.load(f); err != nil {
		fmt.Fprintf(os.Stderr, "%sファイルが読み込めません: %v", fileName, err)
	}

	emu.eval()
}
<commit_msg>add return<commit_after>package main

import (
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, "usage: px86 filename")
		return
	}

	fileName := os.Args[1]

	f, err := os.Open(fileName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%sファイルが開けません: %v", fileName, err)
		return
	}
	defer f.Close()

	emu := newEmulator()
	if err := emu.load(f); err != nil {
		fmt.Fprintf(os.Stderr, "%sファイルが読み込めません: %v", fileName, err)
		return
	}

	emu.eval()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/realglobe-Inc/edo/driver"
	"github.com/realglobe-Inc/edo/util"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/rglog"
	"net/http"
	"os"
)

var exitCode = 0

func exit() {
	if exitCode != 0 {
		os.Exit(exitCode)
	}
}

func main() {
	defer exit()
	defer rglog.Flush()

	hndl := util.InitLog("github.com/realglobe-Inc")

	param, err := parseParameters(os.Args...)
	if err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	hndl.SetLevel(param.consLv)
	if err := util.SetupLog("github.com/realglobe-Inc", param.logType, param.logLv, param.acpLogPath, param.fluAddr, param.acpFluTag); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	if err := mainCore(param); err != nil {
		err = erro.Wrap(err)
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	log.Info("Shut down.")
}

// system を準備する。
func mainCore(param *parameters) error {

	var priKeyCont driver.KeyValueStore
	switch param.priKeyContType {
	case "file":
		priKeyCont = driver.NewFileKeyValueStore(param.priKeyContPath, func(before string) string {
			return before + ".pem"
		}, nil, func(data []byte) (interface{}, error) {
			return util.ParseRsaPrivateKey(string(data))
		}, param.caExpiDur)
		log.Info("Use file code container " + param.priKeyContPath + ".")
	default:
		return erro.New("invalid code container type " + param.priKeyContType + ".")
	}

	sys := newSystem(
		priKeyCont,
		param.taId,
		param.hashName,
	)
	sys.sessMargin = param.sessMargin
	return serve(sys, param.acpSocType, param.acpSocPath, param.acpSocPort, param.acpProtType)
}

// 振り分ける。
const (
	proxyApiPath = "/"
)

func serve(sys *system, socType, socPath string, socPort int, protType string) error {
	routes := map[string]util.HandlerFunc{
		proxyApiPath: wrapper(func(w http.ResponseWriter, r *http.Request) error {
			return proxyApi(sys, w, r)
		}),
	}
	return util.Serve(socType, socPath, socPort, protType, routes)
}

func wrapper(f func(http.ResponseWriter, *http.Request) error) func(http.ResponseWriter, *http.Request) error {
	return func(w http.ResponseWriter, r *http.Request) error {
		if err := f(w, r); err != nil {
			err = erro.Wrap(err)
			var msg string
			for baseErr := err; msg == ""; {
				switch e := erro.Unwrap(baseErr).(type) {
				case *util.HttpStatusError:
					if e.Cause() == nil {
						msg = e.Message()
					} else {
						baseErr = e.Cause()
					}
				case *erro.Tracer:
					baseErr = e.Cause()
				default:
					msg = e.Error()
				}
			}
			w.Header().Set(headerAccProxErr, msg)
			return err
		}
		return nil
	}
}
<commit_msg>ログメッセージの修正<commit_after>package main

import (
	"github.com/realglobe-Inc/edo/driver"
	"github.com/realglobe-Inc/edo/util"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/rglog"
	"net/http"
	"os"
)

var exitCode = 0

func exit() {
	if exitCode != 0 {
		os.Exit(exitCode)
	}
}

func main() {
	defer exit()
	defer rglog.Flush()

	hndl := util.InitLog("github.com/realglobe-Inc")

	param, err := parseParameters(os.Args...)
	if err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	hndl.SetLevel(param.consLv)
	if err := util.SetupLog("github.com/realglobe-Inc", param.logType, param.logLv, param.acpLogPath, param.fluAddr, param.acpFluTag); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	if err := mainCore(param); err != nil {
		err = erro.Wrap(err)
		log.Err(erro.Unwrap(err))
		log.Debug(err)
		exitCode = 1
		return
	}

	log.Info("Shut down.")
}

// system を準備する。
func mainCore(param *parameters) error {

	var priKeyCont driver.KeyValueStore
	switch param.priKeyContType {
	case "file":
		priKeyCont = driver.NewFileKeyValueStore(param.priKeyContPath, func(before string) string {
			return before + ".pem"
		}, nil, func(data []byte) (interface{}, error) {
			return util.ParseRsaPrivateKey(string(data))
		}, param.caExpiDur)
		log.Info("Use file private key container " + param.priKeyContPath + ".")
	default:
		return erro.New("invalid code container type " + param.priKeyContType + ".")
	}

	sys := newSystem(
		priKeyCont,
		param.taId,
		param.hashName,
	)
	sys.sessMargin = param.sessMargin
	return serve(sys, param.acpSocType, param.acpSocPath, param.acpSocPort, param.acpProtType)
}

// 振り分ける。
const (
	proxyApiPath = "/"
)

func serve(sys *system, socType, socPath string, socPort int, protType string) error {
	routes := map[string]util.HandlerFunc{
		proxyApiPath: wrapper(func(w http.ResponseWriter, r *http.Request) error {
			return proxyApi(sys, w, r)
		}),
	}
	return util.Serve(socType, socPath, socPort, protType, routes)
}

func wrapper(f func(http.ResponseWriter, *http.Request) error) func(http.ResponseWriter, *http.Request) error {
	return func(w http.ResponseWriter, r *http.Request) error {
		if err := f(w, r); err != nil {
			err = erro.Wrap(err)
			var msg string
			for baseErr := err; msg == ""; {
				switch e := erro.Unwrap(baseErr).(type) {
				case *util.HttpStatusError:
					if e.Cause() == nil {
						msg = e.Message()
					} else {
						baseErr = e.Cause()
					}
				case *erro.Tracer:
					baseErr = e.Cause()
				default:
					msg = e.Error()
				}
			}
			w.Header().Set(headerAccProxErr, msg)
			return err
		}
		return nil
	}
}
<|endoftext|>


<commit_before>//Most parts of this file are taken from Lakrizz' example on GitHub
// https://github.com/lakrizz/go-pidioder/blob/master/main.go

package dioder

import (
	"bufio"
	"errors"
	"os"
	"strconv"
)

const (
	redPin   = "18"
	bluePin  = "17"
	greenPin = "4"
)

var (
	currentRed   int
	currentGreen int
	currentBlue  int
)

func floatToString(floatValue float64) string {
	return strconv.FormatFloat(floatValue, 'f', 6, 64)
}

func setColor(channel string, value float64) error {
	piBlasterCommand := channel + "=" + floatToString(value) + "\n"

	file, error := os.OpenFile("/dev/pi-blaster", os.O_RDWR, os.ModeNamedPipe)

	if error != nil {
		panic(error)
	}

	defer file.Close()

	stream := bufio.NewWriter(file)

	_, error = stream.WriteString(piBlasterCommand)

	if error != nil {
		panic(error)
	}

	stream.Flush()

	return nil
}

func setChannelInteger(value int, channel string) error {
	if value > 255 {
		return errors.New("Value can not be over 255")
	}

	if value < 0 {
		return errors.New("Value can not be under 0")
	}

	floatval := float64(value) / 255.0

	setColor(channel, float64(floatval))

	return nil
}

// SetAll sets the given values for the channels
func SetAll(r, g, b int) {
	SetRed(r)
	SetGreen(g)
	SetBlue(b)
}

// SetRed sets the given value on the Red channel
func SetRed(value int) error {
	// Do nothing if the new value is the same as the old
	if value == currentRed {
		return nil
	}

	currentRed = value
	return setChannelInteger(value, redPin)
}

// SetGreen sets the given value on the Green channel
func SetGreen(value int) error {
	// Do nothing if the new value is the same as the old
	if value == currentGreen {
		return nil
	}

	currentGreen = value
	return setChannelInteger(value, greenPin)
}

// SetBlue sets the given value on the Blue channel
func SetBlue(value int) error {
	// Do nothing if the new value is the same as the old
	if value == currentBlue {
		return nil
	}

	currentBlue = value
	return setChannelInteger(value, bluePin)
}
<commit_msg>We can only pass values up to 255 so a uint8 is big enough<commit_after>//Most parts of this file are taken from Lakrizz' example on GitHub
// https://github.com/lakrizz/go-pidioder/blob/master/main.go

package dioder

import (
	"bufio"
	"errors"
	"os"
	"strconv"
)

const (
	redPin   = "18"
	bluePin  = "17"
	greenPin = "4"
)

var (
	currentRed   uint8
	currentGreen uint8
	currentBlue  uint8
)

func floatToString(floatValue float64) string {
	return strconv.FormatFloat(floatValue, 'f', 6, 64)
}

func setColor(channel string, value float64) error {
	piBlasterCommand := channel + "=" + floatToString(value) + "\n"

	file, error := os.OpenFile("/dev/pi-blaster", os.O_RDWR, os.ModeNamedPipe)

	if error != nil {
		panic(error)
	}

	defer file.Close()

	stream := bufio.NewWriter(file)

	_, error = stream.WriteString(piBlasterCommand)

	if error != nil {
		panic(error)
	}

	stream.Flush()

	return nil
}

func setChannelInteger(value uint8, channel string) error {
	if value > 255 {
		return errors.New("Value can not be over 255")
	}

	if value < 0 {
		return errors.New("Value can not be under 0")
	}

	floatval := float64(value) / 255.0

	setColor(channel, float64(floatval))

	return nil
}

// SetAll sets the given values for the channels
func SetAll(r, g, b uint8) {
	SetRed(r)
	SetGreen(g)
	SetBlue(b)
}

// SetRed sets the given value on the Red channel
func SetRed(value uint8) error {
	// Do nothing if the new value is the same as the old
	if value == currentRed {
		return nil
	}

	currentRed = value
	return setChannelInteger(value, redPin)
}

// SetGreen sets the given value on the Green channel
func SetGreen(value uint8) error {
	// Do nothing if the new value is the same as the old
	if value == currentGreen {
		return nil
	}

	currentGreen = value
	return setChannelInteger(value, greenPin)
}

// SetBlue sets the given value on the Blue channel
func SetBlue(value uint8) error {
	// Do nothing if the new value is the same as the old
	if value == currentBlue {
		return nil
	}

	currentBlue = value
	return setChannelInteger(value, bluePin)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/binding"

	"github.com/odeke-em/extractor"
	"github.com/odeke-em/meddler"
	"github.com/odeke-em/rsc/qr"
)

const (
	ENV_DRIVE_SERVER_PUB_KEY  = "DRIVE_SERVER_PUB_KEY"
	ENV_DRIVE_SERVER_PRIV_KEY = "DRIVE_SERVER_PRIV_KEY"
	ENV_DRIVE_SERVER_PORT     = "DRIVE_SERVER_PORT"
	ENV_DRIVE_SERVER_HOST     = "DRIVE_SERVER_HOST"
)

var envKeyAlias = &extractor.EnvKey{
	PubKeyAlias:  ENV_DRIVE_SERVER_PUB_KEY,
	PrivKeyAlias: ENV_DRIVE_SERVER_PRIV_KEY,
}

type addressInfo struct {
	port, host string
}

func envGet(varname string, placeholders ...string) string {
	v := os.Getenv(varname)
	if v == "" {
		for _, placeholder := range placeholders {
			if placeholder != "" {
				v = placeholder
				break
			}
		}
	}

	return v
}

func addressInfoFromEnv() *addressInfo {
	return &addressInfo{
		port: envGet(ENV_DRIVE_SERVER_PORT, "8010"),
		host: envGet(ENV_DRIVE_SERVER_HOST, "localhost"),
	}
}

var envKeySet = extractor.KeySetFromEnv(envKeyAlias)
var envAddrInfo = addressInfoFromEnv()

func (ai *addressInfo) ConnectionString() string {
	// TODO: ensure fields meet rubric
	return fmt.Sprintf("%s:%s", ai.host, ai.port)
}

func main() {
	if envKeySet.PublicKey == "" {
		errorPrint("publicKey not set. Please set %s in your env.\n", envKeyAlias.PubKeyAlias)
		return
	}

	if envKeySet.PrivateKey == "" {
		errorPrint("privateKey not set. Please set %s in your env.\n", envKeyAlias.PrivKeyAlias)
		return
	}

	m := martini.Classic()

	m.Get("/qr", binding.Bind(meddler.Payload{}), presentQRCode)
	m.Post("/qr", binding.Bind(meddler.Payload{}), presentQRCode)

	m.RunOnAddr(envAddrInfo.ConnectionString())
}

func presentQRCode(pl meddler.Payload, res http.ResponseWriter, req *http.Request) {
	if pl.PublicKey != envKeySet.PublicKey {
		http.Error(res, "invalid publickey", 405)
		return
	}

	rawTextForSigning := pl.RawTextForSigning()
	if !envKeySet.Match([]byte(rawTextForSigning), []byte(pl.Signature)) {
		http.Error(res, "invalid signature", 403)
		return
	}

	curTimeUnix := time.Now().Unix()
	if pl.ExpiryTime < curTimeUnix {
		http.Error(res, fmt.Sprintf("request expired at %q, current time %q", pl.ExpiryTime, curTimeUnix), 403)
		return
	}

	uri := pl.URI
	code, err := qr.Encode(uri, qr.Q)
	if err != nil {
		fmt.Fprintf(res, "%s %v\n", uri, err)
		return
	}

	pngImage := code.PNG()
	fmt.Fprintf(res, "%s", pngImage)
}

func errorPrint(fmt_ string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "\033[31m")
	fmt.Fprintf(os.Stderr, fmt_, args...)
	fmt.Fprintf(os.Stderr, "\033[00m")
}
<commit_msg>bind on default martini port<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/binding"

	"github.com/odeke-em/extractor"
	"github.com/odeke-em/meddler"
	"github.com/odeke-em/rsc/qr"
)

const (
	ENV_DRIVE_SERVER_PUB_KEY  = "DRIVE_SERVER_PUB_KEY"
	ENV_DRIVE_SERVER_PRIV_KEY = "DRIVE_SERVER_PRIV_KEY"
	ENV_DRIVE_SERVER_PORT     = "DRIVE_SERVER_PORT"
	ENV_DRIVE_SERVER_HOST     = "DRIVE_SERVER_HOST"
)

var envKeyAlias = &extractor.EnvKey{
	PubKeyAlias:  ENV_DRIVE_SERVER_PUB_KEY,
	PrivKeyAlias: ENV_DRIVE_SERVER_PRIV_KEY,
}

type addressInfo struct {
	port, host string
}

func envGet(varname string, placeholders ...string) string {
	v := os.Getenv(varname)
	if v == "" {
		for _, placeholder := range placeholders {
			if placeholder != "" {
				v = placeholder
				break
			}
		}
	}

	return v
}

func addressInfoFromEnv() *addressInfo {
	return &addressInfo{
		port: envGet(ENV_DRIVE_SERVER_PORT, "3000"),
		host: envGet(ENV_DRIVE_SERVER_HOST, "localhost"),
	}
}

var envKeySet = extractor.KeySetFromEnv(envKeyAlias)
var envAddrInfo = addressInfoFromEnv()

func (ai *addressInfo) ConnectionString() string {
	// TODO: ensure fields meet rubric
	return fmt.Sprintf("%s:%s", ai.host, ai.port)
}

func main() {
	if envKeySet.PublicKey == "" {
		errorPrint("publicKey not set. Please set %s in your env.\n", envKeyAlias.PubKeyAlias)
		return
	}

	if envKeySet.PrivateKey == "" {
		errorPrint("privateKey not set. Please set %s in your env.\n", envKeyAlias.PrivKeyAlias)
		return
	}

	m := martini.Classic()

	m.Get("/qr", binding.Bind(meddler.Payload{}), presentQRCode)
	m.Post("/qr", binding.Bind(meddler.Payload{}), presentQRCode)

	m.RunOnAddr(envAddrInfo.ConnectionString())
}

func presentQRCode(pl meddler.Payload, res http.ResponseWriter, req *http.Request) {
	if pl.PublicKey != envKeySet.PublicKey {
		http.Error(res, "invalid publickey", 405)
		return
	}

	rawTextForSigning := pl.RawTextForSigning()
	if !envKeySet.Match([]byte(rawTextForSigning), []byte(pl.Signature)) {
		http.Error(res, "invalid signature", 403)
		return
	}

	curTimeUnix := time.Now().Unix()
	if pl.ExpiryTime < curTimeUnix {
		http.Error(res, fmt.Sprintf("request expired at %q, current time %q", pl.ExpiryTime, curTimeUnix), 403)
		return
	}

	uri := pl.URI
	code, err := qr.Encode(uri, qr.Q)
	if err != nil {
		fmt.Fprintf(res, "%s %v\n", uri, err)
		return
	}

	pngImage := code.PNG()
	fmt.Fprintf(res, "%s", pngImage)
}

func errorPrint(fmt_ string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "\033[31m")
	fmt.Fprintf(os.Stderr, fmt_, args...)
	fmt.Fprintf(os.Stderr, "\033[00m")
}
<|endoftext|>