<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/ninjasphere/gatt"
	"github.com/ninjasphere/go-ninja/api"
	nconfig "github.com/ninjasphere/go-ninja/config"
	nlog "github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/support"
	"github.com/ninjasphere/sphere-client/client"
	"github.com/ninjasphere/sphere-go-led-controller/model"
	"github.com/ninjasphere/sphere-go-led-controller/util"
)

const WirelessNetworkInterface = "wlan0"

// consider the wifi to be invalid after this timeout
const WirelessStaleTimeout = time.Second * 30 // FIXME: INCREASE THIS. a few minutes at least when not in testing.

var firewallHook = flag.Bool("firewall-hook", false, "Sets up the firewall based on configuration options, and nothing else.")
var factoryReset = false
var imagesDir = ""

// factoryReset - we can't use anything that requires MQTT in this mode

var logger = nlog.GetLogger("sphere-setup")

func main() {
	// ap0 adhoc/hostap management
	flag.BoolVar(&factoryReset, "factory-reset", false, "Run in factory reset mode.")
	flag.StringVar(&imagesDir, "images", "/opt/ninjablocks/drivers/sphere-go-led-controller/images", "The location of the images directory.")

	go func() {
		support.WaitUntilSignal()
	}()

	config := LoadConfig("/etc/opt/ninja/setup-assistant.conf")
	apManager := NewAccessPointManager(config)

	flag.Parse()

	if *firewallHook {
		logger.Debugf("Setting ip firewall rules...")
		apManager.SetupFirewall()
		return
	}

	util.SetImageDir(imagesDir)
	var pairing_ui ConsolePairingUI
	var controlChecker *ControlChecker

	restartHeartbeat := false

	if err := EnsureBLEIsUp(time.Second * 30); err != nil {
		logger.Errorf("BLE failed to start: %s", err)
	}

	startResetMonitor(func(m *model.ResetMode) {
		if pairing_ui == nil || controlChecker == nil {
			return
		}
		if m.Mode == "none" {
			if restartHeartbeat {
				// only restart the heartbeat if we stopped it previously
				controlChecker.StartHeartbeat()
			}
		} else {
			restartHeartbeat = controlChecker.StopHeartbeat()
			pairing_ui.DisplayResetMode(m)
		}
	})

	apManager.WriteAPConfig()
	if config.Wireless_Host.Always_Active {
		apManager.StartHostAP()
	} else {
		apManager.StopHostAP()
	}

	// wlan0 client management
	wifi_manager, err := NewWifiManager(WirelessNetworkInterface)
	if err != nil {
		log.Fatal("Could not setup manager for wlan0, does the interface exist?: %v", err)
	}
	defer wifi_manager.Cleanup()

	// When in reset mode, this will talk to the led matrix directly,
	// otherwise, it will use sphere-go-led-controller via mqtt.
	pairing_ui, err = NewPairingUI()
	if err != nil {
		log.Fatal("Could not setup ninja connection")
	}

	// This name is sent in the BLE advertising packet,
	// and is used by the phone to see that this is a
	// sphere, and if it is in factory reset mode.
	serviceName := "ninjasphere"
	if factoryReset {
		serviceName = "resetsphere"
	}

	srv := &gatt.Server{
		Name: serviceName,
		Connect: func(c gatt.Conn) {
			logger.Infof("BLE Connect")
			//pairing_ui.DisplayIcon("ble-connected.gif")
		},
		Disconnect: func(c gatt.Conn) {
			logger.Infof("BLE Disconnect")
			//pairing_ui.DisplayIcon("ble-disconnected.gif")
		},
		StateChange: func(state string) {
			logger.Infof("BLE State Change: %s", state)
		},
	}

	var conn *ninja.Connection

	if !factoryReset {

		conn, err = ninja.Connect("sphere-setup-assistant-updates")

		if err != nil {
			logger.FatalErrorf(err, "Failed to connect to mqtt")
		}
	}

	// start by registering the RPC functions that will be accessible
	// once the client has authenticated
	// We pass in the ble server so that we can close the connection once the updates are installed
	// (THIS SHOULD HAPPEN OVER WIFI INSTEAD!)
	rpc_router := GetSetupRPCRouter(conn, wifi_manager, srv, pairing_ui)

	StartHTTPServer(conn, wifi_manager, srv, pairing_ui)

	auth_handler := new(OneTimeAuthHandler)
	auth_handler.Init("spheramid")

	controlChecker = NewControlChecker(pairing_ui)

	RegisterSecuredRPCService(srv, rpc_router, auth_handler, pairing_ui)

	// Start the server
	//log.Println("Starting setup assistant...");
	//log.Fatal(srv.AdvertiseAndServe())

	states := wifi_manager.WatchState()

	//wifi_manager.WifiConfigured()

	var wireless_stale *time.Timer

	is_serving_pairer := false

	// start by forcing the state to Disconnected.
	// reloading the configuration in wpa_supplicant will also force this,
	// but we need to do it here in case we are already disconnected
	states <- WifiStateDisconnected
	wifi_manager.Controller.ReloadConfiguration()

	badWifiMessage := false

	handleBadWireless := func() {
		logger.Warningf("Wireless is stale! Invalid SSID, router down, or not in range.")

		if !is_serving_pairer {
			is_serving_pairer = true
			colorHintSent = false

			// If we aren't paired, update the avahi service
			if !nconfig.IsPaired() {
				client.UpdateSphereAvahiService(false, false)
			}

			// Show the phone pairing icon only if we don't always have AP
			if !config.Wireless_Host.Always_Active {
				pairing_ui.DisableControl()
				pairing_ui.DisplayIcon("phone-fade.gif")
				wifi_configured, _ := wifi_manager.WifiConfigured()
				if wifi_configured {
					badWifiMessage = true
				}
			}

			logger.Infof("Launching BLE pairing assistant...")
			go func() {
				err := srv.AdvertiseAndServe()
				if err != nil {
					logger.Infof("Failed to advertise and serve OR finished serving: %v", err)
				}
				is_serving_pairer = false
			}()

			// and if the hostap isn't normally active, make it active
			if !config.Wireless_Host.Always_Active {
				logger.Infof("Launching AdHoc pairing assistant...")
				apManager.StartHostAP()
			}
		}
	}

	wifi_configured, _ := wifi_manager.WifiConfigured()
	if !wifi_configured {
		// when wireless isn't configured at all, automatically start doing this, don't wait for staleness
		handleBadWireless()
	}

	if config.Wireless_Host.Enables_Control {
		// the wireless AP causes control to be enabled, so we just start the heartbeat immediately
		controlChecker.StartHeartbeat()
	}

	for {
		state := <-states
		logger.Infof("State: %v", state)

		switch state {
		case WifiStateConnected:
			if wireless_stale != nil {
				wireless_stale.Stop()
			}
			wireless_stale = nil
			logger.Infof("Connected and attempting to get IP.")

			/*if !config.Wireless_Host.Enables_Control {
				// if the wireless AP mode hasn't already enabled normal control, then enable it now that wifi works
				controlChecker.StartHeartbeat()
			}*/

			if badWifiMessage {
				badWifiMessage = false
				pairing_ui.EnableControl()
			}

			if is_serving_pairer {
				is_serving_pairer = false

				// Sleep for 10s before killing ble, just in case we're using it
				go func() {
					time.Sleep(time.Second * 10)
					srv.Close()
				}()

				// and if the hostap isn't normally active, turn it off again
				if !config.Wireless_Host.Always_Active {
					logger.Infof("Terminating AdHoc pairing assistant.")
					go func() {
						// Sleep for 20 sec before killing ap, just in case we're using it to set up!
						time.Sleep(time.Second * 20)
						apManager.StopHostAP()
					}()
				}
			}

			if factoryReset {
				// if the app provided credentials, then we need to wait for app to acknowledge the connected state
				// before we exit otherwise it may not receive the response. So, we configure a callback which
				// will be called once the app as indicated that it has seen the connected state.
				wifi_manager.OnAcknowledgment(func() {
					logger.Infof("Network connected. Quitting.")
					os.Exit(0)
				})
			}

		case WifiStateDisconnected:
			if wireless_stale == nil {
				wireless_stale = time.AfterFunc(WirelessStaleTimeout, handleBadWireless)
			}

		case WifiStateInvalidKey:
			if wireless_stale == nil {
				wireless_stale = time.AfterFunc(WirelessStaleTimeout, handleBadWireless)
			}
			wifi_configured, _ = wifi_manager.WifiConfigured()
			if wifi_configured {
				// not stale, we actually know the key is wrong
				// FIXME: report back to the user! for now we're just going to let staleness timeout
				/*if wireless_stale != nil {
					wireless_stale.Stop()
				}
				wireless_stale = nil*/

				logger.Warningf("Wireless key is invalid!")
			}
		}
	}
}
<commit_msg>Allow LED controller to be re-enabled.<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/ninjasphere/gatt"
	"github.com/ninjasphere/go-ninja/api"
	nconfig "github.com/ninjasphere/go-ninja/config"
	nlog "github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/support"
	"github.com/ninjasphere/sphere-client/client"
	"github.com/ninjasphere/sphere-go-led-controller/model"
	"github.com/ninjasphere/sphere-go-led-controller/util"
)

const WirelessNetworkInterface = "wlan0"

// consider the wifi to be invalid after this timeout
const WirelessStaleTimeout = time.Second * 30 // FIXME: INCREASE THIS. a few minutes at least when not in testing.

var firewallHook = flag.Bool("firewall-hook", false, "Sets up the firewall based on configuration options, and nothing else.")
var factoryReset = false
var imagesDir = ""

// factoryReset - we can't use anything that requires MQTT in this mode

var logger = nlog.GetLogger("sphere-setup")

