<commit_before>package cmd

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/bpicode/fritzctl/config"
	"github.com/mitchellh/cli"
	"github.com/stretchr/testify/assert"
)

// TestCommands is a unit test that runs most commands.
func TestCommands(t *testing.T) {
	testCases := []struct {
		cmd  cli.Command
		args []string
		srv  *httptest.Server
	}{
		{cmd: &pingCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml")},
		{cmd: &listSwitchesCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml")},
		{cmd: &listThermostatsCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml")},
		{cmd: &switchOnCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &switchOffCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &temperatureCommand{}, args: []string{"19.5", "My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &toggleCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &sessionIDCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml")},
		{cmd: &listLandevicesCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/landevices_test.json")},
		{cmd: &listLogsCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/logs_7_lines_test.json")},
		{cmd: &listInetstatsCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/traffic_mon_answer.json")},
		{cmd: &listSwitchesCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &listThermostatsCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestExportCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestPlanCommand{}, args: []string{"../testdata/devicelist_fritzos06.83_plan.yml"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestApplyCommand{}, args: []string{"../testdata/devicelist_fritzos06.83_plan.yml"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml", "testdata/answer_switch_on_test", "testdata/answer_switch_on_test")},
	}
	for i, testCase := range testCases {
		t.Run(fmt.Sprintf("Test run command %d", i), func(t *testing.T) {
			l, err := net.Listen("tcp", ":61666")
			assert.NoError(t, err)
			testCase.srv.Listener = l
			testCase.srv.Start()
			defer testCase.srv.Close()
			exitCode := testCase.cmd.Run(testCase.args)
			assert.Equal(t, 0, exitCode)
		})
	}
}

// TestConfigure tests the interactive configuration.
func TestConfigure(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "test_fritzctl")
	defer os.Remove(tempDir)
	assert.NoError(t, err)
	config.DefaultConfigDir = tempDir
	c := configureCommand{}
	i := c.Run([]string{})
	assert.Equal(t, 0, i)
}

func serverAnswering(answers ...string) *httptest.Server {
	config.ConfigDir = "../testdata"
	config.ConfigFilename = "config_localhost_https_test.json"
	it := 0
	server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ch, _ := os.Open(answers[it%len(answers)])
		defer ch.Close()
		it++
		io.Copy(w, ch)
	}))
	return server
}

// TestCommandsHaveHelp ensures that every command provides
// a help text.
func TestCommandsHaveHelp(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"complete":        CompletionBash(c),
		"configure":       Configure,
		"applymanifest":   ManifestApply,
		"exportmanifest":  ManifestExport,
		"planmanifest":    ManifestPlan,
		"listswitches":    ListSwitches,
		"listthermostats": ListThermostats,
		"listlandevices":  ListLandevices,
		"listlogs":        ListLogs,
		"ping":            Ping,
		"sessionid":       SessionID,
		"switchon":        SwitchOnDevice,
		"switchoff":       SwitchOffDevice,
		"toggle":          ToggleDevice,
		"temperature":     Temperature,
		"inetstatas":      ListInetstats,
	}
	for i, command := range c.Commands {
		t.Run(fmt.Sprintf("Test help of command %s", i), func(t *testing.T) {
			com, err := command()
			assert.NoError(t, err)
			help := com.Help()
			fmt.Printf("Help on command %s: '%s'\n", i, help)
			assert.NotEmpty(t, help)
		})
	}
}

// TestCommandsHaveSynopsis ensures that every command provides
// short a synopsis text.
func TestCommandsHaveSynopsis(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"complete":        CompletionBash(c),
		"configure":       Configure,
		"applymanifest":   ManifestApply,
		"exportmanifest":  ManifestExport,
		"planmanifest":    ManifestPlan,
		"listswitches":    ListSwitches,
		"listthermostats": ListThermostats,
		"listlandevices":  ListLandevices,
		"listlogs":        ListLogs,
		"ping":            Ping,
		"sessionid":       SessionID,
		"switchon":        SwitchOnDevice,
		"switchoff":       SwitchOffDevice,
		"toggle":          ToggleDevice,
		"temperature":     Temperature,
		"inetstatas":      ListInetstats,
	}
	for i, command := range c.Commands {
		t.Run(fmt.Sprintf("Test synopsis of command %s", i), func(t *testing.T) {
			com, err := command()
			assert.NoError(t, err)
			syn := com.Synopsis()
			fmt.Printf("Synopsis on command '%s': '%s'\n", i, syn)
			assert.NotEmpty(t, syn)
		})
	}
}

// TestCompletionBash tests the bash completion export.
func TestCompletionBash(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"ping": Ping,
	}
	completionBashFactory := CompletionBash(c)
	command, err := completionBashFactory()
	assert.NoError(t, err)
	exitCode := command.Run([]string{})
	assert.Equal(t, 0, exitCode)
}
<commit_msg>fix race condition in tests<commit_after>package cmd

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"os"
	"sync/atomic"
	"testing"

	"github.com/bpicode/fritzctl/config"
	"github.com/mitchellh/cli"
	"github.com/stretchr/testify/assert"
)

// TestCommands is a unit test that runs most commands.
func TestCommands(t *testing.T) {
	testCases := []struct {
		cmd  cli.Command
		args []string
		srv  *httptest.Server
	}{
		{cmd: &pingCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml")},
		{cmd: &listSwitchesCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml")},
		{cmd: &listThermostatsCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml")},
		{cmd: &switchOnCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &switchOffCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &temperatureCommand{}, args: []string{"19.5", "My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &toggleCommand{}, args: []string{"My device"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_4_devices_test.xml", "testdata/answer_switch_on_test")},
		{cmd: &sessionIDCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml")},
		{cmd: &listLandevicesCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/landevices_test.json")},
		{cmd: &listLogsCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/logs_7_lines_test.json")},
		{cmd: &listInetstatsCommand{}, args: []string{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/traffic_mon_answer.json")},
		{cmd: &listSwitchesCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &listThermostatsCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestExportCommand{}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestPlanCommand{}, args: []string{"../testdata/devicelist_fritzos06.83_plan.yml"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml")},
		{cmd: &manifestApplyCommand{}, args: []string{"../testdata/devicelist_fritzos06.83_plan.yml"}, srv: serverAnswering("../testdata/loginresponse_test.xml", "../testdata/loginresponse_test.xml", "../testdata/devicelist_fritzos06.83.xml", "testdata/answer_switch_on_test", "testdata/answer_switch_on_test")},
	}
	for i, testCase := range testCases {
		t.Run(fmt.Sprintf("Test run command %d", i), func(t *testing.T) {
			l, err := net.Listen("tcp", ":61666")
			assert.NoError(t, err)
			testCase.srv.Listener = l
			testCase.srv.Start()
			defer testCase.srv.Close()
			exitCode := testCase.cmd.Run(testCase.args)
			assert.Equal(t, 0, exitCode)
		})
	}
}

// TestConfigure tests the interactive configuration.
func TestConfigure(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "test_fritzctl")
	defer os.Remove(tempDir)
	assert.NoError(t, err)
	config.DefaultConfigDir = tempDir
	c := configureCommand{}
	i := c.Run([]string{})
	assert.Equal(t, 0, i)
}

func serverAnswering(answers ...string) *httptest.Server {
	config.ConfigDir = "../testdata"
	config.ConfigFilename = "config_localhost_https_test.json"

	var it int32
	it = 0
	server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ch, _ := os.Open(answers[int(it)%len(answers)])
		defer ch.Close()
		atomic.AddInt32(&it, 1)
		io.Copy(w, ch)
	}))
	return server
}

// TestCommandsHaveHelp ensures that every command provides
// a help text.
func TestCommandsHaveHelp(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"complete":        CompletionBash(c),
		"configure":       Configure,
		"applymanifest":   ManifestApply,
		"exportmanifest":  ManifestExport,
		"planmanifest":    ManifestPlan,
		"listswitches":    ListSwitches,
		"listthermostats": ListThermostats,
		"listlandevices":  ListLandevices,
		"listlogs":        ListLogs,
		"ping":            Ping,
		"sessionid":       SessionID,
		"switchon":        SwitchOnDevice,
		"switchoff":       SwitchOffDevice,
		"toggle":          ToggleDevice,
		"temperature":     Temperature,
		"inetstatas":      ListInetstats,
	}
	for i, command := range c.Commands {
		t.Run(fmt.Sprintf("Test help of command %s", i), func(t *testing.T) {
			com, err := command()
			assert.NoError(t, err)
			help := com.Help()
			fmt.Printf("Help on command %s: '%s'\n", i, help)
			assert.NotEmpty(t, help)
		})
	}
}

// TestCommandsHaveSynopsis ensures that every command provides
// short a synopsis text.
func TestCommandsHaveSynopsis(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"complete":        CompletionBash(c),
		"configure":       Configure,
		"applymanifest":   ManifestApply,
		"exportmanifest":  ManifestExport,
		"planmanifest":    ManifestPlan,
		"listswitches":    ListSwitches,
		"listthermostats": ListThermostats,
		"listlandevices":  ListLandevices,
		"listlogs":        ListLogs,
		"ping":            Ping,
		"sessionid":       SessionID,
		"switchon":        SwitchOnDevice,
		"switchoff":       SwitchOffDevice,
		"toggle":          ToggleDevice,
		"temperature":     Temperature,
		"inetstatas":      ListInetstats,
	}
	for i, command := range c.Commands {
		t.Run(fmt.Sprintf("Test synopsis of command %s", i), func(t *testing.T) {
			com, err := command()
			assert.NoError(t, err)
			syn := com.Synopsis()
			fmt.Printf("Synopsis on command '%s': '%s'\n", i, syn)
			assert.NotEmpty(t, syn)
		})
	}
}

// TestCompletionBash tests the bash completion export.
func TestCompletionBash(t *testing.T) {
	c := cli.NewCLI(config.ApplicationName, config.Version)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"ping": Ping,
	}
	completionBashFactory := CompletionBash(c)
	command, err := completionBashFactory()
	assert.NoError(t, err)
	exitCode := command.Run([]string{})
	assert.Equal(t, 0, exitCode)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/google/uuid"
	"github.com/pkg/errors"
)

type Scout struct {
	installID string
	index     int
	metadata  map[string]interface{}
}

type ScoutMeta struct {
	Key   string
	Value interface{}
}

func NewScout(mode string) (s *Scout) {
	// Fixed (growing) metadata passed with every report
	metadata := make(map[string]interface{})
	metadata["mode"] = mode
	metadata["trace_id"] = uuid.New().String()

	// The result
	s = &Scout{metadata: metadata}

	// Get or create the persistent install ID for Edge Control
	err := func() error {
		// We store the persistent ID in ~/.config/edgectl/id to be consistent
		// with Telepresence. We could instead use os.UserConfigDir() as the
		// root of the destination, which may be the same on Linux, but is
		// definitely different on MacOS.
		home, err := os.UserHomeDir()
		if err != nil {
			return err
		}
		configDir := filepath.Join(home, ".config", "edgectl")
		if err := os.MkdirAll(configDir, 0755); err != nil {
			return err
		}
		idFilename := filepath.Join(configDir, "id")

		// Try to read an existing install ID
		if installIDBytes, err := ioutil.ReadFile(idFilename); err == nil {
			s.installID = string(installIDBytes)
			// Validate UUID format
			if _, err := uuid.Parse(s.installID); err == nil {
				metadata["new_install"] = false
				return nil
			} // else the value is not a UUID
		} // else file doesn't exist, etc.

		// Try to create a new install ID
		s.installID = uuid.New().String()
		metadata["new_install"] = true
		if err := ioutil.WriteFile(idFilename, []byte(s.installID), 0755); err != nil {
			return err
		}
		return nil
	}()
	if err != nil {
		s.installID = "00000000-0000-0000-0000-000000000000"
		metadata["new_install"] = true
		metadata["install_id_error"] = err.Error()
	}

	return
}

func (s *Scout) SetMetadatum(key string, value interface{}) {
	oldValue, ok := s.metadata[key]
	if ok {
		panic(fmt.Sprintf("trying to replace metadata[%q] = %q with %q", key, oldValue, value))
	}
	s.metadata[key] = value
}

func (s *Scout) Report(action string, meta ...ScoutMeta) error {
	if s.Disabled() {
		return nil
	}

	// Construct the report's metadata. Include the fixed (growing) set of
	// metadata in the Scout structure and the pairs passed as arguments to this
	// call. Also include and increment the index, which can be used to
	// determine the correct order of reported events for this installation
	// attempt (correlated by the trace_id set at the start).
	s.index++
	metadata := map[string]interface{}{
		"action": action,
		"index":  s.index,
	}
	for metaKey, metaValue := range s.metadata {
		metadata[metaKey] = metaValue
	}
	for _, metaItem := range meta {
		metadata[metaItem.Key] = metaItem.Value
	}

	data := map[string]interface{}{
		"application": "edgectl",
		"install_id":  s.installID,
		"version":     Version,
		"metadata":    metadata,
	}

	body, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		panic(err)
	}
	metritonEndpoint := "https://metriton.datawire.io/scout"
	resp, err := http.Post(metritonEndpoint, "application/json", bytes.NewBuffer(body))
	if err != nil {
		return errors.Wrap(err, "scout report")
	}

	// TODO: Do something useful (?) with the response?
	_, _ = ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()

	return nil
}

func (s *Scout) Disabled() bool {
	if os.Getenv("SCOUT_DISABLE") != "" {
		return true
	}
	return false
}
<commit_msg>simpler logic<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/google/uuid"
	"github.com/pkg/errors"
)

type Scout struct {
	installID string
	index     int
	metadata  map[string]interface{}
}

type ScoutMeta struct {
	Key   string
	Value interface{}
}

func NewScout(mode string) (s *Scout) {
	// Fixed (growing) metadata passed with every report
	metadata := make(map[string]interface{})
	metadata["mode"] = mode
	metadata["trace_id"] = uuid.New().String()

	// The result
	s = &Scout{metadata: metadata}

	// Get or create the persistent install ID for Edge Control
	err := func() error {
		// We store the persistent ID in ~/.config/edgectl/id to be consistent
		// with Telepresence. We could instead use os.UserConfigDir() as the
		// root of the destination, which may be the same on Linux, but is
		// definitely different on MacOS.
		home, err := os.UserHomeDir()
		if err != nil {
			return err
		}
		configDir := filepath.Join(home, ".config", "edgectl")
		if err := os.MkdirAll(configDir, 0755); err != nil {
			return err
		}
		idFilename := filepath.Join(configDir, "id")

		// Try to read an existing install ID
		if installIDBytes, err := ioutil.ReadFile(idFilename); err == nil {
			s.installID = string(installIDBytes)
			// Validate UUID format
			if _, err := uuid.Parse(s.installID); err == nil {
				metadata["new_install"] = false
				return nil
			} // else the value is not a UUID
		} // else file doesn't exist, etc.

		// Try to create a new install ID
		s.installID = uuid.New().String()
		metadata["new_install"] = true
		if err := ioutil.WriteFile(idFilename, []byte(s.installID), 0755); err != nil {
			return err
		}
		return nil
	}()
	if err != nil {
		s.installID = "00000000-0000-0000-0000-000000000000"
		metadata["new_install"] = true
		metadata["install_id_error"] = err.Error()
	}

	return
}

func (s *Scout) SetMetadatum(key string, value interface{}) {
	oldValue, ok := s.metadata[key]
	if ok {
		panic(fmt.Sprintf("trying to replace metadata[%q] = %q with %q", key, oldValue, value))
	}
	s.metadata[key] = value
}

func (s *Scout) Report(action string, meta ...ScoutMeta) error {
	if s.Disabled() {
		return nil
	}

	// Construct the report's metadata. Include the fixed (growing) set of
	// metadata in the Scout structure and the pairs passed as arguments to this
	// call. Also include and increment the index, which can be used to
	// determine the correct order of reported events for this installation
	// attempt (correlated by the trace_id set at the start).
	s.index++
	metadata := map[string]interface{}{
		"action": action,
		"index":  s.index,
	}
	for metaKey, metaValue := range s.metadata {
		metadata[metaKey] = metaValue
	}
	for _, metaItem := range meta {
		metadata[metaItem.Key] = metaItem.Value
	}

	data := map[string]interface{}{
		"application": "edgectl",
		"install_id":  s.installID,
		"version":     Version,
		"metadata":    metadata,
	}

	body, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		panic(err)
	}
	metritonEndpoint := "https://metriton.datawire.io/scout"
	resp, err := http.Post(metritonEndpoint, "application/json", bytes.NewBuffer(body))
	if err != nil {
		return errors.Wrap(err, "scout report")
	}

	// TODO: Do something useful (?) with the response?
	_, _ = ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()

	return nil
}

func (s *Scout) Disabled() bool {
	return os.Getenv("SCOUT_DISABLE") != ""
}
<|endoftext|>


<commit_before>/*
	This file is part of go-ethereum

	go-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	go-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @authors
 * 	Jeffrey Wilcke <i@jev.io>
 */
package main

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/cmd/utils"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/state"
	"github.com/peterh/liner"
)