func main() {
	// ap0 adhoc/hostap management
	flag.BoolVar(&factoryReset, "factory-reset", false, "Run in factory reset mode.")
	flag.StringVar(&imagesDir, "images", "/opt/ninjablocks/drivers/sphere-go-led-controller/images", "The location of the images directory.")

	go func() {
		support.WaitUntilSignal()
	}()

	config := LoadConfig("/etc/opt/ninja/setup-assistant.conf")
	apManager := NewAccessPointManager(config)

	flag.Parse()

	if *firewallHook {
		logger.Debugf("Setting ip firewall rules...")
		apManager.SetupFirewall()
		return
	}

	util.SetImageDir(imagesDir)
	var pairing_ui ConsolePairingUI
	var controlChecker *ControlChecker

	restartHeartbeat := false

	if err := EnsureBLEIsUp(time.Second * 30); err != nil {
		logger.Errorf("BLE failed to start: %s", err)
	}

	startResetMonitor(func(m *model.ResetMode) {
		if pairing_ui == nil || controlChecker == nil {
			return
		}
		if m.Mode == "none" {
			if restartHeartbeat {
				// only restart the heartbeat if we stopped it previously
				controlChecker.StartHeartbeat()
			}
		} else {
			restartHeartbeat = controlChecker.StopHeartbeat()
		}
		pairing_ui.DisplayResetMode(m)
	})

	apManager.WriteAPConfig()
	if config.Wireless_Host.Always_Active {
		apManager.StartHostAP()
	} else {
		apManager.StopHostAP()
	}

	// wlan0 client management
	wifi_manager, err := NewWifiManager(WirelessNetworkInterface)
	if err != nil {
		log.Fatal("Could not setup manager for wlan0, does the interface exist?: %v", err)
	}
	defer wifi_manager.Cleanup()

	// When in reset mode, this will talk to the led matrix directly,
	// otherwise, it will use sphere-go-led-controller via mqtt.
	pairing_ui, err = NewPairingUI()
	if err != nil {
		log.Fatal("Could not setup ninja connection")
	}

	// This name is sent in the BLE advertising packet,
	// and is used by the phone to see that this is a
	// sphere, and if it is in factory reset mode.
	serviceName := "ninjasphere"
	if factoryReset {
		serviceName = "resetsphere"
	}

	srv := &gatt.Server{
		Name: serviceName,
		Connect: func(c gatt.Conn) {
			logger.Infof("BLE Connect")
			//pairing_ui.DisplayIcon("ble-connected.gif")
		},
		Disconnect: func(c gatt.Conn) {
			logger.Infof("BLE Disconnect")
			//pairing_ui.DisplayIcon("ble-disconnected.gif")
		},
		StateChange: func(state string) {
			logger.Infof("BLE State Change: %s", state)
		},
	}

	var conn *ninja.Connection

	if !factoryReset {

		conn, err = ninja.Connect("sphere-setup-assistant-updates")

		if err != nil {
			logger.FatalErrorf(err, "Failed to connect to mqtt")
		}
	}

	// start by registering the RPC functions that will be accessible
	// once the client has authenticated
	// We pass in the ble server so that we can close the connection once the updates are installed
	// (THIS SHOULD HAPPEN OVER WIFI INSTEAD!)
	rpc_router := GetSetupRPCRouter(conn, wifi_manager, srv, pairing_ui)

	StartHTTPServer(conn, wifi_manager, srv, pairing_ui)

	auth_handler := new(OneTimeAuthHandler)
	auth_handler.Init("spheramid")

	controlChecker = NewControlChecker(pairing_ui)

	RegisterSecuredRPCService(srv, rpc_router, auth_handler, pairing_ui)

	// Start the server
	//log.Println("Starting setup assistant...");
	//log.Fatal(srv.AdvertiseAndServe())

	states := wifi_manager.WatchState()

	//wifi_manager.WifiConfigured()

	var wireless_stale *time.Timer

	is_serving_pairer := false

	// start by forcing the state to Disconnected.
	// reloading the configuration in wpa_supplicant will also force this,
	// but we need to do it here in case we are already disconnected
	states <- WifiStateDisconnected
	wifi_manager.Controller.ReloadConfiguration()

	badWifiMessage := false

	handleBadWireless := func() {
		logger.Warningf("Wireless is stale! Invalid SSID, router down, or not in range.")

		if !is_serving_pairer {
			is_serving_pairer = true
			colorHintSent = false

			// If we aren't paired, update the avahi service
			if !nconfig.IsPaired() {
				client.UpdateSphereAvahiService(false, false)
			}

			// Show the phone pairing icon only if we don't always have AP
			if !config.Wireless_Host.Always_Active {
				pairing_ui.DisableControl()
				pairing_ui.DisplayIcon("phone-fade.gif")
				wifi_configured, _ := wifi_manager.WifiConfigured()
				if wifi_configured {
					badWifiMessage = true
				}
			}

			logger.Infof("Launching BLE pairing assistant...")
			go func() {
				err := srv.AdvertiseAndServe()
				if err != nil {
					logger.Infof("Failed to advertise and serve OR finished serving: %v", err)
				}
				is_serving_pairer = false
			}()

			// and if the hostap isn't normally active, make it active
			if !config.Wireless_Host.Always_Active {
				logger.Infof("Launching AdHoc pairing assistant...")
				apManager.StartHostAP()
			}
		}
	}

	wifi_configured, _ := wifi_manager.WifiConfigured()
	if !wifi_configured {
		// when wireless isn't configured at all, automatically start doing this, don't wait for staleness
		handleBadWireless()
	}

	if config.Wireless_Host.Enables_Control {
		// the wireless AP causes control to be enabled, so we just start the heartbeat immediately
		controlChecker.StartHeartbeat()
	}

	for {
		state := <-states
		logger.Infof("State: %v", state)

		switch state {
		case WifiStateConnected:
			if wireless_stale != nil {
				wireless_stale.Stop()
			}
			wireless_stale = nil
			logger.Infof("Connected and attempting to get IP.")

			/*if !config.Wireless_Host.Enables_Control {
				// if the wireless AP mode hasn't already enabled normal control, then enable it now that wifi works
				controlChecker.StartHeartbeat()
			}*/

			if badWifiMessage {
				badWifiMessage = false
				pairing_ui.EnableControl()
			}

			if is_serving_pairer {
				is_serving_pairer = false

				// Sleep for 10s before killing ble, just in case we're using it
				go func() {
					time.Sleep(time.Second * 10)
					srv.Close()
				}()

				// and if the hostap isn't normally active, turn it off again
				if !config.Wireless_Host.Always_Active {
					logger.Infof("Terminating AdHoc pairing assistant.")
					go func() {
						// Sleep for 20 sec before killing ap, just in case we're using it to set up!
						time.Sleep(time.Second * 20)
						apManager.StopHostAP()
					}()
				}
			}

			if factoryReset {
				// if the app provided credentials, then we need to wait for app to acknowledge the connected state
				// before we exit otherwise it may not receive the response. So, we configure a callback which
				// will be called once the app as indicated that it has seen the connected state.
				wifi_manager.OnAcknowledgment(func() {
					logger.Infof("Network connected. Quitting.")
					os.Exit(0)
				})
			}

		case WifiStateDisconnected:
			if wireless_stale == nil {
				wireless_stale = time.AfterFunc(WirelessStaleTimeout, handleBadWireless)
			}

		case WifiStateInvalidKey:
			if wireless_stale == nil {
				wireless_stale = time.AfterFunc(WirelessStaleTimeout, handleBadWireless)
			}
			wifi_configured, _ = wifi_manager.WifiConfigured()
			if wifi_configured {
				// not stale, we actually know the key is wrong
				// FIXME: report back to the user! for now we're just going to let staleness timeout
				/*if wireless_stale != nil {
					wireless_stale.Stop()
				}
				wireless_stale = nil*/

				logger.Warningf("Wireless key is invalid!")
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	var path = "./test-utils/files/"
	var reader Reader = DiskReader{}

	files, err := reader.Read(path)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%d file(s) read in the directory %s\n", len(files), path)

	NewConsole(
		files,
		LevenshteinRanking{},
		os.Stdin,
		os.Stderr,
	).Run()
}
<commit_msg>Adjust Main to provide a Reporter to Console<commit_after>package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	var reader Reader = DiskReader{}
	var reporter Reporter = SimpleReporter{}
	var rank Ranking = LevenshteinRanking{}

	var path = "./test-utils/files/"

	files, err := reader.Read(path)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%d file(s) read in the directory %s\n", len(files), path)

	NewConsole(
		files,
		rank,
		os.Stdin,
		os.Stderr,
		reporter,
	).Run()
}
<|endoftext|>


<commit_before>package main

import (
	_ "github.com/stef-k/gosimple/routers"
	"github.com/stef-k/gosimple/bootstrap"
	"github.com/astaxie/beego"
)

func init() {
	// setup Logger
	bootstrap.SetupLogger()
	// setup Session
	bootstrap.SetupSession()
	// setup XSRF
	bootstrap.SetupXSRF()
	// setup some opinionated defaults
	bootstrap.SetupDefaults()
}

func main() {
	beego.Run()
}

<commit_msg>main code rearrange<commit_after>package main

import (
	_ "github.com/stef-k/gosimple/routers"
	"github.com/stef-k/gosimple/bootstrap"
	"github.com/astaxie/beego"
)

func init() {
	// setup Logger
	bootstrap.SetupLogger()
	// setup some opinionated defaults
	bootstrap.SetupDefaults()
	// setup Session
	bootstrap.SetupSession()
	// setup XSRF
	bootstrap.SetupXSRF()
}

func main() {
	beego.Run()
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/concourse/fly/commands"
)

var executeFlags = []cli.Flag{
	cli.StringFlag{
		Name:  "config, c",
		Value: "build.yml",
		Usage: "build configuration file",
	},
	cli.StringSliceFlag{
		Name:  "input, i",
		Value: &cli.StringSlice{},
	},
	cli.BoolFlag{
		Name:  "insecure, k",
		Usage: "allow insecure SSL connections and transfers",
	},
	cli.BoolFlag{
		Name:  "exclude-ignored, x",
		Usage: "exclude vcs-ignored files from the build's inputs",
	},
	cli.BoolFlag{
		Name:  "privileged, p",
		Usage: "run the build with root privileges",
	},
}

func main() {
	app := cli.NewApp()
	app.Name = "fly"
	app.Usage = "Concourse CLI"
	app.Version = "0.0.1"
	app.Action = commands.Execute

	app.Flags = append(executeFlags, cli.StringFlag{
		Name:   "atcURL",
		Value:  "http://127.0.0.1:8080",
		Usage:  "address of the ATC to use",
		EnvVar: "ATC_URL",
	})

	app.Commands = []cli.Command{
		{
			Name:      "execute",
			ShortName: "e",
			Usage:     "Execute a build",
			Flags:     executeFlags,
			Action:    commands.Execute,
		},
		takeControl("hijack"),
		takeControl("intercept"),
		{
			Name:      "watch",
			ShortName: "w",
			Usage:     "Stream a build's log",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "job, j",
					Usage: "if specified, hijacks builds of the given job",
				},
				cli.StringFlag{
					Name:  "build, b",
					Usage: "hijack a specific build of a job",
				},
			},
			Action: commands.Watch,
		},
		{
			Name:      "configure",
			ShortName: "c",
			Usage:     "Update configuration",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "config, c",
					Usage: "pipeline configuration file",
				},
				cli.BoolFlag{
					Name:  "json, j",
					Usage: "print config as json instead of yaml",
				},
			},
			Action: commands.Configure,
		},
	}

	err := app.Run(os.Args)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}
}

func takeControl(commandName string) cli.Command {
	return cli.Command{
		Name:      commandName,
		ShortName: "i",
		Usage:     "Execute an interactive command in a build's container",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "job, j",
				Usage: fmt.Sprintf("if specified, %ss builds of the given job", commandName),
			},
			cli.StringFlag{
				Name:  "build, b",
				Usage: fmt.Sprintf("%s a specific build of a job", commandName),
			},
			cli.BoolFlag{
				Name:  "privileged, p",
				Usage: "run the build with root privileges",
			},
		},
		Action: commands.Hijack,
	}
}
<commit_msg>switch default uri to packer box<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/concourse/fly/commands"
)

var executeFlags = []cli.Flag{
	cli.StringFlag{
		Name:  "config, c",
		Value: "build.yml",
		Usage: "build configuration file",
	},
	cli.StringSliceFlag{
		Name:  "input, i",
		Value: &cli.StringSlice{},
	},
	cli.BoolFlag{
		Name:  "insecure, k",
		Usage: "allow insecure SSL connections and transfers",
	},
	cli.BoolFlag{
		Name:  "exclude-ignored, x",
		Usage: "exclude vcs-ignored files from the build's inputs",
	},
	cli.BoolFlag{
		Name:  "privileged, p",
		Usage: "run the build with root privileges",
	},
}

func main() {
	app := cli.NewApp()
	app.Name = "fly"
	app.Usage = "Concourse CLI"
	app.Version = "0.0.1"
	app.Action = commands.Execute

	app.Flags = append(executeFlags, cli.StringFlag{
		Name:   "atcURL",
		Value:  "http://192.168.100.4:8080",
		Usage:  "address of the ATC to use",
		EnvVar: "ATC_URL",
	})

	app.Commands = []cli.Command{
		{
			Name:      "execute",
			ShortName: "e",
			Usage:     "Execute a build",
			Flags:     executeFlags,
			Action:    commands.Execute,
		},
		takeControl("hijack"),
		takeControl("intercept"),
		{
			Name:      "watch",
			ShortName: "w",
			Usage:     "Stream a build's log",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "job, j",
					Usage: "if specified, hijacks builds of the given job",
				},
				cli.StringFlag{
					Name:  "build, b",
					Usage: "hijack a specific build of a job",
				},
			},
			Action: commands.Watch,
		},
		{
			Name:      "configure",
			ShortName: "c",
			Usage:     "Update configuration",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "config, c",
					Usage: "pipeline configuration file",
				},
				cli.BoolFlag{
					Name:  "json, j",
					Usage: "print config as json instead of yaml",
				},
			},
			Action: commands.Configure,
		},
	}

	err := app.Run(os.Args)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}
}

func takeControl(commandName string) cli.Command {
	return cli.Command{
		Name:      commandName,
		ShortName: "i",
		Usage:     "Execute an interactive command in a build's container",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "job, j",
				Usage: fmt.Sprintf("if specified, %ss builds of the given job", commandName),
			},
			cli.StringFlag{
				Name:  "build, b",
				Usage: fmt.Sprintf("%s a specific build of a job", commandName),
			},
			cli.BoolFlag{
				Name:  "privileged, p",
				Usage: "run the build with root privileges",
			},
		},
		Action: commands.Hijack,
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/astaxie/beego/orm"
	"github.com/go-martini/martini"
	"github.com/golang/glog"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"

	_ "github.com/go-sql-driver/mysql"
)

type Pages struct {
	Pages []*Page `json:"pages" binding:"required"`
}

type Page struct {
	Title string `json:"title" binding:"required"`
	Item  string `json:"item" binding:"required"`
}

func main() {
	flag.Parse()

	m := martini.Classic()
	m.Use(render.Renderer())

	host := "galera-lb"
	user := os.Getenv("MYSQL_USER")
	passwd := os.Getenv("MYSQL_PASSWORD")
	database := os.Getenv("MYSQL_DATABASE")

	if err := orm.RegisterDataBase("default",
		"mysql",
		fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8",
			user,
			passwd,
			host,
			database,
		),
		30,
	); err != nil {
		glog.Fatalf("connect to mysql error: %s", err.Error())
	}

	m.Get("/", GetPages)
	m.Post("/", binding.Bind(Pages{}), PostPage)

	m.Run()
}