const (
	ClientIdentifier = "Ethereum(G)"
	Version          = "0.9.0"
)

var (
	clilogger = logger.NewLogger("CLI")
	app       = utils.NewApp(Version, "the go-ethereum command line interface")
)

func init() {
	app.Action = run
	app.HideVersion = true // we have a command to print the version
	app.Commands = []cli.Command{
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
		{
			Action: accountList,
			Name:   "account",
			Usage:  "manage accounts",
			Subcommands: []cli.Command{
				{
					Action: accountList,
					Name:   "list",
					Usage:  "print account addresses",
				},
				{
					Action: accountCreate,
					Name:   "new",
					Usage:  "create a new account",
				},
			},
		},
		{
			Action: dump,
			Name:   "dump",
			Usage:  `dump a specific block from storage`,
			Description: `
The arguments are interpreted as block numbers or hashes.
Use "ethereum dump 0" to dump the genesis block.
`,
		},
		{
			Action: runjs,
			Name:   "js",
			Usage:  `interactive JavaScript console`,
			Description: `
In the console, you can use the eth object to interact
with the running ethereum stack. The API does not match
ethereum.js.

A JavaScript file can be provided as the argument. The
runtime will execute the file and exit.
`,
		},
		{
			Action: importchain,
			Name:   "import",
			Usage:  `import a blockchain file`,
		},
		{
			Action: exportchain,
			Name:   "export",
			Usage:  `export blockchain into file`,
		},
	}
	app.Flags = []cli.Flag{
		utils.UnlockedAccountFlag,
		utils.BootnodesFlag,
		utils.DataDirFlag,
		utils.ListenPortFlag,
		utils.LogFileFlag,
		utils.LogFormatFlag,
		utils.LogLevelFlag,
		utils.MaxPeersFlag,
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
		utils.NATFlag,
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
		utils.UnencryptedKeysFlag,
		utils.VMDebugFlag,
		//utils.VMTypeFlag,
	}

	// missing:
	// flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
	// flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
	// flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")

	// potential subcommands:
	// flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
	// flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
	// flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	defer logger.Flush()
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run(ctx *cli.Context) {
	fmt.Printf("Welcome to the FRONTIER\n")
	utils.HandleInterrupt()
	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
	if err == accounts.ErrNoKeys {
		utils.Fatalf(`No accounts configured.
Please run 'ethereum account new' to create a new account.`)
	} else if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, eth)
	// this blocks the thread
	eth.WaitForShutdown()
}

func runjs(ctx *cli.Context) {
	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
	if err == accounts.ErrNoKeys {
		utils.Fatalf(`No accounts configured.
Please run 'ethereum account new' to create a new account.`)
	} else if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, eth)
	repl := newJSRE(eth)
	if len(ctx.Args()) == 0 {
		repl.interactive()
	} else {
		for _, file := range ctx.Args() {
			repl.exec(file)
		}
	}
	eth.Stop()
	eth.WaitForShutdown()
}

func startEth(ctx *cli.Context, eth *eth.Ethereum) {
	utils.StartEthereum(eth)

	// Load startup keys. XXX we are going to need a different format
	account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
	if len(account) > 0 {
		split := strings.Split(account, ":")
		if len(split) != 2 {
			utils.Fatalf("Illegal 'unlock' format (address:password)")
		}
		am := eth.AccountManager()
		// Attempt to unlock the account
		err := am.Unlock(ethutil.Hex2Bytes(split[0]), split[1])
		if err != nil {
			utils.Fatalf("Unlock account failed '%v'", err)
		}
	}
	// Start auxiliary services if enabled.
	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
		utils.StartRPC(eth, ctx)
	}
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
		eth.StartMining()
	}
}

func accountList(ctx *cli.Context) {
	am := utils.GetAccountManager(ctx)
	accts, err := am.Accounts()
	if err != nil {
		utils.Fatalf("Could not list accounts: %v", err)
	}
	for _, acct := range accts {
		fmt.Printf("Address: %#x\n", acct)
	}
}

func accountCreate(ctx *cli.Context) {
	am := utils.GetAccountManager(ctx)
	passphrase := ""
	if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
		fmt.Println("The new account will be encrypted with a passphrase.")
		fmt.Println("Please enter a passphrase now.")
		auth, err := readPassword("Passphrase: ", true)
		if err != nil {
			utils.Fatalf("%v", err)
		}
		confirm, err := readPassword("Repeat Passphrase: ", false)
		if err != nil {
			utils.Fatalf("%v", err)
		}
		if auth != confirm {
			utils.Fatalf("Passphrases did not match.")
		}
		passphrase = auth
	}
	acct, err := am.NewAccount(passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %#x\n", acct.Address)
}

func importchain(ctx *cli.Context) {
	if len(ctx.Args()) != 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chainmgr, _, _ := utils.GetChain(ctx)
	start := time.Now()
	err := utils.ImportChain(chainmgr, ctx.Args().First())
	if err != nil {
		utils.Fatalf("Import error: %v\n", err)
	}
	fmt.Printf("Import done in %v", time.Since(start))
	return
}

func exportchain(ctx *cli.Context) {
	if len(ctx.Args()) != 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chainmgr, _, _ := utils.GetChain(ctx)
	start := time.Now()
	err := utils.ExportChain(chainmgr, ctx.Args().First())
	if err != nil {
		utils.Fatalf("Export error: %v\n", err)
	}
	fmt.Printf("Export done in %v", time.Since(start))
	return
}

func dump(ctx *cli.Context) {
	chainmgr, _, stateDb := utils.GetChain(ctx)
	for _, arg := range ctx.Args() {
		var block *types.Block
		if hashish(arg) {
			block = chainmgr.GetBlock(ethutil.Hex2Bytes(arg))
		} else {
			num, _ := strconv.Atoi(arg)
			block = chainmgr.GetBlockByNumber(uint64(num))
		}
		if block == nil {
			fmt.Println("{}")
			utils.Fatalf("block not found")
		} else {
			statedb := state.New(block.Root(), stateDb)
			fmt.Printf("%s\n", statedb.Dump())
			// fmt.Println(block)
		}
	}
}

func version(c *cli.Context) {
	fmt.Printf(`%v
Version: %v
Protocol Version: %d
Network Id: %d
GO: %s
OS: %s
GOPATH=%s
GOROOT=%s
`, ClientIdentifier, Version, eth.ProtocolVersion, eth.NetworkId, runtime.Version(), runtime.GOOS, os.Getenv("GOPATH"), runtime.GOROOT())
}

// hashish returns true for strings that look like hashes.
func hashish(x string) bool {
	_, err := strconv.Atoi(x)
	return err != nil
}

func readPassword(prompt string, warnTerm bool) (string, error) {
	if liner.TerminalSupported() {
		lr := liner.NewLiner()
		defer lr.Close()
		return lr.PasswordPrompt(prompt)
	}
	if warnTerm {
		fmt.Println("!! Unsupported terminal, password will be echoed.")
	}
	fmt.Print(prompt)
	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
	fmt.Println()
	return input, err
}
<commit_msg>cmd/ethereum: remove extra check for 'no accounts' error<commit_after>/*
	This file is part of go-ethereum

	go-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	go-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @authors
 * 	Jeffrey Wilcke <i@jev.io>
 */
package main

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/ethereum/go-ethereum/cmd/utils"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/state"
	"github.com/peterh/liner"
)

const (
	ClientIdentifier = "Ethereum(G)"
	Version          = "0.9.0"
)

var (
	clilogger = logger.NewLogger("CLI")
	app       = utils.NewApp(Version, "the go-ethereum command line interface")
)

func init() {
	app.Action = run
	app.HideVersion = true // we have a command to print the version
	app.Commands = []cli.Command{
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
		{
			Action: accountList,
			Name:   "account",
			Usage:  "manage accounts",
			Subcommands: []cli.Command{
				{
					Action: accountList,
					Name:   "list",
					Usage:  "print account addresses",
				},
				{
					Action: accountCreate,
					Name:   "new",
					Usage:  "create a new account",
				},
			},
		},
		{
			Action: dump,
			Name:   "dump",
			Usage:  `dump a specific block from storage`,
			Description: `
The arguments are interpreted as block numbers or hashes.
Use "ethereum dump 0" to dump the genesis block.
`,
		},
		{
			Action: runjs,
			Name:   "js",
			Usage:  `interactive JavaScript console`,
			Description: `
In the console, you can use the eth object to interact
with the running ethereum stack. The API does not match
ethereum.js.

A JavaScript file can be provided as the argument. The
runtime will execute the file and exit.
`,
		},
		{
			Action: importchain,
			Name:   "import",
			Usage:  `import a blockchain file`,
		},
		{
			Action: exportchain,
			Name:   "export",
			Usage:  `export blockchain into file`,
		},
	}
	app.Flags = []cli.Flag{
		utils.UnlockedAccountFlag,
		utils.BootnodesFlag,
		utils.DataDirFlag,
		utils.ListenPortFlag,
		utils.LogFileFlag,
		utils.LogFormatFlag,
		utils.LogLevelFlag,
		utils.MaxPeersFlag,
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
		utils.NATFlag,
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
		utils.UnencryptedKeysFlag,
		utils.VMDebugFlag,
		//utils.VMTypeFlag,
	}

	// missing:
	// flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
	// flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
	// flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")

	// potential subcommands:
	// flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
	// flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
	// flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	defer logger.Flush()
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run(ctx *cli.Context) {
	fmt.Printf("Welcome to the FRONTIER\n")
	utils.HandleInterrupt()
	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, eth)
	// this blocks the thread
	eth.WaitForShutdown()
}

func runjs(ctx *cli.Context) {
	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, eth)
	repl := newJSRE(eth)
	if len(ctx.Args()) == 0 {
		repl.interactive()
	} else {
		for _, file := range ctx.Args() {
			repl.exec(file)
		}
	}
	eth.Stop()
	eth.WaitForShutdown()
}

func startEth(ctx *cli.Context, eth *eth.Ethereum) {
	utils.StartEthereum(eth)

	// Load startup keys. XXX we are going to need a different format
	account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
	if len(account) > 0 {
		split := strings.Split(account, ":")
		if len(split) != 2 {
			utils.Fatalf("Illegal 'unlock' format (address:password)")
		}
		am := eth.AccountManager()
		// Attempt to unlock the account
		err := am.Unlock(ethutil.Hex2Bytes(split[0]), split[1])
		if err != nil {
			utils.Fatalf("Unlock account failed '%v'", err)
		}
	}
	// Start auxiliary services if enabled.
	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
		utils.StartRPC(eth, ctx)
	}
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
		eth.StartMining()
	}
}

func accountList(ctx *cli.Context) {
	am := utils.GetAccountManager(ctx)
	accts, err := am.Accounts()
	if err != nil {
		utils.Fatalf("Could not list accounts: %v", err)
	}
	for _, acct := range accts {
		fmt.Printf("Address: %#x\n", acct)
	}
}

func accountCreate(ctx *cli.Context) {
	am := utils.GetAccountManager(ctx)
	passphrase := ""
	if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
		fmt.Println("The new account will be encrypted with a passphrase.")
		fmt.Println("Please enter a passphrase now.")
		auth, err := readPassword("Passphrase: ", true)
		if err != nil {
			utils.Fatalf("%v", err)
		}
		confirm, err := readPassword("Repeat Passphrase: ", false)
		if err != nil {
			utils.Fatalf("%v", err)
		}
		if auth != confirm {
			utils.Fatalf("Passphrases did not match.")
		}
		passphrase = auth
	}
	acct, err := am.NewAccount(passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %#x\n", acct.Address)
}

func importchain(ctx *cli.Context) {
	if len(ctx.Args()) != 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chainmgr, _, _ := utils.GetChain(ctx)
	start := time.Now()
	err := utils.ImportChain(chainmgr, ctx.Args().First())
	if err != nil {
		utils.Fatalf("Import error: %v\n", err)
	}
	fmt.Printf("Import done in %v", time.Since(start))
	return
}

func exportchain(ctx *cli.Context) {
	if len(ctx.Args()) != 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chainmgr, _, _ := utils.GetChain(ctx)
	start := time.Now()
	err := utils.ExportChain(chainmgr, ctx.Args().First())
	if err != nil {
		utils.Fatalf("Export error: %v\n", err)
	}
	fmt.Printf("Export done in %v", time.Since(start))
	return
}

func dump(ctx *cli.Context) {
	chainmgr, _, stateDb := utils.GetChain(ctx)
	for _, arg := range ctx.Args() {
		var block *types.Block
		if hashish(arg) {
			block = chainmgr.GetBlock(ethutil.Hex2Bytes(arg))
		} else {
			num, _ := strconv.Atoi(arg)
			block = chainmgr.GetBlockByNumber(uint64(num))
		}
		if block == nil {
			fmt.Println("{}")
			utils.Fatalf("block not found")
		} else {
			statedb := state.New(block.Root(), stateDb)
			fmt.Printf("%s\n", statedb.Dump())
			// fmt.Println(block)
		}
	}
}

func version(c *cli.Context) {
	fmt.Printf(`%v
Version: %v
Protocol Version: %d
Network Id: %d
GO: %s
OS: %s
GOPATH=%s
GOROOT=%s
`, ClientIdentifier, Version, eth.ProtocolVersion, eth.NetworkId, runtime.Version(), runtime.GOOS, os.Getenv("GOPATH"), runtime.GOROOT())
}

// hashish returns true for strings that look like hashes.
func hashish(x string) bool {
	_, err := strconv.Atoi(x)
	return err != nil
}

func readPassword(prompt string, warnTerm bool) (string, error) {
	if liner.TerminalSupported() {
		lr := liner.NewLiner()
		defer lr.Close()
		return lr.PasswordPrompt(prompt)
	}
	if warnTerm {
		fmt.Println("!! Unsupported terminal, password will be echoed.")
	}
	fmt.Print(prompt)
	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
	fmt.Println()
	return input, err
}
<|endoftext|>


<commit_before>package namespace

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

	"github.com/containerum/chkit/pkg/chkitErrors"

	"github.com/containerum/chkit/cmd/util"
	"github.com/containerum/chkit/pkg/model"
	"gopkg.in/urfave/cli.v2"
)

// GetNamespace -- commmand 'get' entity data
var GetNamespace = &cli.Command{
	Name:        "ns",
	Description: `show namespace or namespace list`,
	Usage:       `Shows namespace data or namespace list`,
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name: "json",
		},
	},
	Action: func(ctx *cli.Context) error {
		log := util.GetLog(ctx)
		client := util.GetClient(ctx)
		log.Debugf("get ns from %q", client.APIaddr)
		var namespaceData model.Renderer
		if ctx.NArg() > 0 {
			name := ctx.Args().First()
			ns, err := client.GetNamespace(name)
			if err != nil {
				return err
			}
			namespaceData = &ns
		} else {
			list, err := client.GetNamespaceList()
			if err != nil {
				return err
			}
			namespaceData = list
		}
		ok, flag := isSet(ctx.Args().Slice(), "json", "yaml")
		switch {
		case ok && flag.Name == "json":
			log.Debugf("rendering namespace to JSON")
			data, err := namespaceData.RenderJSON()
			if err != nil {
				return err
			}
			if flag.Value == "" {
				fmt.Println(data)
			} else {
				if err := ioutil.WriteFile(flag.Value, []byte(data), os.ModePerm); err != nil {
					return chkitErrors.NewExitCoder(err)
				}
			}
		default:
			log.Debugf("rendering namespace to table")
			fmt.Println(namespaceData.RenderTable())
		}
		return nil
	},
}