func GetPages(req *http.Request, r render.Render) {
	glog.Info(req.RequestURI)

	var maps []orm.Params
	o := orm.NewOrm()
	num, err := o.Raw("select title, item from page").Values(&maps)
	if err != nil {
		r.Text(500, err.Error())
	}

	pages := &Pages{}
	for i := int64(0); i < num; i++ {
		p := &Page{
			Title: maps[i]["title"].(string),
			Item:  maps[i]["item"].(string),
		}

		pages.Pages = append(pages.Pages, p)
	}

	r.HTML(200, "index", pages)

}

func PostPage(req *http.Request, pages Pages) (int, string) {
	glog.Info(req.RemoteAddr)

	o := orm.NewOrm()
	for _, i := range pages.Pages {
		if _, err := o.
			Raw("insert into page(title, item) values(?, ?)").
			SetArgs(i.Title, i.Item).
			Exec(); err != nil {
			glog.Errorf("insert page (%s, %s) error", i.Title, i.Item)
			return 500, "insert page error"
		}

	}
	return 200, ""
}
<commit_msg>fix 表中无数据时的现实错误<commit_after>package main

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

	"github.com/astaxie/beego/orm"
	"github.com/go-martini/martini"
	"github.com/golang/glog"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"

	_ "github.com/go-sql-driver/mysql"
)

type Pages struct {
	Pages []*Page `json:"pages" binding:"required"`
}

type Page struct {
	Title string `json:"title" binding:"required"`
	Item  string `json:"item" binding:"required"`
}

func main() {
	flag.Parse()

	m := martini.Classic()
	m.Use(render.Renderer())

	host := "galera-lb"
	user := os.Getenv("MYSQL_USER")
	passwd := os.Getenv("MYSQL_PASSWORD")
	database := os.Getenv("MYSQL_DATABASE")

	if err := orm.RegisterDataBase("default",
		"mysql",
		fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8",
			user,
			passwd,
			host,
			database,
		),
		30,
	); err != nil {
		glog.Fatalf("connect to mysql error: %s", err.Error())
	}

	m.Get("/", GetPages)
	m.Post("/", binding.Bind(Pages{}), PostPage)

	m.Run()
}

func GetPages(req *http.Request, r render.Render) {
	glog.Info(req.RequestURI)

	var maps []orm.Params
	o := orm.NewOrm()
	num, err := o.Raw("select title, item from page").Values(&maps)
	if err != nil {
		r.Text(500, err.Error())
		return
	}

	pages := &Pages{}
	for i := int64(0); i < num; i++ {
		p := &Page{
			Title: maps[i]["title"].(string),
			Item:  maps[i]["item"].(string),
		}

		pages.Pages = append(pages.Pages, p)
	}

	r.HTML(200, "index", pages)

}

func PostPage(req *http.Request, pages Pages) (int, string) {
	glog.Info(req.RemoteAddr)

	o := orm.NewOrm()
	for _, i := range pages.Pages {
		if _, err := o.
			Raw("insert into page(title, item) values(?, ?)").
			SetArgs(i.Title, i.Item).
			Exec(); err != nil {
			glog.Errorf("insert page (%s, %s) error", i.Title, i.Item)
			return 500, "insert page error"
		}

	}
	return 200, ""
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/codegangsta/martini"
	"github.com/martini-contrib/render"
)

func main() {
	m := martini.Classic()

	m.Use(render.Renderer())

	t := thing{
		Name: "Brian",
		Age:  39,
	}

	m.Get("/", func(r render.Render) {
		r.JSON(200, t)
	})

	m.Run()
}