func isSet(args []string, flags ...string) (bool, *cli.StringFlag) {
	for _, flag := range flags {
		for i, arg := range args {
			if len(flag) == 1 {
				arg = strings.TrimPrefix(arg, "-")
			} else if len(flag) > 1 {
				arg = strings.TrimPrefix(arg, "--")
			}
			if arg == flag {
				value := ""
				if i+1 < len(args) {
					value = args[i+1]
				}
				return true, &cli.StringFlag{
					Name:  flag,
					Value: value,
				}
			}
		}
	}
	return false, nil
}
<commit_msg>rename package<commit_after>package clinamespace

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

	"github.com/containerum/chkit/pkg/chkitErrors"

	"github.com/containerum/chkit/cmd/util"
	"github.com/containerum/chkit/pkg/model"
	"gopkg.in/urfave/cli.v2"
)

// GetNamespace -- commmand 'get' entity data
var GetNamespace = &cli.Command{
	Name:        "ns",
	Description: `show namespace or namespace list`,
	Usage:       `Shows namespace data or namespace list`,
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name: "json",
		},
	},
	Action: func(ctx *cli.Context) error {
		log := util.GetLog(ctx)
		client := util.GetClient(ctx)
		log.Debugf("get ns from %q", client.APIaddr)
		var namespaceData model.Renderer
		if ctx.NArg() > 0 {
			name := ctx.Args().First()
			ns, err := client.GetNamespace(name)
			if err != nil {
				return err
			}
			namespaceData = &ns
		} else {
			list, err := client.GetNamespaceList()
			if err != nil {
				return err
			}
			namespaceData = list
		}
		ok, flag := isSet(ctx.Args().Slice(), "json", "yaml")
		switch {
		case ok && flag.Name == "json":
			log.Debugf("rendering namespace to JSON")
			data, err := namespaceData.RenderJSON()
			if err != nil {
				return err
			}
			if flag.Value == "" {
				fmt.Println(data)
			} else {
				if err := ioutil.WriteFile(flag.Value, []byte(data), os.ModePerm); err != nil {
					return chkitErrors.NewExitCoder(err)
				}
			}
		default:
			log.Debugf("rendering namespace to table")
			fmt.Println(namespaceData.RenderTable())
		}
		return nil
	},
}

func isSet(args []string, flags ...string) (bool, *cli.StringFlag) {
	for _, flag := range flags {
		for i, arg := range args {
			if len(flag) == 1 {
				arg = strings.TrimPrefix(arg, "-")
			} else if len(flag) > 1 {
				arg = strings.TrimPrefix(arg, "--")
			}
			if arg == flag {
				value := ""
				if i+1 < len(args) {
					value = args[i+1]
				}
				return true, &cli.StringFlag{
					Name:  flag,
					Value: value,
				}
			}
		}
	}
	return false, nil
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "log"
    "time"
    "runtime"
    "os/signal"
    "github.com/Lupino/periodic/driver"
    "github.com/Lupino/periodic/driver/redis"
    "github.com/Lupino/periodic/driver/leveldb"
    "github.com/Lupino/periodic"
    "github.com/Lupino/periodic/cmd/periodic/subcmd"
    "github.com/codegangsta/cli"
)

func main() {
    app := cli.NewApp()
    app.Name = "periodic"
    app.Usage = "Periodic task system"
    app.Version = "0.1.2"
    app.Flags = []cli.Flag {
        cli.StringFlag{
            Name: "H",
            Value: "unix:///tmp/periodic.sock",
            Usage: "the server address eg: tcp://127.0.0.1:5000",
            EnvVar: "PERIODIC_PORT",
        },
        cli.StringFlag{
            Name: "redis",
            Value: "tcp://127.0.0.1:6379",
            Usage: "The redis server address, required for driver redis",
        },
        cli.StringFlag{
            Name: "driver",
            Value: "memstore",
            Usage: "The driver [memstore, leveldb, redis]",
        },
        cli.StringFlag{
            Name: "dbpath",
            Value: "leveldb",
            Usage: "The db path, required for driver leveldb",
        },
        cli.BoolFlag{
            Name: "d",
            Usage: "Enable daemon mode",
        },
        cli.IntFlag{
            Name: "timeout",
            Value: 0,
            Usage: "The socket timeout",
        },
        cli.IntFlag{
            Name: "cpus",
            Value: runtime.NumCPU(),
            Usage: "The runtime.GOMAXPROCS",
            EnvVar: "GOMAXPROCS",
        },
    }
    app.Commands = []cli.Command{
        {
            Name: "status",
            Usage: "Show status",
            Action: func(c *cli.Context) {
                subcmd.ShowStatus(c.GlobalString("H"))
            },
        },
        {
            Name: "submit",
            Usage: "Submit job",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name",
                },
                cli.StringFlag{
                    Name: "n",
                    Value: "",
                    Usage: "job name",
                },
                cli.StringFlag{
                    Name: "args",
                    Value: "",
                    Usage: "job workload",
                },
                cli.IntFlag{
                    Name: "t",
                    Value: 0,
                    Usage: "job running timeout",
                },
                cli.IntFlag{
                    Name: "sched_later",
                    Value: 0,
                    Usage: "job sched_later",
                },
            },
            Action: func(c *cli.Context) {
                var job = driver.Job{
                    Name: c.String("n"),
                    Func: c.String("f"),
                    Args: c.String("args"),
                    Timeout: int64(c.Int("t")),
                }
                if len(job.Name) == 0 || len(job.Func) == 0 {
                    cli.ShowCommandHelp(c, "submit")
                    log.Fatal("Job name and func is require")
                }
                delay := c.Int("sched_later")
                var now = time.Now()
                job.SchedAt = int64(now.Unix()) + int64(delay)
                subcmd.SubmitJob(c.GlobalString("H"), job)
            },
        },
        {
            Name: "drop",
            Usage: "Drop func",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name",
                },
            },
            Action: func(c *cli.Context) {
                Func := c.String("f")
                if len(Func) == 0 {
                    cli.ShowCommandHelp(c, "drop")
                    log.Fatal("function name is required")
                }
                subcmd.DropFunc(c.GlobalString("H"), Func)
            },
        },
        {
            Name: "run",
            Usage: "Run func",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name required",
                },
                cli.StringFlag{
                    Name: "exec",
                    Value: "",
                    Usage: "command required",
                },
            },
            Action: func(c *cli.Context) {
                Func := c.String("f")
                exec := c.String("exec")
                if len(Func) == 0 {
                    cli.ShowCommandHelp(c, "run")
                    log.Fatal("function name is required")
                }
                if len(exec) == 0 {
                    cli.ShowCommandHelp(c, "run")
                    log.Fatal("command is required")
                }
                subcmd.Run(c.GlobalString("H"), Func, exec)
            },
        },
    }
    app.Action = func(c *cli.Context) {
        if c.Bool("d") {
            var store driver.StoreDriver
            switch c.String("driver") {
                case "memstore":
                    store = driver.NewMemStroeDriver()
                    break
                case "redis":
                    store = redis.NewRedisDriver(c.String("redis"))
                    break
                case "leveldb":
                    store = leveldb.NewLevelDBDriver(c.String("dbpath"))
                    break
                default:
                    store = driver.NewMemStroeDriver()
                    break
            }

            runtime.GOMAXPROCS(c.Int("cpus"))
            timeout := time.Duration(c.Int("timeout"))
            periodicd := periodic.NewSched(c.String("H"), store, timeout)
            go periodicd.Serve()
            s := make(chan os.Signal, 1)
            signal.Notify(s, os.Interrupt, os.Kill)
            <-s
            periodicd.Close()
        } else {
            cli.ShowAppHelp(c)
        }
    }

    app.Run(os.Args)
}
<commit_msg>Add cpuprofile<commit_after>package main

import (
    "os"
    "log"
    "time"
    "runtime"
    "os/signal"
    "github.com/Lupino/periodic/driver"
    "github.com/Lupino/periodic/driver/redis"
    "github.com/Lupino/periodic/driver/leveldb"
    "github.com/Lupino/periodic"
    "github.com/Lupino/periodic/cmd/periodic/subcmd"
    "github.com/codegangsta/cli"
    "runtime/pprof"
)

func main() {
    app := cli.NewApp()
    app.Name = "periodic"
    app.Usage = "Periodic task system"
    app.Version = "0.1.2"
    app.Flags = []cli.Flag {
        cli.StringFlag{
            Name: "H",
            Value: "unix:///tmp/periodic.sock",
            Usage: "the server address eg: tcp://127.0.0.1:5000",
            EnvVar: "PERIODIC_PORT",
        },
        cli.StringFlag{
            Name: "redis",
            Value: "tcp://127.0.0.1:6379",
            Usage: "The redis server address, required for driver redis",
        },
        cli.StringFlag{
            Name: "driver",
            Value: "memstore",
            Usage: "The driver [memstore, leveldb, redis]",
        },
        cli.StringFlag{
            Name: "dbpath",
            Value: "leveldb",
            Usage: "The db path, required for driver leveldb",
        },
        cli.BoolFlag{
            Name: "d",
            Usage: "Enable daemon mode",
        },
        cli.IntFlag{
            Name: "timeout",
            Value: 0,
            Usage: "The socket timeout",
        },
        cli.IntFlag{
            Name: "cpus",
            Value: runtime.NumCPU(),
            Usage: "The runtime.GOMAXPROCS",
            EnvVar: "GOMAXPROCS",
        },
        cli.StringFlag{
            Name: "cpuprofile",
            Value: "",
            Usage: "write cpu profile to file",
        },
    }
    app.Commands = []cli.Command{
        {
            Name: "status",
            Usage: "Show status",
            Action: func(c *cli.Context) {
                subcmd.ShowStatus(c.GlobalString("H"))
            },
        },
        {
            Name: "submit",
            Usage: "Submit job",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name",
                },
                cli.StringFlag{
                    Name: "n",
                    Value: "",
                    Usage: "job name",
                },
                cli.StringFlag{
                    Name: "args",
                    Value: "",
                    Usage: "job workload",
                },
                cli.IntFlag{
                    Name: "t",
                    Value: 0,
                    Usage: "job running timeout",
                },
                cli.IntFlag{
                    Name: "sched_later",
                    Value: 0,
                    Usage: "job sched_later",
                },
            },
            Action: func(c *cli.Context) {
                var job = driver.Job{
                    Name: c.String("n"),
                    Func: c.String("f"),
                    Args: c.String("args"),
                    Timeout: int64(c.Int("t")),
                }
                if len(job.Name) == 0 || len(job.Func) == 0 {
                    cli.ShowCommandHelp(c, "submit")
                    log.Fatal("Job name and func is require")
                }
                delay := c.Int("sched_later")
                var now = time.Now()
                job.SchedAt = int64(now.Unix()) + int64(delay)
                subcmd.SubmitJob(c.GlobalString("H"), job)
            },
        },
        {
            Name: "drop",
            Usage: "Drop func",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name",
                },
            },
            Action: func(c *cli.Context) {
                Func := c.String("f")
                if len(Func) == 0 {
                    cli.ShowCommandHelp(c, "drop")
                    log.Fatal("function name is required")
                }
                subcmd.DropFunc(c.GlobalString("H"), Func)
            },
        },
        {
            Name: "run",
            Usage: "Run func",
            Flags: []cli.Flag {
                cli.StringFlag{
                    Name: "f",
                    Value: "",
                    Usage: "function name required",
                },
                cli.StringFlag{
                    Name: "exec",
                    Value: "",
                    Usage: "command required",
                },
            },
            Action: func(c *cli.Context) {
                Func := c.String("f")
                exec := c.String("exec")
                if len(Func) == 0 {
                    cli.ShowCommandHelp(c, "run")
                    log.Fatal("function name is required")
                }
                if len(exec) == 0 {
                    cli.ShowCommandHelp(c, "run")
                    log.Fatal("command is required")
                }
                subcmd.Run(c.GlobalString("H"), Func, exec)
            },
        },
    }
    app.Action = func(c *cli.Context) {
        if c.Bool("d") {
            if c.String("cpuprofile") != "" {
                f, err := os.Create(c.String("cpuprofile"))
                if err != nil {
                    log.Fatal(err)
                }
                pprof.StartCPUProfile(f)
                defer pprof.StopCPUProfile()
            }
            var store driver.StoreDriver
            switch c.String("driver") {
                case "memstore":
                    store = driver.NewMemStroeDriver()
                    break
                case "redis":
                    store = redis.NewRedisDriver(c.String("redis"))
                    break
                case "leveldb":
                    store = leveldb.NewLevelDBDriver(c.String("dbpath"))
                    break
                default:
                    store = driver.NewMemStroeDriver()
                    break
            }

            runtime.GOMAXPROCS(c.Int("cpus"))
            timeout := time.Duration(c.Int("timeout"))
            periodicd := periodic.NewSched(c.String("H"), store, timeout)
            go periodicd.Serve()
            s := make(chan os.Signal, 1)
            signal.Notify(s, os.Interrupt, os.Kill)
            <-s
            periodicd.Close()
        } else {
            cli.ShowAppHelp(c)
        }
    }

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