type thing struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}
<commit_msg>muckery<commit_after>/*
 * Copyright 2014 Brian McCallister
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *

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

import (
	"github.com/codegangsta/martini"
	"github.com/martini-contrib/render"
)

func main() {
	m := martini.Classic()
	m.Use(render.Renderer())

	m.Get("/", func(r render.Render) {
		r.JSON(200, person{
			Name: "World",
			Age:  6,
		})
	})

	m.Get("/:name", func(p martini.Params, r render.Render) {
		r.JSON(200, person{
			Name: p["name"],
			Age:  39,
		})
	})

	m.Run()
}

type person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/google/gops/agent"
	"github.com/tsuru/bs/bslog"
	"github.com/tsuru/bs/config"
	"github.com/tsuru/bs/log"
	"github.com/tsuru/bs/metric"
	_ "github.com/tsuru/bs/metric/logstash"
	"github.com/tsuru/bs/status"
)

const (
	version = "v1.11"
)

var printVersion bool

type StopWaiter interface {
	Stop()
	Wait()
}

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print version and exit")
}

func startSignalHandler(callback func(os.Signal), signals ...os.Signal) {
	sigChan := make(chan os.Signal, 4)
	go func() {
		if signal, ok := <-sigChan; ok {
			callback(signal)
		}
	}()
	signal.Notify(sigChan, signals...)
}

func main() {
	err := agent.Listen(&agent.Options{
		NoShutdownCleanup: true,
	})
	if err != nil {
		bslog.Fatalf("Unable to initialize gops agent: %s\n", err)
	}
	defer agent.Close()
	flag.Parse()
	if printVersion {
		fmt.Printf("bs version %s\n", version)
		return
	}
	lf := log.LogForwarder{
		BindAddress:     config.Config.SyslogListenAddress,
		DockerEndpoint:  config.Config.DockerEndpoint,
		EnabledBackends: config.Config.LogBackends,
	}
	err = lf.Start()
	if err != nil {
		bslog.Fatalf("Unable to initialize log forwarder: %s\n", err)
	}
	mRunner := metric.NewRunner(config.Config.DockerEndpoint, config.Config.MetricsInterval,
		config.Config.MetricsBackend)
	err = mRunner.Start()
	if err != nil {
		bslog.Warnf("Unable to initialize metrics runner: %s\n", err)
	}
	reporter, err := status.NewReporter(&status.ReporterConfig{
		TsuruEndpoint:  config.Config.TsuruEndpoint,
		TsuruToken:     config.Config.TsuruToken,
		DockerEndpoint: config.Config.DockerEndpoint,
		Interval:       config.Config.StatusInterval,
	})
	if err != nil {
		bslog.Warnf("Unable to initialize status reporter: %s\n", err)
	}
	monitorEl := []StopWaiter{&lf, mRunner}
	if reporter != nil {
		monitorEl = append(monitorEl, reporter)
	}
	var signaled bool
	startSignalHandler(func(signal os.Signal) {
		signaled = true
		for _, m := range monitorEl {
			go m.Stop()
		}
	}, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
	for _, m := range monitorEl {
		m.Wait()
	}
	if !signaled {
		bslog.Fatalf("Exiting bs because no service could be initialized.")
	}
}
<commit_msg>bump version to 1.12-rc1<commit_after>// Copyright 2016 bs authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/google/gops/agent"
	"github.com/tsuru/bs/bslog"
	"github.com/tsuru/bs/config"
	"github.com/tsuru/bs/log"
	"github.com/tsuru/bs/metric"
	_ "github.com/tsuru/bs/metric/logstash"
	"github.com/tsuru/bs/status"
)

const (
	version = "v1.12-rc1"
)

var printVersion bool

type StopWaiter interface {
	Stop()
	Wait()
}

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print version and exit")
}

func startSignalHandler(callback func(os.Signal), signals ...os.Signal) {
	sigChan := make(chan os.Signal, 4)
	go func() {
		if signal, ok := <-sigChan; ok {
			callback(signal)
		}
	}()
	signal.Notify(sigChan, signals...)
}

func main() {
	err := agent.Listen(&agent.Options{
		NoShutdownCleanup: true,
	})
	if err != nil {
		bslog.Fatalf("Unable to initialize gops agent: %s\n", err)
	}
	defer agent.Close()
	flag.Parse()
	if printVersion {
		fmt.Printf("bs version %s\n", version)
		return
	}
	lf := log.LogForwarder{
		BindAddress:     config.Config.SyslogListenAddress,
		DockerEndpoint:  config.Config.DockerEndpoint,
		EnabledBackends: config.Config.LogBackends,
	}
	err = lf.Start()
	if err != nil {
		bslog.Fatalf("Unable to initialize log forwarder: %s\n", err)
	}
	mRunner := metric.NewRunner(config.Config.DockerEndpoint, config.Config.MetricsInterval,
		config.Config.MetricsBackend)
	err = mRunner.Start()
	if err != nil {
		bslog.Warnf("Unable to initialize metrics runner: %s\n", err)
	}
	reporter, err := status.NewReporter(&status.ReporterConfig{
		TsuruEndpoint:  config.Config.TsuruEndpoint,
		TsuruToken:     config.Config.TsuruToken,
		DockerEndpoint: config.Config.DockerEndpoint,
		Interval:       config.Config.StatusInterval,
	})
	if err != nil {
		bslog.Warnf("Unable to initialize status reporter: %s\n", err)
	}
	monitorEl := []StopWaiter{&lf, mRunner}
	if reporter != nil {
		monitorEl = append(monitorEl, reporter)
	}
	var signaled bool
	startSignalHandler(func(signal os.Signal) {
		signaled = true
		for _, m := range monitorEl {
			go m.Stop()
		}
	}, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
	for _, m := range monitorEl {
		m.Wait()
	}
	if !signaled {
		bslog.Fatalf("Exiting bs because no service could be initialized.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/jessevdk/go-flags"
	"github.com/yuya-takeyama/argf"
)

func usage() {
	os.Stderr.WriteString(`
Usage: ltsvp OPTION... [FILE]...
Print selected parts of LTSV from each FILE to standard output.

Options:
  -k, --keys=LIST          select only these keys (required)
  -d, --delimiter=STRING   use STRING to separate parts (default: \t)
  -r, --remain-ltsv        print selected parts as LTSV
  -h, --help               display this help text and exit
  -v, --version            display version information and exit

LIST is made up of keys separated by commas.
  host           # Select host
  host,time,ua   # Select host, time, and ua
`[1:])
}

func version() {
	os.Stderr.WriteString(`
v0.2.0
`[1:])
}

type Option struct {
	List       string `short:"k" long:"keys" required:"true"`
	Delimiter  string `short:"d" long:"delimiter" default:"\t"`
	RemainLTSV bool   `short:"r" long:"remain-ltsv"`
	IsHelp     bool   `short:"h" long:"help"`
	IsVersion  bool   `short:"v" long:"version"`
	Files      []string
}

func parseOption(args []string) (opt *Option, err error) {
	opt = &Option{}
	flag := flags.NewParser(opt, flags.PassDoubleDash)

	opt.Files, err = flag.ParseArgs(args)
	if err != nil && !opt.IsHelp && !opt.IsVersion {
		return nil, err
	}
	return opt, nil
}

func newLTSVScannerFromOption(opt *Option) (l *LTSVScanner, err error) {
	keys := ParseKeysList(opt.List)
	reader, err := argf.From(opt.Files)
	if err != nil {
		return nil, err
	}

	l = NewLTSVScanner(keys, reader)
	l.Delimiter = opt.Delimiter
	l.RemainLTSV = opt.RemainLTSV
	return l, nil
}

func do(l *LTSVScanner) error {
	for l.Scan() {
		fmt.Println(l.Text())
	}
	return l.Err()
}

func printErr(err error) {
	fmt.Fprintln(os.Stderr, "ltsvp:", err)
}

func guideToHelp() {
	os.Stderr.WriteString(`
Try 'ltsvp --help' for more information.
`[1:])
}

func _main() int {
	opt, err := parseOption(os.Args[1:])
	if err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	switch {
	case opt.IsHelp:
		usage()
		return 0
	case opt.IsVersion:
		version()
		return 0
	}

	l, err := newLTSVScannerFromOption(opt)
	if err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	if err := do(l); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<commit_msg>Remove 'v' of version<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/jessevdk/go-flags"
	"github.com/yuya-takeyama/argf"
)

func usage() {
	os.Stderr.WriteString(`
Usage: ltsvp OPTION... [FILE]...
Print selected parts of LTSV from each FILE to standard output.

Options:
  -k, --keys=LIST          select only these keys (required)
  -d, --delimiter=STRING   use STRING to separate parts (default: \t)
  -r, --remain-ltsv        print selected parts as LTSV
  -h, --help               display this help text and exit
  -v, --version            display version information and exit

LIST is made up of keys separated by commas.
  host           # Select host
  host,time,ua   # Select host, time, and ua
`[1:])
}

func version() {
	os.Stderr.WriteString(`
0.2.0
`[1:])
}

type Option struct {
	List       string `short:"k" long:"keys" required:"true"`
	Delimiter  string `short:"d" long:"delimiter" default:"\t"`
	RemainLTSV bool   `short:"r" long:"remain-ltsv"`
	IsHelp     bool   `short:"h" long:"help"`
	IsVersion  bool   `short:"v" long:"version"`
	Files      []string
}

func parseOption(args []string) (opt *Option, err error) {
	opt = &Option{}
	flag := flags.NewParser(opt, flags.PassDoubleDash)

	opt.Files, err = flag.ParseArgs(args)
	if err != nil && !opt.IsHelp && !opt.IsVersion {
		return nil, err
	}
	return opt, nil
}

func newLTSVScannerFromOption(opt *Option) (l *LTSVScanner, err error) {
	keys := ParseKeysList(opt.List)
	reader, err := argf.From(opt.Files)
	if err != nil {
		return nil, err
	}

	l = NewLTSVScanner(keys, reader)
	l.Delimiter = opt.Delimiter
	l.RemainLTSV = opt.RemainLTSV
	return l, nil
}

func do(l *LTSVScanner) error {
	for l.Scan() {
		fmt.Println(l.Text())
	}
	return l.Err()
}

func printErr(err error) {
	fmt.Fprintln(os.Stderr, "ltsvp:", err)
}

func guideToHelp() {
	os.Stderr.WriteString(`
Try 'ltsvp --help' for more information.
`[1:])
}

func _main() int {
	opt, err := parseOption(os.Args[1:])
	if err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	switch {
	case opt.IsHelp:
		usage()
		return 0
	case opt.IsVersion:
		version()
		return 0
	}

	l, err := newLTSVScannerFromOption(opt)
	if err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	if err := do(l); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<|endoftext|>


<commit_before>// Go equivalent of the "DNS & BIND" book check-soa program.
// Created by Stephane Bortzmeyer.
package main

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"os"
	"sort"
	"time"

	"github.com/miekg/dns"
)

const (
	// DefaultTimeout is default timeout many operation in this program will
	// use.
	DefaultTimeout time.Duration = 5 * time.Second
)

var (
	localm           *dns.Msg
	localc           *dns.Client
	conf             *dns.ClientConfig
	domain           string
	assembledDomain string
	nextNs          string
)

func localQuery(qname string, qtype uint16, server string) (*dns.Msg, error) {
	localm.SetQuestion(qname, qtype)
	r, _, err := localc.Exchange(localm, server+":53")
	if err != nil {
		return nil, err
	}
	if r == nil || r.Rcode == dns.RcodeNameError || r.Rcode == dns.RcodeSuccess {
		return r, err
	}

	return nil, errors.New("No name server to answer the question")
}

func getNsRecords(zone string, server string) ([]string, string, error) {
	zone = dns.Fqdn(zone)
	r, err := localQuery(zone, dns.TypeNS, server)
	if err != nil || r == nil {
		log.Fatal("Cannot retrieve the list of name servers for %s: %s\n", zone, err)
	}

	var nameservers []string
	var random_ns string

	for _, ans := range r.Answer {
		switch t := ans.(type) {
		case *dns.NS:
			nameserver := t.Ns
			nameservers = append(nameservers, nameserver)
		}
	}

	if len(nameservers) == 0 {
		// No "Answer" given by the server, check the Authority section if
		// additional nameservers were provided.
		for _, ans := range r.Ns {
			switch t := ans.(type) {
			case *dns.NS:
				nameserver := t.Ns
				nameservers = append(nameservers, nameserver)
			}
		}
	}

	if len(nameservers) == 0 {
		return nil, "", errors.New("No nameservers found for " + zone)
	}

	// Pick a random NS record for the next queries
	random_ns = nameservers[rand.Intn(len(nameservers))]

	sort.Strings(nameservers)

	return nameservers, random_ns, nil

}

func main() {
	if len(os.Args) != 2 {
		log.Fatal("%s ZONE\n", os.Args[0])
	}
	domain = os.Args[1]

	rand.Seed(time.Now().Unix())
	var err error
	conf, err = dns.ClientConfigFromFile("/etc/resolv.conf")
	if err != nil || conf == nil {
		log.Fatal("Cannot initialize the local resolver: %s\n", err)
	}
	localm = &dns.Msg{
		MsgHdr: dns.MsgHdr{
			RecursionDesired: true,
		},
		Question: make([]dns.Question, 1),
	}
	localc = &dns.Client{
		ReadTimeout: DefaultTimeout,
	}

	// Walk the root until you find the authoritative nameservers
	fmt.Printf("Retrieving list of root nameservers:\n")
	root_nameservers, nextNs, err := getNsRecords(".", conf.Servers[0])
	if err != nil {
		log.Fatal("Query failed: ", err)
	}
	for _, nameserver := range root_nameservers {
		if nameserver == nextNs {
			// We'll use this one for queries
			fmt.Println(" ➡ " + nameserver)
		} else {
			fmt.Println(" - " + nameserver)
		}
	}

	// We have list of root nameservers: split domain, query each part for NS records
	domain_pieces := dns.SplitDomainName(domain)
	assembledDomain = "."
	var ns []string

	for i := len(domain_pieces) - 1; i >= 0; i-- {
		fmt.Println("\n")
		element := domain_pieces[i]
		if assembledDomain == "." {
			assembledDomain = element + "."
		} else {
			assembledDomain = element + "." + assembledDomain
		}

		fmt.Println("Finding nameservers for zone '" + assembledDomain + "' using parent nameserver '" + nextNs + "'")
		ns, nextNs, err = getNsRecords(assembledDomain, nextNs)
		if err != nil {
			fmt.Println("Query failed: ", err)
		}

		// Print the nameservers for this zone, highlight the one we used to query
		for _, nameserver := range ns {
			if nameserver == nextNs && dns.Fqdn(domain) != assembledDomain {
				// We'll use this one for queries
				fmt.Println(" ➡ " + nameserver)
			} else {
				fmt.Println(" - " + nameserver)
			}
		}
	}

}
<commit_msg>Error handling in main, not in functions + go fmt<commit_after>// Go equivalent of the "DNS & BIND" book check-soa program.
// Created by Stephane Bortzmeyer.
package main

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"os"
	"sort"
	"time"

	"github.com/miekg/dns"
)

const (
	// DefaultTimeout is default timeout many operation in this program will
	// use.
	DefaultTimeout time.Duration = 5 * time.Second
)

var (
	localm          *dns.Msg
	localc          *dns.Client
	conf            *dns.ClientConfig
	domain          string
	assembledDomain string
	nextNs          string
)

func localQuery(qname string, qtype uint16, server string) (*dns.Msg, error) {
	localm.SetQuestion(qname, qtype)
	r, _, err := localc.Exchange(localm, server+":53")
	if err != nil {
		return nil, err
	}
	if r == nil || r.Rcode == dns.RcodeNameError || r.Rcode == dns.RcodeSuccess {
		return r, err
	}

	return nil, errors.New("No name server to answer the question")
}

func getNsRecords(zone string, server string) ([]string, string, error) {
	zone = dns.Fqdn(zone)
	r, err := localQuery(zone, dns.TypeNS, server)
	if err != nil || r == nil {
		return nil, "", err
	}

	var nameservers []string
	var random_ns string

	for _, ans := range r.Answer {
		switch t := ans.(type) {
		case *dns.NS:
			nameserver := t.Ns
			nameservers = append(nameservers, nameserver)
		}
	}

	if len(nameservers) == 0 {
		// No "Answer" given by the server, check the Authority section if
		// additional nameservers were provided.
		for _, ans := range r.Ns {
			switch t := ans.(type) {
			case *dns.NS:
				nameserver := t.Ns
				nameservers = append(nameservers, nameserver)
			}
		}
	}

	if len(nameservers) == 0 {
		return nil, "", errors.New("No nameservers found for " + zone)
	}

	// Pick a random NS record for the next queries
	random_ns = nameservers[rand.Intn(len(nameservers))]

	sort.Strings(nameservers)

	return nameservers, random_ns, nil

}

func main() {
	if len(os.Args) != 2 {
		log.Fatal("%s ZONE\n", os.Args[0])
	}
	domain = os.Args[1]

	rand.Seed(time.Now().Unix())
	var err error
	conf, err = dns.ClientConfigFromFile("/etc/resolv.conf")
	if err != nil || conf == nil {
		log.Fatal("Cannot initialize the local resolver: %s\n", err)
	}
	localm = &dns.Msg{
		MsgHdr: dns.MsgHdr{
			RecursionDesired: true,
		},
		Question: make([]dns.Question, 1),
	}
	localc = &dns.Client{
		ReadTimeout: DefaultTimeout,
	}

	// Walk the root until you find the authoritative nameservers
	fmt.Printf("Retrieving list of root nameservers:\n")
	root_nameservers, nextNs, err := getNsRecords(".", conf.Servers[0])
	if err != nil {
		log.Fatal("Query failed: ", err)
	}
	for _, nameserver := range root_nameservers {
		if nameserver == nextNs {
			// We'll use this one for queries
			fmt.Println(" ➡ " + nameserver)
		} else {
			fmt.Println(" - " + nameserver)
		}
	}

	// We have list of root nameservers: split domain, query each part for NS records
	domain_pieces := dns.SplitDomainName(domain)
	assembledDomain = "."
	var ns []string

	for i := len(domain_pieces) - 1; i >= 0; i-- {
		fmt.Println("\n")
		element := domain_pieces[i]
		if assembledDomain == "." {
			assembledDomain = element + "."
		} else {
			assembledDomain = element + "." + assembledDomain
		}

		fmt.Println("Finding nameservers for zone '" + assembledDomain + "' using parent nameserver '" + nextNs + "'")
		ns, nextNs, err = getNsRecords(assembledDomain, nextNs)
		if err != nil {
			fmt.Println("Query failed: ", err)
		}

		// Print the nameservers for this zone, highlight the one we used to query
		for _, nameserver := range ns {
			if nameserver == nextNs && dns.Fqdn(domain) != assembledDomain {
				// We'll use this one for queries
				fmt.Println(" ➡ " + nameserver)
			} else {
				fmt.Println(" - " + nameserver)
			}
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"

	"github.com/elpinal/coco3/eval"
	"github.com/elpinal/coco3/parser"
	"github.com/mattn/go-runewidth"
)

var prompt = "; "

func main() {
	var command = flag.String("c", "", "take first argument as a command to execute")
	flag.Parse()
	if *command != "" {
		if err := execute([]byte(*command)); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	for {
		if err := loop(); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

const (
	CharCtrlA = iota + 1
	CharCtrlB
	CharCtrlC
	CharCtrlD
	CharCtrlE
	CharCtrlF
	CharCtrlG
	CharCtrlH
	CharCtrlI
	CharCtrlJ
	CharCtrlK
	CharCtrlL
	CharCtrlM
	CharCtrlN
	CharCtrlO
	CharCtrlP
	CharCtrlQ
	CharCtrlR
	CharCtrlS
	CharCtrlT
	CharCtrlU
	CharCtrlV
	CharCtrlW
	CharCtrlX
	CharCtrlY
	CharCtrlZ
	CharEscape

	CharBackspace = 127
)

func loop() error {
	fmt.Print(prompt)
	rd := NewReader(os.Stdin)
	cl := &commandline{
		w: bufio.NewWriter(os.Stdout),
	}
	state, err := enterRowMode()
	if err != nil {
		return err
	}
LOOP:
	for {
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch ch {
		case CharCtrlM:
			break LOOP
		case CharCtrlB:
			cl.moveBackward()
		case CharCtrlF:
			cl.moveForward()
		case CharBackspace:
			cl.deleteChar()
		default:
			cl.buf = append(cl.buf, ch)
			cl.index++
		}
		cl.refresh()
	}
	cl.w.WriteByte('\n')
	cl.w.Flush()
	err = exitRowMode(state)
	if err != nil {
		return err
	}
	return execute([]byte(string(cl.buf)))
}

func execute(b []byte) error {
	f, err := parser.ParseSrc(b)
	if err != nil {
		return err
	}
	return eval.Eval(f.Lines)
}

type commandline struct {
	w     *bufio.Writer
	buf   []rune
	index int
}

func (cl *commandline) refresh() {
	cl.w.WriteString("\r\033[J")
	cl.w.WriteString(prompt)
	cl.w.WriteString(string(cl.buf))
	cl.w.WriteString(fmt.Sprintf("\033[%vG", len(prompt)+runewidth.StringWidth(string(cl.buf[:cl.index]))+1))
	cl.w.Flush()
}

func (cl *commandline) moveBackward() {
	if cl.index == 0 {
		return
	}
	cl.index--
}

func (cl *commandline) moveForward() {
	if cl.index == len(cl.buf) {
		return
	}
	cl.index++
}

func (cl *commandline) deleteChar() {
	switch cl.index {
	case 0:
		return
	case 1:
		cl.buf = cl.buf[1:]
	case len(cl.buf):
		cl.buf = cl.buf[:cl.index-1]
	default:
		cl.buf = append(cl.buf[:cl.index-1], cl.buf[cl.index:]...)
	}
	cl.index--
}
<commit_msg>Fix inputs<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"

	"github.com/elpinal/coco3/eval"
	"github.com/elpinal/coco3/parser"
	"github.com/mattn/go-runewidth"
)

var prompt = "; "

func main() {
	var command = flag.String("c", "", "take first argument as a command to execute")
	flag.Parse()
	if *command != "" {
		if err := execute([]byte(*command)); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	for {
		if err := loop(); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

const (
	CharCtrlA = iota + 1
	CharCtrlB
	CharCtrlC
	CharCtrlD
	CharCtrlE
	CharCtrlF
	CharCtrlG
	CharCtrlH
	CharCtrlI
	CharCtrlJ
	CharCtrlK
	CharCtrlL
	CharCtrlM
	CharCtrlN
	CharCtrlO
	CharCtrlP
	CharCtrlQ
	CharCtrlR
	CharCtrlS
	CharCtrlT
	CharCtrlU
	CharCtrlV
	CharCtrlW
	CharCtrlX
	CharCtrlY
	CharCtrlZ
	CharEscape

	CharBackspace = 127
)

func loop() error {
	fmt.Print(prompt)
	rd := NewReader(os.Stdin)
	cl := &commandline{
		w: bufio.NewWriter(os.Stdout),
	}
	state, err := enterRowMode()
	if err != nil {
		return err
	}
LOOP:
	for {
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch ch {
		case CharCtrlM:
			break LOOP
		case CharCtrlB:
			cl.moveBackward()
		case CharCtrlF:
			cl.moveForward()
		case CharBackspace:
			cl.deleteChar()
		default:
			cl.appendChar(ch)
		}
		cl.refresh()
	}
	cl.w.WriteByte('\n')
	cl.w.Flush()
	err = exitRowMode(state)
	if err != nil {
		return err
	}
	return execute([]byte(string(cl.buf)))
}

func execute(b []byte) error {
	f, err := parser.ParseSrc(b)
	if err != nil {
		return err
	}
	return eval.Eval(f.Lines)
}

type commandline struct {
	w     *bufio.Writer
	buf   []rune
	index int
}

func (cl *commandline) refresh() {
	cl.w.WriteString("\r\033[J")
	cl.w.WriteString(prompt)
	cl.w.WriteString(string(cl.buf))
	cl.w.WriteString(fmt.Sprintf("\033[%vG", len(prompt)+runewidth.StringWidth(string(cl.buf[:cl.index]))+1))
	cl.w.Flush()
}

func (cl *commandline) moveBackward() {
	if cl.index == 0 {
		return
	}
	cl.index--
}

func (cl *commandline) moveForward() {
	if cl.index == len(cl.buf) {
		return
	}
	cl.index++
}

func (cl *commandline) appendChar(ch rune) {
	switch cl.index {
	case 0:
		cl.buf = append([]rune{ch}, cl.buf...)
	case len(cl.buf):
		cl.buf = append(cl.buf, ch)
	default:
		buf := make([]rune, cl.index, len(cl.buf)+1)
		copy(buf, cl.buf[:cl.index])
		buf = append(buf, ch)
		buf = append(buf, cl.buf[cl.index:]...)
		cl.buf = buf
	}
	cl.index++
}

func (cl *commandline) deleteChar() {
	switch cl.index {
	case 0:
		return
	case 1:
		cl.buf = cl.buf[1:]
	case len(cl.buf):
		cl.buf = cl.buf[:cl.index-1]
	default:
		cl.buf = append(cl.buf[:cl.index-1], cl.buf[cl.index:]...)
	}
	cl.index--
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/gcfg"
	"compress/gzip"
	"fmt"
	"github.com/boredomist/mixport/exports"
	"github.com/boredomist/mixport/mixpanel"
	flag "github.com/ogier/pflag"
	kinesis "github.com/sendgridlabs/go-kinesis"
	"io"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"strings"
	"sync"
	"syscall"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// Configuration options common to the file export streams (CSV and JSON)
type fileExportConfig struct {
	State     bool
	Gzip      bool
	Fifo      bool
	Directory string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
//
// - `Product` is Mixpanel API credential information for each product that will be
//   exported.
// - `Kinesis` is access keys and configuration for Amazon Kinesis exporter.
// - `JSON` and `CSV` are the configuration setups for the `JSON` and `CSV`
//   exporters, respectively.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON fileExportConfig
	CSV  fileExportConfig
}

var configFile = flag.StringP("config", "c", "./mixport.conf", "path to configuration file")
var dateString = flag.StringP("date", "d", "", "date of data to pull in YYYY/MM/DD, default is yesterday")
var rangeString = flag.StringP("range", "r", "", "date range to pull in YYYY/MM/DD-YYYY/MM/DD")
var cpuProfile = flag.String("prof", "", "dump pprof info to a file.")
var productList = flag.String("products", "", "comma separated list of products to export.")
var maxProcs = flag.IntP("procs", "p", runtime.NumCPU(), "maximum number of OS threads to spawn.")

// Holds parsed configuration file
var cfg = configFormat{}

// Will be set to true when an export goroutine fails. (to set status correctly)
var exportFailed = false

func main() {
	flag.Parse()

	runtime.GOMAXPROCS(*maxProcs)

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if err := gcfg.ReadFileInto(&cfg, *configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", *configFile, err)
	}

	var exportStart, exportEnd time.Time

	// Default to yesterday (should be newest available data)
	if *dateString == "" {
		year, month, day := time.Now().UTC().AddDate(0, 0, -1).Date()

		exportStart = time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
		exportEnd = exportStart
	} else {
		if d, err := time.Parse("2006/01/02", *dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY/MM/DD format",
				*dateString)
		} else {
			exportStart = d
			exportEnd = exportStart
		}
	}

	if *rangeString != "" {
		formatError := func() {
			log.Fatalf("Invalid range: %s, should be YYYY/MM/DD-YYYY/MM/DD.", *rangeString)
		}

		parts := strings.Split(*rangeString, "-")

		if len(parts) != 2 {
			formatError()
		}

		var err error

		if exportStart, err = time.Parse("2006/01/02", parts[0]); err != nil {
			formatError()
		}

		if exportEnd, err = time.Parse("2006/01/02", parts[1]); err != nil {
			formatError()
		}

	}

	products := make(map[string]*mixpanelCredentials)

	// If not explicitly specified, export all products in the config
	if *productList == "" {
		products = cfg.Product
	} else {
		for _, name := range strings.Split(*productList, ",") {
			if creds, ok := cfg.Product[name]; ok {
				products[name] = creds
			} else {
				log.Fatalf("Don't have credentials specified for %s", name)
			}
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range products {
		// Run each individual product in a new thread.
		go exportProduct(exportStart, exportEnd, product, *creds, &wg)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()

	if exportFailed {
		log.Fatalf("Export finished with errors.")
	}
}

func exportProduct(start, end time.Time, product string, creds mixpanelCredentials, wg *sync.WaitGroup) {
	defer wg.Done()

	client := mixpanel.New(product, creds.Key, creds.Secret)
	eventData := make(chan mixpanel.EventData)

	// We need to mux eventData into multiple channels to
	// ensure all export funcs have a chance to see each event
	// instance.
	var chans []chan mixpanel.EventData

	if cfg.Kinesis.State {
		ch := make(chan mixpanel.EventData)
		chans = append(chans, ch)

		ksis := kinesis.New(cfg.Kinesis.Keyid, cfg.Kinesis.Secretkey)
		if cfg.Kinesis.Region != "" {
			ksis.Region = "us-east-1"
		}

		wg.Add(1)
		go func() {
			exports.KinesisStreamer(ksis, cfg.Kinesis.Stream, ch)
			defer wg.Done()
		}()
	}

	type streamFunc func(io.Writer, <-chan mixpanel.EventData)

	// Generalize setup of JSON and CSV streams into a single function.
	setupFileExportStream := func(conf fileExportConfig, ext string, streamer streamFunc) {
		wg.Add(1)
		defer wg.Done()

		ch := make(chan mixpanel.EventData)
		chans = append(chans, ch)

		if conf.Gzip {
			ext += ".gz"
		}

		timeFmt := "20060102"
		stamp := start.Format(timeFmt)

		// Append end date to timestamp if we're using a date range.
		if start != end {
			stamp += fmt.Sprintf("-%s", end.Format(timeFmt))
		}

		name := path.Join(conf.Directory, fmt.Sprintf("%s-%s.%s", product, stamp, ext))

		if conf.Fifo {
			if err := syscall.Mkfifo(name, syscall.S_IRWXU); err != nil {
				log.Fatalf("Couldn't create named pipe: %s", err)
			}
		}

		fp, err := os.Create(name)
		if err != nil {
			log.Fatalf("Couldn't create file: %s", err)
		}

		if conf.Fifo {
			defer os.Remove(name)
		}
		defer fp.Close()

		writer := (io.Writer)(fp)
		if conf.Gzip {
			writer = gzip.NewWriter(fp)
			defer (writer).(*gzip.Writer).Close()
		} else {
			writer = fp
		}

		streamer(writer, ch)
	}

	if cfg.JSON.State {
		go setupFileExportStream(cfg.JSON, "json", exports.JSONStreamer)
	}

	if cfg.CSV.State {
		go setupFileExportStream(cfg.CSV, "csv", exports.CSVStreamer)
	}

	go func(end time.Time) {
		defer close(eventData)

		// We want it to be start-end inclusive, so add one day to end date.
		end = end.AddDate(0, 0, 1)

		for date := start; date.Before(end); date = date.AddDate(0, 0, 1) {
			if err := client.ExportDate(date, eventData, nil); err != nil {
				log.Printf("export failed: %v", err)
				exportFailed = true
				break
			}
		}
	}(end)

	// Multiplex each received event to each of the active export
	// functions.
	for data := range eventData {
		for _, ch := range chans {
			ch <- data
		}
	}

	// Closing all the channels will signal the streaming export functions
	// that they've reached the end of the stream and should terminate as
	// soon as the channel is drained.
	for _, ch := range chans {
		close(ch)
	}
}
<commit_msg>Set flags inside of main()<commit_after>package main

import (
	"code.google.com/p/gcfg"
	"compress/gzip"
	"fmt"
	"github.com/boredomist/mixport/exports"
	"github.com/boredomist/mixport/mixpanel"
	flag "github.com/ogier/pflag"
	kinesis "github.com/sendgridlabs/go-kinesis"
	"io"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"strings"
	"sync"
	"syscall"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// Configuration options common to the file export streams (CSV and JSON)
type fileExportConfig struct {
	State     bool
	Gzip      bool
	Fifo      bool
	Directory string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
//
// - `Product` is Mixpanel API credential information for each product that will be
//   exported.
// - `Kinesis` is access keys and configuration for Amazon Kinesis exporter.
// - `JSON` and `CSV` are the configuration setups for the `JSON` and `CSV`
//   exporters, respectively.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON fileExportConfig
	CSV  fileExportConfig
}

// Holds parsed configuration file
var cfg = configFormat{}

// Will be set to true when an export goroutine fails (to set exit status
// correctly).
var exportFailed = false

func main() {

	var (
		configFile  = flag.StringP("config", "c", "./mixport.conf", "path to configuration file")
		dateString  = flag.StringP("date", "d", "", "date of data to pull in YYYY/MM/DD, default is yesterday")
		rangeString = flag.StringP("range", "r", "", "date range to pull in YYYY/MM/DD-YYYY/MM/DD")
		cpuProfile  = flag.String("prof", "", "dump pprof info to a file.")
		productList = flag.String("products", "", "comma separated list of products to export.")
		maxProcs    = flag.IntP("procs", "p", runtime.NumCPU(), "maximum number of OS threads to spawn.")
	)

	flag.Parse()

	runtime.GOMAXPROCS(*maxProcs)

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if err := gcfg.ReadFileInto(&cfg, *configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", *configFile, err)
	}

	var exportStart, exportEnd time.Time

	// Default to yesterday (should be newest available data)
	if *dateString == "" {
		year, month, day := time.Now().UTC().AddDate(0, 0, -1).Date()

		exportStart = time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
		exportEnd = exportStart
	} else {
		if d, err := time.Parse("2006/01/02", *dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY/MM/DD format",
				*dateString)
		} else {
			exportStart = d
			exportEnd = exportStart
		}
	}

	if *rangeString != "" {
		formatError := func() {
			log.Fatalf("Invalid range: %s, should be YYYY/MM/DD-YYYY/MM/DD.", *rangeString)
		}

		parts := strings.Split(*rangeString, "-")

		if len(parts) != 2 {
			formatError()
		}

		var err error

		if exportStart, err = time.Parse("2006/01/02", parts[0]); err != nil {
			formatError()
		}

		if exportEnd, err = time.Parse("2006/01/02", parts[1]); err != nil {
			formatError()
		}

	}

	products := make(map[string]*mixpanelCredentials)

	// If not explicitly specified, export all products in the config
	if *productList == "" {
		products = cfg.Product
	} else {
		for _, name := range strings.Split(*productList, ",") {
			if creds, ok := cfg.Product[name]; ok {
				products[name] = creds
			} else {
				log.Fatalf("Don't have credentials specified for %s", name)
			}
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range products {
		// Run each individual product in a new thread.
		go exportProduct(exportStart, exportEnd, product, *creds, &wg)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()

	if exportFailed {
		log.Fatalf("Export finished with errors.")
	}
}

func exportProduct(start, end time.Time, product string, creds mixpanelCredentials, wg *sync.WaitGroup) {
	defer wg.Done()

	client := mixpanel.New(product, creds.Key, creds.Secret)
	eventData := make(chan mixpanel.EventData)

	// We need to mux eventData into multiple channels to
	// ensure all export funcs have a chance to see each event
	// instance.
	var chans []chan mixpanel.EventData

	if cfg.Kinesis.State {
		ch := make(chan mixpanel.EventData)
		chans = append(chans, ch)

		ksis := kinesis.New(cfg.Kinesis.Keyid, cfg.Kinesis.Secretkey)
		if cfg.Kinesis.Region != "" {
			ksis.Region = "us-east-1"
		}

		wg.Add(1)
		go func() {
			exports.KinesisStreamer(ksis, cfg.Kinesis.Stream, ch)
			defer wg.Done()
		}()
	}

	type streamFunc func(io.Writer, <-chan mixpanel.EventData)

	// Generalize setup of JSON and CSV streams into a single function.
	setupFileExportStream := func(conf fileExportConfig, ext string, streamer streamFunc) {
		wg.Add(1)
		defer wg.Done()

		ch := make(chan mixpanel.EventData)
		chans = append(chans, ch)

		if conf.Gzip {
			ext += ".gz"
		}

		timeFmt := "20060102"
		stamp := start.Format(timeFmt)

		// Append end date to timestamp if we're using a date range.
		if start != end {
			stamp += fmt.Sprintf("-%s", end.Format(timeFmt))
		}

		name := path.Join(conf.Directory, fmt.Sprintf("%s-%s.%s", product, stamp, ext))

		if conf.Fifo {
			if err := syscall.Mkfifo(name, syscall.S_IRWXU); err != nil {
				log.Fatalf("Couldn't create named pipe: %s", err)
			}
		}

		fp, err := os.Create(name)
		if err != nil {
			log.Fatalf("Couldn't create file: %s", err)
		}

		if conf.Fifo {
			defer os.Remove(name)
		}
		defer fp.Close()

		writer := (io.Writer)(fp)
		if conf.Gzip {
			writer = gzip.NewWriter(fp)
			defer (writer).(*gzip.Writer).Close()
		} else {
			writer = fp
		}

		streamer(writer, ch)
	}

	if cfg.JSON.State {
		go setupFileExportStream(cfg.JSON, "json", exports.JSONStreamer)
	}

	if cfg.CSV.State {
		go setupFileExportStream(cfg.CSV, "csv", exports.CSVStreamer)
	}

	go func(end time.Time) {
		defer close(eventData)

		// We want it to be start-end inclusive, so add one day to end date.
		end = end.AddDate(0, 0, 1)

		for date := start; date.Before(end); date = date.AddDate(0, 0, 1) {
			if err := client.ExportDate(date, eventData, nil); err != nil {
				log.Printf("export failed: %v", err)
				exportFailed = true
				break
			}
		}
	}(end)

	// Multiplex each received event to each of the active export funcs.
	for data := range eventData {
		for _, ch := range chans {
			ch <- data
		}
	}

	// Closing all the channels will signal the streaming export functions
	// that they've reached the end of the stream and should terminate as
	// soon as the channel is drained.
	for _, ch := range chans {
		close(ch)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

// map[VERSION:3.14.10 (13 September 2011) debian MINTIMEL:3 Minutes BATTDATE:2014-10-21 END APC:2016-08-30 17 NUMXFERS:0 NOMPOWER:480 Watts NOMINV:230 Volts FIRMWARE:925.T1 .I USB FW APC:001,036,0923 STATUS:ONLINE BCHARGE:100.0 Percent TONBATT:0 seconds HOSTNAME:beaker.murf.org CABLE:USB Cable TIMELEFT:104.6 Minutes SELFTEST:NO ALARMDEL:30 seconds STATFLAG:0x07000008 Status Flag DATE:2016-08-30 17 UPSMODE:Stand Alone MAXTIME:0 Seconds SENSE:Medium HITRANS:280.0 Volts LASTXFER:Unacceptable line voltage changes XOFFBATT:N/A SERIALNO:3B1443X05291 UPSNAME:backups-950 DRIVER:USB UPS Driver STARTTIME:2016-08-30 16 LOADPCT:5.0 Percent Load Capacity MBATTCHG:5 Percent LOTRANS:155.0 Volts BATTV:13.5 Volts CUMONBATT:0 seconds MODEL:Back-UPS XS 950U LINEV:242.0 Volts NOMBATTV:12.0 Volts

type upsInfo struct {
	status string

	nomPower             float64
	batteryChargePercent float64

	timeOnBattery    time.Duration
	timeLeft         time.Duration
	cumTimeOnBattery time.Duration

	loadPercent float64

	batteryVoltage    float64
	lineVoltage       float64
	nomBatteryVoltage float64
	nomInputVoltage   float64

	hostname string
	upsName  string
}

// See SVN code at https://sourceforge.net/p/apcupsd/svn/HEAD/tree/trunk/src/lib/apcstatus.c#l166 for
// list of statuses.
var statusList = []string{
	"online",
	"onbatt",
	"trim",
	"boost",
	"overload",
	"lowbatt",
	"replacebatt",
	"nobatt",
	"slave",
	"slavedown",
	"commlost",
	"shutting down",
}

var (
	labels = []string{"hostname", "upsname"}

	status = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_status",
		Help: "Current status of UPS",
	},
		append(labels, "status"),
	)

	statusNumeric = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_status_numeric",
		Help: "Current status of UPS represented as integer",
	},
		labels,
	)

	nominalPower = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nominal_power_watts",
		Help: "Nominal UPS Power",
	},
		labels,
	)

	batteryChargePercent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_battery_charge_percent",
		Help: "Percentage Battery Charge",
	},
		labels,
	)

	loadPercent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_load_percent",
		Help: "Percentage Battery Load",
	},
		labels,
	)

	timeOnBattery = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_time_on_battery_seconds",
		Help: "Total time on UPS battery",
	},
		labels,
	)

	timeLeft = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_time_left_seconds",
		Help: "Time on UPS battery",
	},
		labels,
	)

	cumTimeOnBattery = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_cum_time_on_battery_seconds",
		Help: "Cumululative Time on UPS battery",
	},
		labels,
	)

	batteryVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_battery_volts",
		Help: "UPS Battery Voltage",
	},
		labels,
	)

	lineVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_line_volts",
		Help: "UPS Line Voltage",
	},
		labels,
	)

	nomBatteryVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nom_battery_volts",
		Help: "UPS Nominal Battery Voltage",
	},
		labels,
	)

	nomInputVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nom_input_volts",
		Help: "UPS Nominal Input Voltage",
	},
		labels,
	)

	collectSeconds = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_collect_time_seconds",
		Help: "Time to collect stats for last poll of UPS network interface",
	},
		labels,
	)
)

func main() {

	// TODO: Register a port for listening here: https://github.com/prometheus/prometheus/wiki/Default-port-allocations
	addr := flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
	upsAddr := flag.String("ups-address", "localhost:3551", "The address of the acupsd daemon to query: hostname:port")
	flag.Parse()

	log.Printf("Connection to UPS at: %s", *upsAddr)
	log.Printf("Metric listener at: %s", *addr)

	prometheus.MustRegister(status)
	prometheus.MustRegister(statusNumeric)
	prometheus.MustRegister(nominalPower)
	prometheus.MustRegister(batteryChargePercent)
	prometheus.MustRegister(timeOnBattery)
	prometheus.MustRegister(timeLeft)
	prometheus.MustRegister(cumTimeOnBattery)
	prometheus.MustRegister(loadPercent)
	prometheus.MustRegister(batteryVoltage)
	prometheus.MustRegister(lineVoltage)
	prometheus.MustRegister(nomBatteryVoltage)
	prometheus.MustRegister(nomInputVoltage)
	prometheus.MustRegister(collectSeconds)

	go func() {
		c := time.Tick(10 * time.Second)
		for _ = range c {
			if err := collectUPSData(upsAddr); err != nil {
				log.Printf("Error collecting UPS data: %+v", err)
			}
		}

	}()

	http.Handle("/metrics", prometheus.Handler())
	http.ListenAndServe(*addr, nil)
}

func collectUPSData(upsAddr *string) error {

	gatherStart := time.Now()

	data, err := retrieveData(*upsAddr)
	if err != nil {
		return err
	}

	gatherDuration := time.Now().Sub(gatherStart)

	info, err := transformData(data)
	if err != nil {
		return err
	}
	collectSeconds.WithLabelValues(info.hostname, info.upsName).Set(gatherDuration.Seconds())

	log.Printf("%+v", info)

	for i, stat := range statusList {
		if stat == info.status {
			status.WithLabelValues(info.hostname, info.upsName, stat).Set(1)
			statusNumeric.WithLabelValues(info.hostname, info.upsName).Set(float64(i))
		} else {
			status.WithLabelValues(info.hostname, info.upsName, stat).Set(0)
		}
	}

	status.WithLabelValues(info.hostname, info.upsName, info.status).Set(1)

	nominalPower.WithLabelValues(info.hostname, info.upsName).Set(info.nomPower)

	batteryChargePercent.WithLabelValues(info.hostname, info.upsName).Set(info.batteryChargePercent)
	timeOnBattery.WithLabelValues(info.hostname, info.upsName).Set(info.timeOnBattery.Seconds())

	timeLeft.WithLabelValues(info.hostname, info.upsName).Set(info.timeLeft.Seconds())

	cumTimeOnBattery.WithLabelValues(info.hostname, info.upsName).Set(info.cumTimeOnBattery.Seconds())
	loadPercent.WithLabelValues(info.hostname, info.upsName).Set(info.loadPercent)
	batteryVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.batteryVoltage)
	lineVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.lineVoltage)
	nomBatteryVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.nomBatteryVoltage)
	nomInputVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.nomInputVoltage)

	return nil
}

func transformData(ups map[string]string) (*upsInfo, error) {

	upsInfo := &upsInfo{}

	upsInfo.status = strings.ToLower(ups["STATUS"])

	if nomPower, err := parseUnits(ups["NOMPOWER"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomPower = nomPower
	}

	if chargePercent, err := parseUnits(ups["BCHARGE"]); err != nil {
		return nil, err
	} else {
		upsInfo.batteryChargePercent = chargePercent
	}

	if time, err := parseTime(ups["TONBATT"]); err != nil {
		return nil, err
	} else {
		upsInfo.timeOnBattery = time
	}

	if time, err := parseTime(ups["TIMELEFT"]); err != nil {
		return nil, err
	} else {
		upsInfo.timeLeft = time
	}

	if time, err := parseTime(ups["CUMONBATT"]); err != nil {
		return nil, err
	} else {
		upsInfo.cumTimeOnBattery = time
	}

	if percent, err := parseUnits(ups["LOADPCT"]); err != nil {
		return nil, err
	} else {
		upsInfo.loadPercent = percent
	}

	if volts, err := parseUnits(ups["BATTV"]); err != nil {
		return nil, err
	} else {
		upsInfo.batteryVoltage = volts
	}

	if volts, err := parseUnits(ups["LINEV"]); err != nil {
		return nil, err
	} else {
		upsInfo.lineVoltage = volts
	}

	if volts, err := parseUnits(ups["NOMBATTV"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomBatteryVoltage = volts
	}

	if volts, err := parseUnits(ups["NOMINV"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomInputVoltage = volts
	}

	upsInfo.hostname = ups["HOSTNAME"]
	upsInfo.upsName = ups["UPSNAME"]

	return upsInfo, nil
}

// parse time strings like 30 seconds or 1.25 minutes
func parseTime(t string) (time.Duration, error) {
	chunks := strings.Split(t, " ")
	fmtStr := chunks[0] + string(strings.ToLower(chunks[1])[0])
	return time.ParseDuration(fmtStr)
}

// parse generic units, splitting of units name and converting to float
func parseUnits(v string) (float64, error) {
	if v == ""{
		return 0, nil
	}
	return strconv.ParseFloat(strings.Split(v, " ")[0], 32)
}

func retrieveData(hostPort string) (map[string]string, error) {

	conn, err := net.Dial("tcp", hostPort)
	if err != nil {
		return nil, fmt.Errorf("Unable to connect to remote port: %+v", err)
	}

	if _, err = conn.Write([]byte{0, 6}); err != nil {
		return nil, fmt.Errorf("Error writing command length: %+v", err)
	}

	if _, err = conn.Write([]byte("status")); err != nil {
		return nil, fmt.Errorf("Error writing command data: %+v", err)
	}

	complete := false
	upsData := map[string]string{}

	for !complete {
		sizeBuf := []byte{0, 0}
		var size int16
		if _, err := conn.Read(sizeBuf); err != nil {
			return nil, fmt.Errorf("Error reading size from incoming reader: %+v", err)
		}

		if err = binary.Read(bytes.NewBuffer(sizeBuf), binary.BigEndian, &size); err != nil {
			return nil, fmt.Errorf("Error decoding size in response: %+v", err)
		}

		if size > 0 {
			data := make([]byte, size)
			if _, err = conn.Read(data); err != nil {
				log.Panicf("Error reading size from incoming reader: %+v", err)
			}
			chunks := strings.Split(string(data), ":")
			upsData[strings.TrimSpace(chunks[0])] = strings.TrimSpace(chunks[1])

		} else {
			complete = true
		}
	}

	if err = conn.Close(); err != nil {
		log.Panicf("Error closing apcupsd connection: %+v", err)
	}

	return upsData, nil

}
<commit_msg>Prevent panic when a time field is missing (e.g. TIMELEFT)<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

// map[VERSION:3.14.10 (13 September 2011) debian MINTIMEL:3 Minutes BATTDATE:2014-10-21 END APC:2016-08-30 17 NUMXFERS:0 NOMPOWER:480 Watts NOMINV:230 Volts FIRMWARE:925.T1 .I USB FW APC:001,036,0923 STATUS:ONLINE BCHARGE:100.0 Percent TONBATT:0 seconds HOSTNAME:beaker.murf.org CABLE:USB Cable TIMELEFT:104.6 Minutes SELFTEST:NO ALARMDEL:30 seconds STATFLAG:0x07000008 Status Flag DATE:2016-08-30 17 UPSMODE:Stand Alone MAXTIME:0 Seconds SENSE:Medium HITRANS:280.0 Volts LASTXFER:Unacceptable line voltage changes XOFFBATT:N/A SERIALNO:3B1443X05291 UPSNAME:backups-950 DRIVER:USB UPS Driver STARTTIME:2016-08-30 16 LOADPCT:5.0 Percent Load Capacity MBATTCHG:5 Percent LOTRANS:155.0 Volts BATTV:13.5 Volts CUMONBATT:0 seconds MODEL:Back-UPS XS 950U LINEV:242.0 Volts NOMBATTV:12.0 Volts

type upsInfo struct {
	status string

	nomPower             float64
	batteryChargePercent float64

	timeOnBattery    time.Duration
	timeLeft         time.Duration
	cumTimeOnBattery time.Duration

	loadPercent float64

	batteryVoltage    float64
	lineVoltage       float64
	nomBatteryVoltage float64
	nomInputVoltage   float64

	hostname string
	upsName  string
}

// See SVN code at https://sourceforge.net/p/apcupsd/svn/HEAD/tree/trunk/src/lib/apcstatus.c#l166 for
// list of statuses.
var statusList = []string{
	"online",
	"onbatt",
	"trim",
	"boost",
	"overload",
	"lowbatt",
	"replacebatt",
	"nobatt",
	"slave",
	"slavedown",
	"commlost",
	"shutting down",
}

var (
	labels = []string{"hostname", "upsname"}

	status = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_status",
		Help: "Current status of UPS",
	},
		append(labels, "status"),
	)

	statusNumeric = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_status_numeric",
		Help: "Current status of UPS represented as integer",
	},
		labels,
	)

	nominalPower = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nominal_power_watts",
		Help: "Nominal UPS Power",
	},
		labels,
	)

	batteryChargePercent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_battery_charge_percent",
		Help: "Percentage Battery Charge",
	},
		labels,
	)

	loadPercent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_load_percent",
		Help: "Percentage Battery Load",
	},
		labels,
	)

	timeOnBattery = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_time_on_battery_seconds",
		Help: "Total time on UPS battery",
	},
		labels,
	)

	timeLeft = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_time_left_seconds",
		Help: "Time on UPS battery",
	},
		labels,
	)

	cumTimeOnBattery = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_cum_time_on_battery_seconds",
		Help: "Cumululative Time on UPS battery",
	},
		labels,
	)

	batteryVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_battery_volts",
		Help: "UPS Battery Voltage",
	},
		labels,
	)

	lineVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_line_volts",
		Help: "UPS Line Voltage",
	},
		labels,
	)

	nomBatteryVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nom_battery_volts",
		Help: "UPS Nominal Battery Voltage",
	},
		labels,
	)

	nomInputVoltage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_nom_input_volts",
		Help: "UPS Nominal Input Voltage",
	},
		labels,
	)

	collectSeconds = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "apcups_collect_time_seconds",
		Help: "Time to collect stats for last poll of UPS network interface",
	},
		labels,
	)
)

func main() {

	// TODO: Register a port for listening here: https://github.com/prometheus/prometheus/wiki/Default-port-allocations
	addr := flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
	upsAddr := flag.String("ups-address", "localhost:3551", "The address of the acupsd daemon to query: hostname:port")
	flag.Parse()

	log.Printf("Connection to UPS at: %s", *upsAddr)
	log.Printf("Metric listener at: %s", *addr)

	prometheus.MustRegister(status)
	prometheus.MustRegister(statusNumeric)
	prometheus.MustRegister(nominalPower)
	prometheus.MustRegister(batteryChargePercent)
	prometheus.MustRegister(timeOnBattery)
	prometheus.MustRegister(timeLeft)
	prometheus.MustRegister(cumTimeOnBattery)
	prometheus.MustRegister(loadPercent)
	prometheus.MustRegister(batteryVoltage)
	prometheus.MustRegister(lineVoltage)
	prometheus.MustRegister(nomBatteryVoltage)
	prometheus.MustRegister(nomInputVoltage)
	prometheus.MustRegister(collectSeconds)

	go func() {
		c := time.Tick(10 * time.Second)
		for _ = range c {
			if err := collectUPSData(upsAddr); err != nil {
				log.Printf("Error collecting UPS data: %+v", err)
			}
		}

	}()

	http.Handle("/metrics", prometheus.Handler())
	http.ListenAndServe(*addr, nil)
}

func collectUPSData(upsAddr *string) error {

	gatherStart := time.Now()

	data, err := retrieveData(*upsAddr)
	if err != nil {
		return err
	}

	gatherDuration := time.Now().Sub(gatherStart)

	info, err := transformData(data)
	if err != nil {
		return err
	}
	collectSeconds.WithLabelValues(info.hostname, info.upsName).Set(gatherDuration.Seconds())

	log.Printf("%+v", info)

	for i, stat := range statusList {
		if stat == info.status {
			status.WithLabelValues(info.hostname, info.upsName, stat).Set(1)
			statusNumeric.WithLabelValues(info.hostname, info.upsName).Set(float64(i))
		} else {
			status.WithLabelValues(info.hostname, info.upsName, stat).Set(0)
		}
	}

	status.WithLabelValues(info.hostname, info.upsName, info.status).Set(1)

	nominalPower.WithLabelValues(info.hostname, info.upsName).Set(info.nomPower)

	batteryChargePercent.WithLabelValues(info.hostname, info.upsName).Set(info.batteryChargePercent)
	timeOnBattery.WithLabelValues(info.hostname, info.upsName).Set(info.timeOnBattery.Seconds())

	timeLeft.WithLabelValues(info.hostname, info.upsName).Set(info.timeLeft.Seconds())

	cumTimeOnBattery.WithLabelValues(info.hostname, info.upsName).Set(info.cumTimeOnBattery.Seconds())
	loadPercent.WithLabelValues(info.hostname, info.upsName).Set(info.loadPercent)
	batteryVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.batteryVoltage)
	lineVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.lineVoltage)
	nomBatteryVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.nomBatteryVoltage)
	nomInputVoltage.WithLabelValues(info.hostname, info.upsName).Set(info.nomInputVoltage)

	return nil
}

func transformData(ups map[string]string) (*upsInfo, error) {

	upsInfo := &upsInfo{}

	upsInfo.status = strings.ToLower(ups["STATUS"])

	if nomPower, err := parseUnits(ups["NOMPOWER"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomPower = nomPower
	}

	if chargePercent, err := parseUnits(ups["BCHARGE"]); err != nil {
		return nil, err
	} else {
		upsInfo.batteryChargePercent = chargePercent
	}

	if time, err := parseTime(ups["TONBATT"]); err != nil {
		return nil, err
	} else {
		upsInfo.timeOnBattery = time
	}

	if time, err := parseTime(ups["TIMELEFT"]); err != nil {
		return nil, err
	} else {
		upsInfo.timeLeft = time
	}

	if time, err := parseTime(ups["CUMONBATT"]); err != nil {
		return nil, err
	} else {
		upsInfo.cumTimeOnBattery = time
	}

	if percent, err := parseUnits(ups["LOADPCT"]); err != nil {
		return nil, err
	} else {
		upsInfo.loadPercent = percent
	}

	if volts, err := parseUnits(ups["BATTV"]); err != nil {
		return nil, err
	} else {
		upsInfo.batteryVoltage = volts
	}

	if volts, err := parseUnits(ups["LINEV"]); err != nil {
		return nil, err
	} else {
		upsInfo.lineVoltage = volts
	}

	if volts, err := parseUnits(ups["NOMBATTV"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomBatteryVoltage = volts
	}

	if volts, err := parseUnits(ups["NOMINV"]); err != nil {
		return nil, err
	} else {
		upsInfo.nomInputVoltage = volts
	}

	upsInfo.hostname = ups["HOSTNAME"]
	upsInfo.upsName = ups["UPSNAME"]

	return upsInfo, nil
}

// parse time strings like 30 seconds or 1.25 minutes
func parseTime(t string) (time.Duration, error) {
	if t == ""{
		return 0, nil
	}
	chunks := strings.Split(t, " ")
	fmtStr := chunks[0] + string(strings.ToLower(chunks[1])[0])
	return time.ParseDuration(fmtStr)
}

// parse generic units, splitting of units name and converting to float
func parseUnits(v string) (float64, error) {
	if v == ""{
		return 0, nil
	}
	return strconv.ParseFloat(strings.Split(v, " ")[0], 32)
}

func retrieveData(hostPort string) (map[string]string, error) {

	conn, err := net.Dial("tcp", hostPort)
	if err != nil {
		return nil, fmt.Errorf("Unable to connect to remote port: %+v", err)
	}

	if _, err = conn.Write([]byte{0, 6}); err != nil {
		return nil, fmt.Errorf("Error writing command length: %+v", err)
	}

	if _, err = conn.Write([]byte("status")); err != nil {
		return nil, fmt.Errorf("Error writing command data: %+v", err)
	}

	complete := false
	upsData := map[string]string{}

	for !complete {
		sizeBuf := []byte{0, 0}
		var size int16
		if _, err := conn.Read(sizeBuf); err != nil {
			return nil, fmt.Errorf("Error reading size from incoming reader: %+v", err)
		}

		if err = binary.Read(bytes.NewBuffer(sizeBuf), binary.BigEndian, &size); err != nil {
			return nil, fmt.Errorf("Error decoding size in response: %+v", err)
		}

		if size > 0 {
			data := make([]byte, size)
			if _, err = conn.Read(data); err != nil {
				log.Panicf("Error reading size from incoming reader: %+v", err)
			}
			chunks := strings.Split(string(data), ":")
			upsData[strings.TrimSpace(chunks[0])] = strings.TrimSpace(chunks[1])

		} else {
			complete = true
		}
	}

	if err = conn.Close(); err != nil {
		log.Panicf("Error closing apcupsd connection: %+v", err)
	}

	return upsData, nil

}
<|endoftext|>


<commit_before>package main

import (
	"./highbatch"
	"github.com/BurntSushi/toml"
	"os"
	"bytes"
	"io/ioutil"
	"fmt"
	"path/filepath"
)

func main() {

	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	fmt.Println(dir)
	if err != nil {
		fmt.Println(err)
	}
	if err := os.Chdir(dir); err != nil {
		fmt.Println(err)
	}

	highbatch.LogInit("debug")

	if bootCheck() {							// 設定ファイルの有無
		highbatch.Ld("start HighBatch")

		// 設定ファイルの読み込み
		highbatch.LoadConfig()
		highbatch.Ld("load config")

		if highbatch.Conf.Server.Name != "" { // マスターの場合

			// DBの作成
			highbatch.Initdb()
			highbatch.Ld("init boltdb")

			// バッチ処理指示エンジンの起動
			go highbatch.StartArranger()
			highbatch.Ld("start arranger")

			// バッチ処理設定関係の変更監視とダウンロード用ZIP作成
			go highbatch.StartWatcher()
			highbatch.Ld("start watcher()")
		}

		// 処理結果の未送信情報再送信
		go highbatch.ReSend()
		highbatch.Ld("start resend")

		// バッチ処理エンジンの起動
		go highbatch.StartWorker()
		highbatch.Ld("start worker")

		// 通信用HTTPサーバー起動
		highbatch.StartWebserver()
	}
}

func bootCheck() bool {
	configfile := "config.toml"

	if _, err := os.Stat(configfile); err != nil {
		var config highbatch.ClientConfigFile

		tag := []string{"test"}
		config.Client.Tag = tag
		config.Client.Master.Hostname = "localhost"
		config.Client.Master.Port = "8081"

		var buffer bytes.Buffer
		encoder := toml.NewEncoder(&buffer)
		if err := encoder.Encode(config); err != nil {
			highbatch.Le(err);
		}
		if err := ioutil.WriteFile(configfile, []byte(buffer.String()), 0644); err != nil {
			highbatch.Le(err)
		}
		highbatch.Lw("create config file")
		return false
	} else {
		return true
	}
}
<commit_msg>起動パスの調整<commit_after>package main

import (
	"./highbatch"
	"github.com/BurntSushi/toml"
	"os"
	"bytes"
	"io/ioutil"
	"fmt"
)

func main() {

	dir, err := os.Getwd()
	fmt.Println(dir)
	if err != nil {
		fmt.Println(err)
	}
	if err := os.Chdir(dir); err != nil {
		fmt.Println(err)
	}

	highbatch.LogInit("debug")

	if bootCheck() {							// 設定ファイルの有無
		highbatch.Ld("start HighBatch")

		// 設定ファイルの読み込み
		highbatch.LoadConfig()
		highbatch.Ld("load config")

		if highbatch.Conf.Server.Name != "" { // マスターの場合

			// DBの作成
			highbatch.Initdb()
			highbatch.Ld("init boltdb")

			// バッチ処理指示エンジンの起動
			go highbatch.StartArranger()
			highbatch.Ld("start arranger")

			// バッチ処理設定関係の変更監視とダウンロード用ZIP作成
			go highbatch.StartWatcher()
			highbatch.Ld("start watcher()")
		}

		// 処理結果の未送信情報再送信
		go highbatch.ReSend()
		highbatch.Ld("start resend")

		// バッチ処理エンジンの起動
		go highbatch.StartWorker()
		highbatch.Ld("start worker")

		// 通信用HTTPサーバー起動
		highbatch.StartWebserver()
	}
}

func bootCheck() bool {
	configfile := "config.toml"

	if _, err := os.Stat(configfile); err != nil {
		var config highbatch.ClientConfigFile

		tag := []string{"test"}
		config.Client.Tag = tag
		config.Client.Master.Hostname = "localhost"
		config.Client.Master.Port = "8081"

		var buffer bytes.Buffer
		encoder := toml.NewEncoder(&buffer)
		if err := encoder.Encode(config); err != nil {
			highbatch.Le(err);
		}
		if err := ioutil.WriteFile(configfile, []byte(buffer.String()), 0644); err != nil {
			highbatch.Le(err)
		}
		highbatch.Lw("create config file")
		return false
	} else {
		return true
	}
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "io/ioutil"
import "io"
import "log"
import "net/url"
import "os"
import "os/exec"
import "path/filepath"
import "strings"

func cleanWcRoot(wcPath string) (err error) {
	infos, err := ioutil.ReadDir(wcPath)
	if nil != err {
		return
	}
	for _, inf := range infos {
		if ".svn" == inf.Name() {
			continue
		}
		fullPath := filepath.Join(wcPath, inf.Name())
		err = os.RemoveAll(fullPath)
		if nil != err {
			return
		}
	}
	return nil
}

func execPiped(name string, arg ...string) error {
	fmt.Println(name + " " + strings.Join(arg, " "))
	cmd := exec.Command(name, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	return cmd.Run()
}

func copyFile(src, dst string) (err error) {
	fmt.Println(src)
	fmt.Println(dst)
	fmt.Println()
	s, err := os.Open(src)
	if err != nil {
		return
	}
	defer func() {
		closeErr := s.Close()
		if nil == err {
			err = closeErr
		}
	}()
	d, err := os.Create(dst)
	if err != nil {
		return
	}
	_, err = io.Copy(d, s)
	if nil != err {
		d.Close()
		return
	}
	return d.Close()
}

func copyRecursive(srcDir, dstDir string) (err error) {
	err = os.MkdirAll(dstDir, perm)
	if nil != err {
		return
	}
	infs, err := ioutil.ReadDir(srcDir)
	if nil != err {
		return
	}
	for _, inf := range infs {
		src := filepath.Join(srcDir, inf.Name())
		dst := filepath.Join(dstDir, inf.Name())
		if inf.IsDir() {
			err = copyRecursive(src, dst)
			if nil != err {
				return
			}
			continue
		}
		err = copyFile(src, dst)
		if nil != err {
			return
		}
	}
	return nil
}

func svnDiffCommit(srcPath string, wcPath string, repos *url.URL) (err error) {
	err = execPiped("svn", "checkout", repos.String(), wcPath)
	if nil != err {
		return
	}
	err = cleanWcRoot(wcPath)
	if nil != err {
		return
	}
	err = copyRecursive(srcPath, wcPath)
	if nil != err {
		return
	}
	// svn status
	// svn remove all missing files
	// svn commit
	return nil
}

func createRepos(reposPath string) (repos *url.URL, err error) {
	err = execPiped("svnadmin", "create", reposPath)
	if nil != err {
		return
	}
	absReposPath, err := filepath.Abs(reposPath)
	if nil != err {
		return
	}
	absReposPath = "file://" + absReposPath
	repos, err = url.Parse(absReposPath)
	return
}

type testData struct {
	Path string;
	IsDir bool;
	Content string;
}

func makeTestData() []testData {
	result := []testData {
		{ "1.txt", false, "data1" },
		{ "2.txt", false, "data2" },
		{ "subdir1", true, "" },
		{ filepath.Join("subdir1", "1.txt"), false, "subdata1" },
		{ "subdir2", true, "" } }
	return result
}

const perm = 0755

func createTestSourceFiles(basePath string) (err error) {
	err = os.Mkdir(basePath, perm)
	if nil != err {
		return
	}
	testDatas := makeTestData()
	for _, td := range testDatas {
		path := filepath.Join(basePath, td.Path)
		if td.IsDir {
			err = os.Mkdir(path, perm)
			if nil != err {
				return
			}
			continue
		}
		err = ioutil.WriteFile(path, []byte(td.Content), perm)
		if nil != err {
			return
		}
	}
	return nil
}

func setupTest(testPath string) (repos *url.URL, srcPath string, err error) {
	err = os.Mkdir(testPath, perm)
	if nil != err {
		return
	}
	srcPath = filepath.Join(testPath, "src")
	err = createTestSourceFiles(srcPath)
	if nil != err {
		return
	}
	reposPath := filepath.Join(testPath, "repos")
	repos, err = createRepos(reposPath)
	return
}

func teardownTest(testPath string) {
	err := os.RemoveAll(testPath)
	if nil != err {
		log.Println("ERROR: ", err)
	}
}

func runSelfTest() (err error) {
	fmt.Print("\n\nSelf test --> Start...\n\n\n")
	testPath := filepath.Join(".", "self_test")
	reposUrl, srcPath, err := setupTest(testPath)
	if nil != err {
		return
	}
	defer teardownTest(testPath)
	wcPath := filepath.Join(testPath, "wc")
	err = svnDiffCommit(srcPath, wcPath, reposUrl)
	if nil != err {
		return
	}
	fmt.Print("\n\nSelf test --> Success.\n\n\n")
	return nil
}

func main() {
	err := runSelfTest()
	if nil != err {
		log.Fatal(err)
	}
}

<commit_msg>gofmt -s -w .<commit_after>package main

import "fmt"
import "io/ioutil"
import "io"
import "log"
import "net/url"
import "os"
import "os/exec"
import "path/filepath"
import "strings"

func cleanWcRoot(wcPath string) (err error) {
	infos, err := ioutil.ReadDir(wcPath)
	if nil != err {
		return
	}
	for _, inf := range infos {
		if ".svn" == inf.Name() {
			continue
		}
		fullPath := filepath.Join(wcPath, inf.Name())
		err = os.RemoveAll(fullPath)
		if nil != err {
			return
		}
	}
	return nil
}

func execPiped(name string, arg ...string) error {
	fmt.Println(name + " " + strings.Join(arg, " "))
	cmd := exec.Command(name, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	return cmd.Run()
}

func copyFile(src, dst string) (err error) {
	fmt.Println(src)
	fmt.Println(dst)
	fmt.Println()
	s, err := os.Open(src)
	if err != nil {
		return
	}
	defer func() {
		closeErr := s.Close()
		if nil == err {
			err = closeErr
		}
	}()
	d, err := os.Create(dst)
	if err != nil {
		return
	}
	_, err = io.Copy(d, s)
	if nil != err {
		d.Close()
		return
	}
	return d.Close()
}

func copyRecursive(srcDir, dstDir string) (err error) {
	err = os.MkdirAll(dstDir, perm)
	if nil != err {
		return
	}
	infs, err := ioutil.ReadDir(srcDir)
	if nil != err {
		return
	}
	for _, inf := range infs {
		src := filepath.Join(srcDir, inf.Name())
		dst := filepath.Join(dstDir, inf.Name())
		if inf.IsDir() {
			err = copyRecursive(src, dst)
			if nil != err {
				return
			}
			continue
		}
		err = copyFile(src, dst)
		if nil != err {
			return
		}
	}
	return nil
}

func svnDiffCommit(srcPath string, wcPath string, repos *url.URL) (err error) {
	err = execPiped("svn", "checkout", repos.String(), wcPath)
	if nil != err {
		return
	}
	err = cleanWcRoot(wcPath)
	if nil != err {
		return
	}
	err = copyRecursive(srcPath, wcPath)
	if nil != err {
		return
	}
	// svn status
	// svn remove all missing files
	// svn commit
	return nil
}

func createRepos(reposPath string) (repos *url.URL, err error) {
	err = execPiped("svnadmin", "create", reposPath)
	if nil != err {
		return
	}
	absReposPath, err := filepath.Abs(reposPath)
	if nil != err {
		return
	}
	absReposPath = "file://" + absReposPath
	repos, err = url.Parse(absReposPath)
	return
}

type testData struct {
	Path    string
	IsDir   bool
	Content string
}

func makeTestData() []testData {
	result := []testData{
		{"1.txt", false, "data1"},
		{"2.txt", false, "data2"},
		{"subdir1", true, ""},
		{filepath.Join("subdir1", "1.txt"), false, "subdata1"},
		{"subdir2", true, ""}}
	return result
}

const perm = 0755

func createTestSourceFiles(basePath string) (err error) {
	err = os.Mkdir(basePath, perm)
	if nil != err {
		return
	}
	testDatas := makeTestData()
	for _, td := range testDatas {
		path := filepath.Join(basePath, td.Path)
		if td.IsDir {
			err = os.Mkdir(path, perm)
			if nil != err {
				return
			}
			continue
		}
		err = ioutil.WriteFile(path, []byte(td.Content), perm)
		if nil != err {
			return
		}
	}
	return nil
}

func setupTest(testPath string) (repos *url.URL, srcPath string, err error) {
	err = os.Mkdir(testPath, perm)
	if nil != err {
		return
	}
	srcPath = filepath.Join(testPath, "src")
	err = createTestSourceFiles(srcPath)
	if nil != err {
		return
	}
	reposPath := filepath.Join(testPath, "repos")
	repos, err = createRepos(reposPath)
	return
}

func teardownTest(testPath string) {
	err := os.RemoveAll(testPath)
	if nil != err {
		log.Println("ERROR: ", err)
	}
}

func runSelfTest() (err error) {
	fmt.Print("\n\nSelf test --> Start...\n\n\n")
	testPath := filepath.Join(".", "self_test")
	reposUrl, srcPath, err := setupTest(testPath)
	if nil != err {
		return
	}
	defer teardownTest(testPath)
	wcPath := filepath.Join(testPath, "wc")
	err = svnDiffCommit(srcPath, wcPath, reposUrl)
	if nil != err {
		return
	}
	fmt.Print("\n\nSelf test --> Success.\n\n\n")
	return nil
}

func main() {
	err := runSelfTest()
	if nil != err {
		log.Fatal(err)
	}
}
<|endoftext|>