<commit_before>/*
http://www.apache.org/licenses/LICENSE-2.0.txt

Copyright 2015 Intel Corporation

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 (
	"os"
	"sort"
	"time"

	"github.com/codegangsta/cli"
	"github.com/intelsdi-x/pulse/mgmt/rest/client"
)

var (
	gitversion string
	pClient    *client.Client
	timeFormat = time.RFC1123
)

func main() {

	app := cli.NewApp()
	app.Name = "pulsectl"
	app.Version = gitversion
	app.Usage = "A powerful telemetry agent framework"
	app.Flags = []cli.Flag{flURL, flSecure, flAPIVer}
	app.Commands = commands

	app.Before = func(c *cli.Context) error {
		if pClient == nil {
			pClient = client.New(c.GlobalString("url"), c.GlobalString("api-version"), c.GlobalBool("insecure"))
		}
		resp := pClient.ListAgreements()
		if resp.Err == nil {
			app.Commands = append(app.Commands, tribeCommands...)
		}
		sort.Sort(ByCommand(app.Commands))
		return nil
	}

	app.Run(os.Args)
}
<commit_msg>Fixes the detection of tribe in pulsectl<commit_after>/*
http://www.apache.org/licenses/LICENSE-2.0.txt

Copyright 2015 Intel Corporation

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 (
	"flag"
	"os"
	"sort"
	"time"

	"github.com/codegangsta/cli"
	"github.com/intelsdi-x/pulse/mgmt/rest/client"
)

var (
	gitversion string
	pClient    *client.Client
	timeFormat = time.RFC1123
)

func main() {
	app := cli.NewApp()
	app.Name = "pulsectl"
	app.Version = gitversion
	app.Usage = "A powerful telemetry agent framework"
	app.Flags = []cli.Flag{flURL, flSecure, flAPIVer}
	app.Commands = commands
	sort.Sort(ByCommand(app.Commands))
	app.Run(os.Args)
}

func init() {
	f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
	prtURL := f1.String("url", flURL.Value, flURL.Usage)
	prtU := f1.String("u", flURL.Value, flURL.Usage)
	prtAv := f1.String("api-version", flAPIVer.Value, flAPIVer.Usage)
	prtA := f1.String("a", flAPIVer.Value, flAPIVer.Usage)
	prti := f1.Bool("insecure", false, flSecure.Usage)

	url := flURL.Value
	ver := flAPIVer.Value
	secure := false

	for idx, a := range os.Args {
		switch a {
		case "--url":
			if err := f1.Parse(os.Args[idx : idx+2]); err == nil {
				url = *prtURL
			}
		case "--u":
			if err := f1.Parse(os.Args[idx : idx+2]); err == nil {
				url = *prtU
			}
		case "--api-version":
			if err := f1.Parse(os.Args[idx : idx+2]); err == nil {
				ver = *prtAv
			}
		case "--a":
			if err := f1.Parse(os.Args[idx : idx+2]); err == nil {
				ver = *prtA
			}
		case "--insecure":
			if err := f1.Parse(os.Args[idx:]); err == nil {
				secure = *prti
			}
		}
	}
	pClient = client.New(url, ver, secure)
	resp := pClient.ListAgreements()
	if resp.Err == nil {
		commands = append(commands, tribeCommands...)
	}

}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"

	"time"

	"github.com/coreos/etcdlabs/pkg/metrics"
	"github.com/spf13/cobra"
)

var rootCommand = &cobra.Command{
	Use:        "reporter",
	Short:      "reporter is etcd functional-tester reporter.",
	SuggestFor: []string{"etcd-tester-reportr", "etcdtesterreporter"},
}

func init() {
	cobra.EnablePrefixMatching = true
}

var metricsName string
var metricsEndpoint string

var dbHost string
var dbPort int
var dbUser string
var dbPassword string

var syncInterval time.Duration

func init() {
	rootCommand.PersistentFlags().StringVar(&metricsName, "metrics-name", "", "metrics name")
	rootCommand.PersistentFlags().StringVar(&metricsEndpoint, "metrics-endpoint", "", "metrics endpoint")

	rootCommand.PersistentFlags().StringVar(&dbHost, "db-host", "", "database host")
	rootCommand.PersistentFlags().IntVar(&dbPort, "db-port", 3306, "database port")
	rootCommand.PersistentFlags().StringVar(&dbUser, "db-user", "root", "database user")
	rootCommand.PersistentFlags().StringVar(&dbPassword, "db-password", "", "database password")

	syncCommand.PersistentFlags().DurationVarP(&syncInterval, "sync-interval", "i", time.Duration(0), "interval to run sync")

	rootCommand.AddCommand(pingCommand)
	rootCommand.AddCommand(syncCommand)
}

func main() {
	if err := rootCommand.Execute(); err != nil {
		fmt.Fprintln(os.Stdout, err)
		os.Exit(1)
	}
}

var pingCommand = &cobra.Command{
	Use:   "ping",
	Short: "ping ping etcd functional-tester and database.",
	RunE:  pingCommandFunc,
}

var syncCommand = &cobra.Command{
	Use:   "sync",
	Short: "sync syncs etcd functional-tester to the database.",
	RunE:  syncCommandFunc,
}

func pingCommandFunc(cmd *cobra.Command, args []string) error {
	if len(metricsEndpoint) < 3 {
		return fmt.Errorf("got empty metrics endpoint %q", metricsEndpoint)
	}
	if dbHost == "" {
		return fmt.Errorf("got empty db host %q", dbHost)
	}
	if dbPort == 0 {
		return fmt.Errorf("got 0 db port")
	}
	if dbUser == "" {
		return fmt.Errorf("got empty db user %q", dbUser)
	}

	mt := metrics.New(metricsName, metricsEndpoint, dbHost, dbPort, dbUser, dbPassword)
	mt.Ping()
	return nil
}

func syncCommandFunc(cmd *cobra.Command, args []string) error {
	if len(metricsEndpoint) < 3 {
		return fmt.Errorf("got empty metrics endpoint %q", metricsEndpoint)
	}
	if dbHost == "" {
		return fmt.Errorf("got empty db host %q", dbHost)
	}
	if dbPort == 0 {
		return fmt.Errorf("got 0 db port")
	}
	if dbUser == "" {
		return fmt.Errorf("got empty db user %q", dbUser)
	}

	mt := metrics.New(metricsName, metricsEndpoint, dbHost, dbPort, dbUser, dbPassword)

	for {
		if err := mt.Sync(); err != nil {
			return err
		}
		if syncInterval < time.Duration(1) {
			fmt.Println("sync done!")
			break
		}
		fmt.Println("sleeping", syncInterval)
		time.Sleep(syncInterval)
	}
	return nil
}
<commit_msg>cmd/reporter: clean up<commit_after>// Copyright 2016 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"os"

	"time"

	"github.com/coreos/etcdlabs/pkg/metrics"
	"github.com/spf13/cobra"
)

func init() {
	cobra.EnablePrefixMatching = true
}

func main() {
	if err := rootCommand.Execute(); err != nil {
		fmt.Fprintln(os.Stdout, err)
		os.Exit(1)
	}
}

var metricsName string
var metricsEndpoint string

var dbHost string
var dbPort int
var dbUser string
var dbPassword string

var syncInterval time.Duration

var rootCommand = &cobra.Command{
	Use:        "reporter",
	Short:      "reporter is etcd functional-tester reporter.",
	SuggestFor: []string{"etcd-tester-reportr", "etcdtesterreporter"},
}

func init() {
	rootCommand.PersistentFlags().StringVar(&metricsName, "metrics-name", "", "metrics name")
	rootCommand.PersistentFlags().StringVar(&metricsEndpoint, "metrics-endpoint", "", "metrics endpoint")

	rootCommand.PersistentFlags().StringVar(&dbHost, "db-host", "", "database host")
	rootCommand.PersistentFlags().IntVar(&dbPort, "db-port", 3306, "database port")
	rootCommand.PersistentFlags().StringVar(&dbUser, "db-user", "root", "database user")
	rootCommand.PersistentFlags().StringVar(&dbPassword, "db-password", "", "database password")

	syncCommand.PersistentFlags().DurationVarP(&syncInterval, "sync-interval", "i", time.Duration(0), "interval to run sync")

	rootCommand.AddCommand(pingCommand)
	rootCommand.AddCommand(syncCommand)
}

var pingCommand = &cobra.Command{
	Use:   "ping",
	Short: "ping ping etcd functional-tester and database.",
	RunE:  pingCommandFunc,
}

func pingCommandFunc(cmd *cobra.Command, args []string) error {
	if len(metricsEndpoint) < 3 {
		return fmt.Errorf("got empty metrics endpoint %q", metricsEndpoint)
	}
	if dbHost == "" {
		return fmt.Errorf("got empty db host %q", dbHost)
	}
	if dbPort == 0 {
		return fmt.Errorf("got 0 db port")
	}
	if dbUser == "" {
		return fmt.Errorf("got empty db user %q", dbUser)
	}

	mt := metrics.New(metricsName, metricsEndpoint, dbHost, dbPort, dbUser, dbPassword)
	mt.Ping()
	return nil
}

var syncCommand = &cobra.Command{
	Use:   "sync",
	Short: "sync syncs etcd functional-tester to the database.",
	RunE:  syncCommandFunc,
}

func syncCommandFunc(cmd *cobra.Command, args []string) error {
	if len(metricsEndpoint) < 3 {
		return fmt.Errorf("got empty metrics endpoint %q", metricsEndpoint)
	}
	if dbHost == "" {
		return fmt.Errorf("got empty db host %q", dbHost)
	}
	if dbPort == 0 {
		return fmt.Errorf("got 0 db port")
	}
	if dbUser == "" {
		return fmt.Errorf("got empty db user %q", dbUser)
	}

	mt := metrics.New(metricsName, metricsEndpoint, dbHost, dbPort, dbUser, dbPassword)

	for {
		if err := mt.Sync(); err != nil {
			return err
		}
		if syncInterval < time.Duration(1) {
			fmt.Println("sync done!")
			break
		}
		fmt.Println("sleeping", syncInterval)
		time.Sleep(syncInterval)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"

	"github.com/spf13/cobra"

	"github.com/restic/restic/internal/errors"
	"github.com/restic/restic/internal/restic"
	"github.com/restic/restic/internal/walker"
)

var cmdLs = &cobra.Command{
	Use:   "ls [flags] [snapshot-ID ...]",
	Short: "List files in a snapshot",
	Long: `
The "ls" command allows listing files and directories in a snapshot.

The special snapshot-ID "latest" can be used to list files and directories of the latest snapshot in the repository.
`,
	DisableAutoGenTag: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		return runLs(lsOptions, globalOptions, args)
	},
}

// LsOptions collects all options for the ls command.
type LsOptions struct {
	ListLong bool
	Host     string
	Tags     restic.TagLists
	Paths    []string
}

var lsOptions LsOptions

func init() {
	cmdRoot.AddCommand(cmdLs)

	flags := cmdLs.Flags()
	flags.BoolVarP(&lsOptions.ListLong, "long", "l", false, "use a long listing format showing size and mode")

	flags.StringVarP(&lsOptions.Host, "host", "H", "", "only consider snapshots for this `host`, when no snapshot ID is given")
	flags.Var(&lsOptions.Tags, "tag", "only consider snapshots which include this `taglist`, when no snapshot ID is given")
	flags.StringArrayVar(&lsOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given")
}

func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
	if len(args) == 0 && opts.Host == "" && len(opts.Tags) == 0 && len(opts.Paths) == 0 {
		return errors.Fatal("Invalid arguments, either give one or more snapshot IDs or set filters.")
	}

	repo, err := OpenRepository(gopts)
	if err != nil {
		return err
	}

	if err = repo.LoadIndex(gopts.ctx); err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(gopts.ctx)
	defer cancel()
	for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args) {
		Verbosef("snapshot %s of %v at %s):\n", sn.ID().Str(), sn.Paths, sn.Time)

		err := walker.Walk(ctx, repo, *sn.Tree, nil, func(nodepath string, node *restic.Node, err error) (bool, error) {
			if err != nil {
				return false, err
			}

			if node == nil {
				return false, nil
			}
			Printf("%s\n", formatNode(nodepath, node, lsOptions.ListLong))
			return false, nil
		})
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>ls: Implement directory filter, optionally subfolders<commit_after>package main

import (
	"context"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"

	"github.com/restic/restic/internal/errors"
	"github.com/restic/restic/internal/restic"
	"github.com/restic/restic/internal/walker"
)

var cmdLs = &cobra.Command{
	Use:   "ls [flags] [snapshot-ID] [dir...]",
	Short: "List files in a snapshot",
	Long: `
The "ls" command allows listing files and directories in a snapshot.

The special snapshot-ID "latest" can be used to list files and directories of the latest snapshot in the repository.
`,
	DisableAutoGenTag: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		return runLs(lsOptions, globalOptions, args)
	},
}

// LsOptions collects all options for the ls command.
type LsOptions struct {
	ListLong  bool
	Host      string
	Tags      restic.TagLists
	Paths     []string
	Recursive bool
}

var lsOptions LsOptions

func init() {
	cmdRoot.AddCommand(cmdLs)

	flags := cmdLs.Flags()
	flags.BoolVarP(&lsOptions.ListLong, "long", "l", false, "use a long listing format showing size and mode")

	flags.StringVarP(&lsOptions.Host, "host", "H", "", "only consider snapshots for this `host`, when no snapshot ID is given")
	flags.Var(&lsOptions.Tags, "tag", "only consider snapshots which include this `taglist`, when no snapshot ID is given")
	flags.StringArrayVar(&lsOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given")
	flags.BoolVar(&lsOptions.Recursive, "recursive", false, "include files in subfolders of the listed directories")
}

func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
	if len(args) == 0 && opts.Host == "" && len(opts.Tags) == 0 && len(opts.Paths) == 0 {
		return errors.Fatal("Invalid arguments, either give one or more snapshot IDs or set filters.")
	}

	repo, err := OpenRepository(gopts)
	if err != nil {
		return err
	}

	if err = repo.LoadIndex(gopts.ctx); err != nil {
		return err
	}

	// extract any specific directories to walk
	dirs := args[1:]

	ctx, cancel := context.WithCancel(gopts.ctx)
	defer cancel()
	for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args[:1]) {
		Verbosef("snapshot %s of %v at %s):\n", sn.ID().Str(), sn.Paths, sn.Time)

		err := walker.Walk(ctx, repo, *sn.Tree, nil, func(nodepath string, node *restic.Node, err error) (bool, error) {
			if err != nil {
				return false, err
			}
			if node == nil {
				return false, nil
			}

			// apply any directory filters
			if len(dirs) > 0 {
				var nodeDir string
				if !opts.Recursive {
					// only needed for exact directory match; i.e. no subfolders
					nodeDir = filepath.Dir(nodepath)
				}
				var match bool
				for _, dir := range dirs {
					if opts.Recursive {
						if strings.HasPrefix(nodepath, dir) {
							match = true
							break
						}
					} else {
						if nodeDir == dir {
							match = true
							break
						}
					}
				}
				if !match {
					return true, nil
				}
			}

			Printf("%s\n", formatNode(nodepath, node, lsOptions.ListLong))
			return false, nil
		})
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"math/rand"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/go-kit/kit/metrics"
	"github.com/relab/raft/commonpb"
	"github.com/relab/rkv/rkvpb"
	"google.golang.org/grpc"
)

type client struct {
	l             *uint64
	currentLeader uint64
	servers       []rkvpb.RKVClient

	inFlight int64

	id  uint64
	seq uint64

	zipf *rand.Zipf

	s *stats
}

func newClient(leader *uint64, servers []string, zipf *rand.Zipf, s *stats) (*client, error) {
	conns := make([]rkvpb.RKVClient, len(servers))

	for i, server := range servers {
		cc, err := grpc.Dial(server, grpc.WithBlock(), grpc.WithInsecure())

		if err != nil {
			return nil, err
		}

		conns[i] = rkvpb.NewRKVClient(cc)
	}

	c := &client{
		l:       leader,
		servers: conns,
		zipf:    zipf,
		s:       s,
	}

	res, err := c.register()

	if err != nil {
		return nil, err
	}

	c.id = res.ClientID
	c.seq = 1

	return c, nil
}

const (
	retryPerServer = 10
	sleepPerRound  = 250 * time.Millisecond
	requestTimeout = 10 * time.Minute
	maxInFlight    = 15000
)

// ErrMaxInFlightReached indicates that there are too many messages in-flight.
var ErrMaxInFlightReached = errors.New("reached max in-flight")

func sleep(round int) {
	dur := sleepPerRound * time.Duration(round)
	time.Sleep(dur)
}

func (c *client) addServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfAdd)
}

func (c *client) removeServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfRemove)
}

func (c *client) reconf(serverID uint64, reconfType commonpb.ReconfType) (*commonpb.ReconfResponse, error) {
	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *commonpb.ReconfResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Reconf(ctx, &commonpb.ReconfRequest{
			ServerID:   serverID,
			ReconfType: reconfType,
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		break
	}

	return res, err
}

func (c *client) register() (*rkvpb.RegisterResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.RegisterResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Register(ctx, &rkvpb.RegisterRequest{})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		break
	}

	return res, err
}

func (c *client) lookup() (*rkvpb.LookupResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.readReqs.Add(1)
	timer := metrics.NewTimer(c.s.readLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.LookupResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Lookup(ctx, &rkvpb.LookupRequest{
			Key: strconv.FormatUint(c.zipf.Uint64(), 10),
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.reads.Add(1)
		timer.ObserveDuration()
		break

	}

	return res, err
}

func (c *client) insert() (*rkvpb.InsertResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.InsertResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Insert(ctx, &rkvpb.InsertRequest{
			ClientID:  c.id,
			ClientSeq: atomic.AddUint64(&c.seq, 1),
			Key:       strconv.FormatUint(c.zipf.Uint64(), 10),
			Value:     strconv.FormatUint(c.zipf.Uint64(), 10),
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		break
	}

	return res, err
}

func (c *client) leader() rkvpb.RKVClient {
	return c.servers[c.getLeader()]
}

func (c *client) nextLeader() {
	newLeader := (c.currentLeader + 1) % uint64(len(c.servers))
	atomic.CompareAndSwapUint64(c.l, c.currentLeader, newLeader)
}

func (c *client) getLeader() uint64 {
	c.currentLeader = atomic.LoadUint64(c.l)
	return c.currentLeader
}
<commit_msg>rkvctl: Fix data race on zipf<commit_after>package main

import (
	"context"
	"errors"
	"math/rand"
	"strconv"
	"sync"
	"sync/atomic"
	"time"

	"github.com/go-kit/kit/metrics"
	"github.com/relab/raft/commonpb"
	"github.com/relab/rkv/rkvpb"
	"google.golang.org/grpc"
)

type client struct {
	l             *uint64
	currentLeader uint64
	servers       []rkvpb.RKVClient

	inFlight int64

	id  uint64
	seq uint64

	zipf *z

	s *stats
}

// z wraps rand.Zipf with a mutex.
type z struct {
	sync.Mutex
	*rand.Zipf
}

func (zz *z) Uint64() uint64 {
	zz.Lock()
	i := zz.Zipf.Uint64()
	zz.Unlock()
	return i
}

func newClient(leader *uint64, servers []string, zipf *rand.Zipf, s *stats) (*client, error) {
	conns := make([]rkvpb.RKVClient, len(servers))

	for i, server := range servers {
		cc, err := grpc.Dial(server, grpc.WithBlock(), grpc.WithInsecure())

		if err != nil {
			return nil, err
		}

		conns[i] = rkvpb.NewRKVClient(cc)
	}

	c := &client{
		l:       leader,
		servers: conns,
		zipf:    &z{Zipf: zipf},
		s:       s,
	}

	res, err := c.register()

	if err != nil {
		return nil, err
	}

	c.id = res.ClientID
	c.seq = 1

	return c, nil
}

const (
	retryPerServer = 10
	sleepPerRound  = 250 * time.Millisecond
	requestTimeout = 10 * time.Minute
	maxInFlight    = 15000
)

// ErrMaxInFlightReached indicates that there are too many messages in-flight.
var ErrMaxInFlightReached = errors.New("reached max in-flight")

func sleep(round int) {
	dur := sleepPerRound * time.Duration(round)
	time.Sleep(dur)
}

func (c *client) addServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfAdd)
}

func (c *client) removeServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfRemove)
}

func (c *client) reconf(serverID uint64, reconfType commonpb.ReconfType) (*commonpb.ReconfResponse, error) {
	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *commonpb.ReconfResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Reconf(ctx, &commonpb.ReconfRequest{
			ServerID:   serverID,
			ReconfType: reconfType,
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		break
	}

	return res, err
}

func (c *client) register() (*rkvpb.RegisterResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.RegisterResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Register(ctx, &rkvpb.RegisterRequest{})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		break
	}

	return res, err
}

func (c *client) lookup() (*rkvpb.LookupResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.readReqs.Add(1)
	timer := metrics.NewTimer(c.s.readLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.LookupResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Lookup(ctx, &rkvpb.LookupRequest{
			Key: strconv.FormatUint(c.zipf.Uint64(), 10),
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.reads.Add(1)
		timer.ObserveDuration()
		break

	}

	return res, err
}

func (c *client) insert() (*rkvpb.InsertResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.InsertResponse
	var err error

	for i := 0; i < retryPerServer*len(c.servers); i++ {
		if i%len(c.servers) == 0 {
			sleep(i / len(c.servers))
		}

		res, err = c.leader().Insert(ctx, &rkvpb.InsertRequest{
			ClientID:  c.id,
			ClientSeq: atomic.AddUint64(&c.seq, 1),
			Key:       strconv.FormatUint(c.zipf.Uint64(), 10),
			Value:     strconv.FormatUint(c.zipf.Uint64(), 10),
		})

		if err != nil {
			c.nextLeader()
			continue
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		break
	}

	return res, err
}

func (c *client) leader() rkvpb.RKVClient {
	return c.servers[c.getLeader()]
}

func (c *client) nextLeader() {
	newLeader := (c.currentLeader + 1) % uint64(len(c.servers))
	atomic.CompareAndSwapUint64(c.l, c.currentLeader, newLeader)
}

func (c *client) getLeader() uint64 {
	c.currentLeader = atomic.LoadUint64(c.l)
	return c.currentLeader
}
<|endoftext|>


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

// The stress utility is intended for catching of episodic failures.
// It runs a given process in parallel in a loop and collects any failures.
// Usage:
// 	$ stress ./fmt.test -test.run=TestSometing -test.cpu=10
// You can also specify a number of parallel processes with -p flag;
// instruct the utility to not kill hanged processes for gdb attach;
// or specify the failure output you are looking for (if you want to
// ignore some other episodic failures).
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"syscall"
	"time"
)

var (
	flagP       = flag.Int("p", runtime.NumCPU(), "run `N` processes in parallel")
	flagTimeout = flag.Duration("timeout", 10*time.Minute, "timeout each process after `duration`")
	flagKill    = flag.Bool("kill", true, "kill timed out processes if true, otherwise just print pid (to attach with gdb)")
	flagFailure = flag.String("failure", "", "fail only if output matches `regexp`")
)

func main() {
	flag.Parse()
	if *flagP <= 0 || *flagTimeout <= 0 || len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(1)
	}
	var failureRe *regexp.Regexp
	if *flagFailure != "" {
		var err error
		if failureRe, err = regexp.Compile(*flagFailure); err != nil {
			fmt.Println("bad failure regexp:", err)
			os.Exit(1)
		}
	}
	res := make(chan []byte)
	for i := 0; i < *flagP; i++ {
		go func() {
			for {
				cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
				done := make(chan bool)
				if *flagTimeout > 0 {
					go func() {
						select {
						case <-done:
							return
						case <-time.After(*flagTimeout):
						}
						if !*flagKill {
							fmt.Printf("process %v timed out\n", cmd.Process.Pid)
							return
						}
						cmd.Process.Signal(syscall.SIGABRT)
						select {
						case <-done:
							return
						case <-time.After(10 * time.Second):
						}
						cmd.Process.Kill()
					}()
				}
				out, err := cmd.CombinedOutput()
				close(done)
				if err != nil && (failureRe == nil || failureRe.Match(out)) {
					out = append(out, fmt.Sprintf("\n\nERROR: %v\n", err)...)
				} else {
					out = []byte{}
				}
				res <- out
			}
		}()
	}
	runs, fails := 0, 0
	ticker := time.NewTicker(5 * time.Second).C
	for {
		select {
		case out := <-res:
			runs++
			if len(out) == 0 {
				continue
			}
			fails++
			f, err := ioutil.TempFile("", "go-stress")
			if err != nil {
				fmt.Printf("failed to create temp file: %v\n", err)
				os.Exit(1)
			}
			f.Write(out)
			f.Close()
			if len(out) > 2<<10 {
				out = out[:2<<10]
			}
			fmt.Printf("\n%s\n%s\n", f.Name(), out)
		case <-ticker:
			fmt.Printf("%v runs so far, %v failures\n", runs, fails)
		}
	}
}
<commit_msg>cmd/stress: add "-ignore regexp" flag<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The stress utility is intended for catching of episodic failures.
// It runs a given process in parallel in a loop and collects any failures.
// Usage:
// 	$ stress ./fmt.test -test.run=TestSometing -test.cpu=10
// You can also specify a number of parallel processes with -p flag;
// instruct the utility to not kill hanged processes for gdb attach;
// or specify the failure output you are looking for (if you want to
// ignore some other episodic failures).
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"syscall"
	"time"
)

var (
	flagP       = flag.Int("p", runtime.NumCPU(), "run `N` processes in parallel")
	flagTimeout = flag.Duration("timeout", 10*time.Minute, "timeout each process after `duration`")
	flagKill    = flag.Bool("kill", true, "kill timed out processes if true, otherwise just print pid (to attach with gdb)")
	flagFailure = flag.String("failure", "", "fail only if output matches `regexp`")
	flagIgnore  = flag.String("ignore", "", "ignore failure if output matches `regexp`")
)

func main() {
	flag.Parse()
	if *flagP <= 0 || *flagTimeout <= 0 || len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(1)
	}
	var failureRe, ignoreRe *regexp.Regexp
	if *flagFailure != "" {
		var err error
		if failureRe, err = regexp.Compile(*flagFailure); err != nil {
			fmt.Println("bad failure regexp:", err)
			os.Exit(1)
		}
	}
	if *flagIgnore != "" {
		var err error
		if ignoreRe, err = regexp.Compile(*flagIgnore); err != nil {
			fmt.Println("bad ignore regexp:", err)
			os.Exit(1)
		}
	}
	res := make(chan []byte)
	for i := 0; i < *flagP; i++ {
		go func() {
			for {
				cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
				done := make(chan bool)
				if *flagTimeout > 0 {
					go func() {
						select {
						case <-done:
							return
						case <-time.After(*flagTimeout):
						}
						if !*flagKill {
							fmt.Printf("process %v timed out\n", cmd.Process.Pid)
							return
						}
						cmd.Process.Signal(syscall.SIGABRT)
						select {
						case <-done:
							return
						case <-time.After(10 * time.Second):
						}
						cmd.Process.Kill()
					}()
				}
				out, err := cmd.CombinedOutput()
				close(done)
				if err != nil && (failureRe == nil || failureRe.Match(out)) && (ignoreRe == nil || !ignoreRe.Match(out)) {
					out = append(out, fmt.Sprintf("\n\nERROR: %v\n", err)...)
				} else {
					out = []byte{}
				}
				res <- out
			}
		}()
	}
	runs, fails := 0, 0
	ticker := time.NewTicker(5 * time.Second).C
	for {
		select {
		case out := <-res:
			runs++
			if len(out) == 0 {
				continue
			}
			fails++
			f, err := ioutil.TempFile("", "go-stress")
			if err != nil {
				fmt.Printf("failed to create temp file: %v\n", err)
				os.Exit(1)
			}
			f.Write(out)
			f.Close()
			if len(out) > 2<<10 {
				out = out[:2<<10]
			}
			fmt.Printf("\n%s\n%s\n", f.Name(), out)
		case <-ticker:
			fmt.Printf("%v runs so far, %v failures\n", runs, fails)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The Upspin 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

// This file contains the implementation of the keygen command.

import (
	"encoding/binary"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"upspin.io/errors"
	"upspin.io/key/proquint"
	"upspin.io/pack/ee"
)

func (s *State) keygen(args ...string) {
	const help = `
Keygen creates a new Upspin key pair and stores the pair in local
files secret.upspinkey and public.upspinkey in $HOME/.ssh. Existing
key pairs are appended to $HOME/.ssh/secret2.upspinkey. Keygen does
not update the information in the key server; use the user -put
command for that.

New users should instead use the signup command to create their
first key. Keygen can be used to create new keys.

See the description for rotate for information about updating keys.
`
	fs := flag.NewFlagSet("keygen", flag.ExitOnError)
	curveName := fs.String("curve", "p256", "cryptographic curve `name`: p256, p384, or p521")
	secret := fs.String("secretseed", "", "128 bit secret `seed` in proquint format")
	where := fs.String("where", filepath.Join(os.Getenv("HOME"), ".ssh"), "`directory` to store keys")
	s.parseFlags(fs, args, help, "keygen [-curve=256] [-secret=seed] [-where=$HOME/.ssh]")
	if fs.NArg() != 0 {
		fs.Usage()
	}
	switch *curveName {
	case "p256", "p384", "p521":
		// ok
	default:
		log.Printf("no such curve %q", *curveName)
		fs.Usage()
	}

	public, private, proquintStr, err := createKeys(*curveName, *secret)
	if err != nil {
		s.exitf("creating keys: %v", err)
	}

	if *where == "" {
		s.exitf("-where must not be empty")
	}
	err = saveKeys(*where)
	if err != nil {
		s.exitf("saving previous keys failed(%v); keys not generated", err)
	}
	err = writeKeys(*where, public, private)
	if err != nil {
		s.exitf("writing keys: %v", err)
	}
	fmt.Println("Upspin private/public key pair written to:")
	fmt.Printf("\t%s\n", filepath.Join(*where, "public.upspinkey"))
	fmt.Printf("\t%s\n", filepath.Join(*where, "secret.upspinkey"))
	fmt.Println("This key pair provides access to your Upspin identity and data.")
	if proquintStr != "" {
		fmt.Println("If you lose the keys you can re-create them by running this command:")
		fmt.Printf("\tupspin keygen -secretseed %s\n", proquintStr)
		fmt.Println("Write this command down and store it in a secure, private place.")
		fmt.Println("Do not share your private key or this command with anyone.")
	} else {
		fmt.Println("Do not share your private key with anyone.")
	}
	fmt.Println()
}

func createKeys(curveName, secret string) (public string, private, proquintStr string, err error) {
	// Pick secret 128 bits.
	// TODO(ehg)  Consider whether we are willing to ask users to write long seeds for P521.
	b := make([]byte, 16)
	if len(secret) > 0 {
		if len((secret)) != 47 || (secret)[5] != '-' {
			log.Printf("expected secret like\n lusab-babad-gutih-tugad.gutuk-bisog-mudof-sakat\n"+
				"not\n %s\nkey not generated", secret)
			return "", "", "", errors.E("keygen", errors.Invalid, errors.Str("bad format for secret"))
		}
		for i := 0; i < 8; i++ {
			binary.BigEndian.PutUint16(b[2*i:2*i+2], proquint.Decode([]byte((secret)[6*i:6*i+5])))
		}
	} else {
		ee.GenEntropy(b)
		proquints := make([]interface{}, 8)
		for i := 0; i < 8; i++ {
			proquints[i] = proquint.Encode(binary.BigEndian.Uint16(b[2*i : 2*i+2]))
		}
		proquintStr = fmt.Sprintf("%s-%s-%s-%s.%s-%s-%s-%s", proquints...)
		// Ignore punctuation on input;  this format is just to help the user keep their place.
	}

	pub, priv, err := ee.CreateKeys(curveName, b)
	if err != nil {
		return "", "", "", err
	}
	return string(pub), priv, proquintStr, nil
}

func writeKeys(where, publicKey, privateKey string) error {
	const create = os.O_RDWR | os.O_CREATE | os.O_TRUNC
	// Save the keys to files.
	fdPrivate, err := os.OpenFile(filepath.Join(where, "secret.upspinkey"), create, 0400)
	if err != nil {
		return err
	}
	fdPublic, err := os.OpenFile(filepath.Join(where, "public.upspinkey"), create, 0400)
	if err != nil {
		return err
	}

	fdPrivate.WriteString(privateKey)
	fdPublic.WriteString(string(publicKey))

	err = fdPrivate.Close()
	if err != nil {
		return err
	}
	err = fdPublic.Close()
	if err != nil {
		return err
	}
	return nil
}

func saveKeys(where string) error {
	private, err := os.Open(filepath.Join(where, "secret.upspinkey"))
	if os.IsNotExist(err) {
		return nil // There is nothing we need to save.
	}
	priv, err := ioutil.ReadAll(private)
	if err != nil {
		return err
	}
	public, err := os.Open(filepath.Join(where, "public.upspinkey"))
	if err != nil {
		return err // Halt. Existing files are corrupted and need manual attention.
	}
	pub, err := ioutil.ReadAll(public)
	if err != nil {
		return err
	}
	archive, err := os.OpenFile(filepath.Join(where, "secret2.upspinkey"),
		os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
	if err != nil {
		return err // We don't have permission to archive old keys?
	}
	_, err = archive.Write([]byte("# EE \n")) // TODO(ehg) add file date
	if err != nil {
		return err
	}
	_, err = archive.Write(pub)
	if err != nil {
		return err
	}
	_, err = archive.Write(priv)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>cmd/upspin: fix the usage.<commit_after>// Copyright 2016 The Upspin 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

// This file contains the implementation of the keygen command.

import (
	"encoding/binary"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"upspin.io/errors"
	"upspin.io/key/proquint"
	"upspin.io/pack/ee"
)

func (s *State) keygen(args ...string) {
	const help = `
Keygen creates a new Upspin key pair and stores the pair in local
files secret.upspinkey and public.upspinkey in $HOME/.ssh. Existing
key pairs are appended to $HOME/.ssh/secret2.upspinkey. Keygen does
not update the information in the key server; use the user -put
command for that.

New users should instead use the signup command to create their
first key. Keygen can be used to create new keys.

See the description for rotate for information about updating keys.
`
	fs := flag.NewFlagSet("keygen", flag.ExitOnError)
	curveName := fs.String("curve", "p256", "cryptographic curve `name`: p256, p384, or p521")
	secret := fs.String("secretseed", "", "128 bit secret `seed` in proquint format")
	where := fs.String("where", filepath.Join(os.Getenv("HOME"), ".ssh"), "`directory` to store keys")
	s.parseFlags(fs, args, help, "keygen [-curve=256] [-secretseed=seed] [-where=$HOME/.ssh]")
	if fs.NArg() != 0 {
		fs.Usage()
	}
	switch *curveName {
	case "p256", "p384", "p521":
		// ok
	default:
		log.Printf("no such curve %q", *curveName)
		fs.Usage()
	}

	public, private, proquintStr, err := createKeys(*curveName, *secret)
	if err != nil {
		s.exitf("creating keys: %v", err)
	}

	if *where == "" {
		s.exitf("-where must not be empty")
	}
	err = saveKeys(*where)
	if err != nil {
		s.exitf("saving previous keys failed(%v); keys not generated", err)
	}
	err = writeKeys(*where, public, private)
	if err != nil {
		s.exitf("writing keys: %v", err)
	}
	fmt.Println("Upspin private/public key pair written to:")
	fmt.Printf("\t%s\n", filepath.Join(*where, "public.upspinkey"))
	fmt.Printf("\t%s\n", filepath.Join(*where, "secret.upspinkey"))
	fmt.Println("This key pair provides access to your Upspin identity and data.")
	if proquintStr != "" {
		fmt.Println("If you lose the keys you can re-create them by running this command:")
		fmt.Printf("\tupspin keygen -secretseed %s\n", proquintStr)
		fmt.Println("Write this command down and store it in a secure, private place.")
		fmt.Println("Do not share your private key or this command with anyone.")
	} else {
		fmt.Println("Do not share your private key with anyone.")
	}
	fmt.Println()
}

func createKeys(curveName, secret string) (public string, private, proquintStr string, err error) {
	// Pick secret 128 bits.
	// TODO(ehg)  Consider whether we are willing to ask users to write long seeds for P521.
	b := make([]byte, 16)
	if len(secret) > 0 {
		if len((secret)) != 47 || (secret)[5] != '-' {
			log.Printf("expected secret like\n lusab-babad-gutih-tugad.gutuk-bisog-mudof-sakat\n"+
				"not\n %s\nkey not generated", secret)
			return "", "", "", errors.E("keygen", errors.Invalid, errors.Str("bad format for secret"))
		}
		for i := 0; i < 8; i++ {
			binary.BigEndian.PutUint16(b[2*i:2*i+2], proquint.Decode([]byte((secret)[6*i:6*i+5])))
		}
	} else {
		ee.GenEntropy(b)
		proquints := make([]interface{}, 8)
		for i := 0; i < 8; i++ {
			proquints[i] = proquint.Encode(binary.BigEndian.Uint16(b[2*i : 2*i+2]))
		}
		proquintStr = fmt.Sprintf("%s-%s-%s-%s.%s-%s-%s-%s", proquints...)
		// Ignore punctuation on input;  this format is just to help the user keep their place.
	}

	pub, priv, err := ee.CreateKeys(curveName, b)
	if err != nil {
		return "", "", "", err
	}
	return string(pub), priv, proquintStr, nil
}

func writeKeys(where, publicKey, privateKey string) error {
	const create = os.O_RDWR | os.O_CREATE | os.O_TRUNC
	// Save the keys to files.
	fdPrivate, err := os.OpenFile(filepath.Join(where, "secret.upspinkey"), create, 0400)
	if err != nil {
		return err
	}
	fdPublic, err := os.OpenFile(filepath.Join(where, "public.upspinkey"), create, 0400)
	if err != nil {
		return err
	}

	fdPrivate.WriteString(privateKey)
	fdPublic.WriteString(string(publicKey))

	err = fdPrivate.Close()
	if err != nil {
		return err
	}
	err = fdPublic.Close()
	if err != nil {
		return err
	}
	return nil
}

func saveKeys(where string) error {
	private, err := os.Open(filepath.Join(where, "secret.upspinkey"))
	if os.IsNotExist(err) {
		return nil // There is nothing we need to save.
	}
	priv, err := ioutil.ReadAll(private)
	if err != nil {
		return err
	}
	public, err := os.Open(filepath.Join(where, "public.upspinkey"))
	if err != nil {
		return err // Halt. Existing files are corrupted and need manual attention.
	}
	pub, err := ioutil.ReadAll(public)
	if err != nil {
		return err
	}
	archive, err := os.OpenFile(filepath.Join(where, "secret2.upspinkey"),
		os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
	if err != nil {
		return err // We don't have permission to archive old keys?
	}
	_, err = archive.Write([]byte("# EE \n")) // TODO(ehg) add file date
	if err != nil {
		return err
	}
	_, err = archive.Write(pub)
	if err != nil {
		return err
	}
	_, err = archive.Write(priv)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>