<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"os"
	"path"
	"path/filepath"

	cmds "github.com/jbenet/go-ipfs/commands"
	config "github.com/jbenet/go-ipfs/config"
	core "github.com/jbenet/go-ipfs/core"
	ci "github.com/jbenet/go-ipfs/crypto"
	imp "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
	errors "github.com/jbenet/go-ipfs/util/debugerror"
)

var initCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Initializes IPFS config file",
		ShortDescription: "Initializes IPFS configuration files and generates a new keypair.",
	},

	Options: []cmds.Option{
		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),
		cmds.StringOption("datastore", "d", "Location for the IPFS data store"),

		// TODO need to decide whether to expose the override as a file or a
		// directory. That is: should we allow the user to also specify the
		// name of the file?
		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
	},
	Run: func(req cmds.Request) (interface{}, error) {

		dspathOverride, _, err := req.Option("d").String() // if !found it's okay. Let == ""
		if err != nil {
			return nil, err
		}

		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
		if err != nil {
			return nil, err
		}

		nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
		if err != nil {
			return nil, err
		}
		if !bitsOptFound {
			nBitsForKeypair = 4096
		}

		return doInit(req.Context().ConfigRoot, dspathOverride, force, nBitsForKeypair)
	},
}

var errCannotInitConfigExists = errors.New(`ipfs configuration file already exists!
Reinitializing would overwrite your keys.
(use -f to force overwrite)
`)

var welcomeMsg = `Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

For a short demo of what you can do, enter 'ipfs tour'
`

// NB: if dspath is not provided, it will be retrieved from the config
func doInit(configRoot string, dspathOverride string, force bool, nBitsForKeypair int) (interface{}, error) {

	u.POut("initializing ipfs node at %s\n", configRoot)

	configFilename, err := config.Filename(configRoot)
	if err != nil {
		return nil, errors.New("Couldn't get home directory path")
	}

	fi, err := os.Lstat(configFilename)
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		if !force {
			// TODO multi-line string
			return nil, errCannotInitConfigExists
		}
	}

	conf, err := initConfig(configFilename, dspathOverride, nBitsForKeypair)
	if err != nil {
		return nil, err
	}

	err = addTheWelcomeFile(conf, func(k u.Key) {
		fmt.Printf("\nto get started, enter: ipfs cat %s\n", k)
	})
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// addTheWelcomeFile adds a file containing the welcome message to the newly
// minted node. On success, it calls onSuccess
func addTheWelcomeFile(conf *config.Config, onSuccess func(u.Key)) error {
	// TODO extract this file creation operation into a function
	nd, err := core.NewIpfsNode(conf, false)
	if err != nil {
		return err
	}
	defer nd.Close()

	// Set up default file
	reader := bytes.NewBufferString(welcomeMsg)

	defnd, err := imp.BuildDagFromReader(reader, nd.DAG, nd.Pinning.GetManual(), chunk.DefaultSplitter)
	if err != nil {
		return err
	}

	k, err := defnd.Key()
	if err != nil {
		return fmt.Errorf("failed to write test file: %s", err)
	}
	onSuccess(k)
	return nil
}

func datastoreConfig(dspath string) (config.Datastore, error) {
	ds := config.Datastore{}
	if len(dspath) == 0 {
		var err error
		dspath, err = config.DataStorePath("")
		if err != nil {
			return ds, err
		}
	}
	ds.Path = dspath
	ds.Type = "leveldb"

	err := initCheckDir(dspath)
	if err != nil {
		return ds, errors.Errorf("datastore: %s", err)
	}

	return ds, nil
}

func initConfig(configFilename string, dspathOverride string, nBitsForKeypair int) (*config.Config, error) {
	ds, err := datastoreConfig(dspathOverride)
	if err != nil {
		return nil, err
	}

	identity, err := identityConfig(nBitsForKeypair, func() {
		fmt.Printf("generating key pair...")
	}, func(ident config.Identity) {
		fmt.Printf("done.\n")
		fmt.Printf("peer identity: %s\n", ident.PeerID)
	})
	if err != nil {
		return nil, err
	}

	logConfig, err := initLogs("") // TODO allow user to override dir
	if err != nil {
		return nil, err
	}

	conf := &config.Config{

		// setup the node addresses.
		Addresses: config.Addresses{
			Swarm: "/ip4/0.0.0.0/tcp/4001",
			API:   "/ip4/127.0.0.1/tcp/5001",
		},

		Bootstrap: []*config.BootstrapPeer{
			&config.BootstrapPeer{ // Use these hardcoded bootstrap peers for now.
				// mars.i.ipfs.io
				PeerID:  "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
				Address: "/ip4/104.131.131.82/tcp/4001",
			},
		},

		Datastore: ds,

		Logs: logConfig,

		Identity: identity,

		// setup the node mount points.
		Mounts: config.Mounts{
			IPFS: "/ipfs",
			IPNS: "/ipns",
		},

		// tracking ipfs version used to generate the init folder and adding
		// update checker default setting.
		Version: config.VersionDefaultValue(),
	}

	if err := config.WriteConfigFile(configFilename, conf); err != nil {
		return nil, err
	}

	return conf, nil
}

// identityConfig initializes a new identity. It calls onBegin when it begins
// to generate the identity and it calls onSuccess once the operation is
// completed successfully
func identityConfig(nbits int, onBegin func(), onSuccess func(config.Identity)) (config.Identity, error) {
	// TODO guard higher up
	ident := config.Identity{}
	if nbits < 1024 {
		return ident, errors.New("Bitsize less than 1024 is considered unsafe.")
	}

	onBegin()
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
	if err != nil {
		return ident, err
	}

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
		return ident, err
	}
	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPubKey(pk)
	if err != nil {
		return ident, err
	}
	ident.PeerID = id.Pretty()
	onSuccess(ident)
	return ident, nil
}

func initLogs(logpath string) (config.Logs, error) {
	if len(logpath) == 0 {
		var err error
		logpath, err = config.LogsPath("")
		if err != nil {
			return config.Logs{}, errors.Wrap(err)
		}
	}

	err := initCheckDir(logpath)
	if err != nil {
		return config.Logs{}, errors.Errorf("logs: %s", err)
	}

	return config.Logs{
		Filename: path.Join(logpath, "events.log"),
	}, nil
}

// initCheckDir ensures the directory exists and is writable
func initCheckDir(path string) error {
	// Construct the path if missing
	if err := os.MkdirAll(path, os.ModePerm); err != nil {
		return err
	}

	// Check the directory is writeable
	if f, err := os.Create(filepath.Join(path, "._check_writeable")); err == nil {
		os.Remove(f.Name())
	} else {
		return errors.New("'" + path + "' is not writeable")
	}
	return nil
}
<commit_msg>fix(2/init) msg<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"os"
	"path"
	"path/filepath"

	cmds "github.com/jbenet/go-ipfs/commands"
	config "github.com/jbenet/go-ipfs/config"
	core "github.com/jbenet/go-ipfs/core"
	ci "github.com/jbenet/go-ipfs/crypto"
	imp "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
	errors "github.com/jbenet/go-ipfs/util/debugerror"
)

var initCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Initializes IPFS config file",
		ShortDescription: "Initializes IPFS configuration files and generates a new keypair.",
	},

	Options: []cmds.Option{
		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),
		cmds.StringOption("datastore", "d", "Location for the IPFS data store"),

		// TODO need to decide whether to expose the override as a file or a
		// directory. That is: should we allow the user to also specify the
		// name of the file?
		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
	},
	Run: func(req cmds.Request) (interface{}, error) {

		dspathOverride, _, err := req.Option("d").String() // if !found it's okay. Let == ""
		if err != nil {
			return nil, err
		}

		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
		if err != nil {
			return nil, err
		}

		nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
		if err != nil {
			return nil, err
		}
		if !bitsOptFound {
			nBitsForKeypair = 4096
		}

		return doInit(req.Context().ConfigRoot, dspathOverride, force, nBitsForKeypair)
	},
}

var errCannotInitConfigExists = errors.New(`ipfs configuration file already exists!
Reinitializing would overwrite your keys.
(use -f to force overwrite)
`)

var welcomeMsg = `Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

For a short demo of what you can do, enter 'ipfs tour'
`

// NB: if dspath is not provided, it will be retrieved from the config
func doInit(configRoot string, dspathOverride string, force bool, nBitsForKeypair int) (interface{}, error) {

	u.POut("initializing ipfs node at %s\n", configRoot)

	configFilename, err := config.Filename(configRoot)
	if err != nil {
		return nil, errors.New("Couldn't get home directory path")
	}

	fi, err := os.Lstat(configFilename)
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		if !force {
			// TODO multi-line string
			return nil, errCannotInitConfigExists
		}
	}

	conf, err := initConfig(configFilename, dspathOverride, nBitsForKeypair)
	if err != nil {
		return nil, err
	}

	err = addTheWelcomeFile(conf, func(k u.Key) {
		fmt.Printf("\nto get started, enter: ipfs cat %s\n", k)
	})
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// addTheWelcomeFile adds a file containing the welcome message to the newly
// minted node. On success, it calls onSuccess
func addTheWelcomeFile(conf *config.Config, onSuccess func(u.Key)) error {
	// TODO extract this file creation operation into a function
	nd, err := core.NewIpfsNode(conf, false)
	if err != nil {
		return err
	}
	defer nd.Close()

	// Set up default file
	reader := bytes.NewBufferString(welcomeMsg)

	defnd, err := imp.BuildDagFromReader(reader, nd.DAG, nd.Pinning.GetManual(), chunk.DefaultSplitter)
	if err != nil {
		return err
	}

	k, err := defnd.Key()
	if err != nil {
		return fmt.Errorf("failed to write test file: %s", err)
	}
	onSuccess(k)
	return nil
}

func datastoreConfig(dspath string) (config.Datastore, error) {
	ds := config.Datastore{}
	if len(dspath) == 0 {
		var err error
		dspath, err = config.DataStorePath("")
		if err != nil {
			return ds, err
		}
	}
	ds.Path = dspath
	ds.Type = "leveldb"

	err := initCheckDir(dspath)
	if err != nil {
		return ds, errors.Errorf("datastore: %s", err)
	}

	return ds, nil
}

func initConfig(configFilename string, dspathOverride string, nBitsForKeypair int) (*config.Config, error) {
	ds, err := datastoreConfig(dspathOverride)
	if err != nil {
		return nil, err
	}

	identity, err := identityConfig(nBitsForKeypair, func() {
		fmt.Printf("generating key pair...")
	}, func(ident config.Identity) {
		fmt.Printf("done\n")
		fmt.Printf("peer identity: %s\n", ident.PeerID)
	})
	if err != nil {
		return nil, err
	}

	logConfig, err := initLogs("") // TODO allow user to override dir
	if err != nil {
		return nil, err
	}

	conf := &config.Config{

		// setup the node addresses.
		Addresses: config.Addresses{
			Swarm: "/ip4/0.0.0.0/tcp/4001",
			API:   "/ip4/127.0.0.1/tcp/5001",
		},

		Bootstrap: []*config.BootstrapPeer{
			&config.BootstrapPeer{ // Use these hardcoded bootstrap peers for now.
				// mars.i.ipfs.io
				PeerID:  "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
				Address: "/ip4/104.131.131.82/tcp/4001",
			},
		},

		Datastore: ds,

		Logs: logConfig,

		Identity: identity,

		// setup the node mount points.
		Mounts: config.Mounts{
			IPFS: "/ipfs",
			IPNS: "/ipns",
		},

		// tracking ipfs version used to generate the init folder and adding
		// update checker default setting.
		Version: config.VersionDefaultValue(),
	}

	if err := config.WriteConfigFile(configFilename, conf); err != nil {
		return nil, err
	}

	return conf, nil
}

// identityConfig initializes a new identity. It calls onBegin when it begins
// to generate the identity and it calls onSuccess once the operation is
// completed successfully
func identityConfig(nbits int, onBegin func(), onSuccess func(config.Identity)) (config.Identity, error) {
	// TODO guard higher up
	ident := config.Identity{}
	if nbits < 1024 {
		return ident, errors.New("Bitsize less than 1024 is considered unsafe.")
	}

	onBegin()
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
	if err != nil {
		return ident, err
	}

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
		return ident, err
	}
	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPubKey(pk)
	if err != nil {
		return ident, err
	}
	ident.PeerID = id.Pretty()
	onSuccess(ident)
	return ident, nil
}

func initLogs(logpath string) (config.Logs, error) {
	if len(logpath) == 0 {
		var err error
		logpath, err = config.LogsPath("")
		if err != nil {
			return config.Logs{}, errors.Wrap(err)
		}
	}

	err := initCheckDir(logpath)
	if err != nil {
		return config.Logs{}, errors.Errorf("logs: %s", err)
	}

	return config.Logs{
		Filename: path.Join(logpath, "events.log"),
	}, nil
}

// initCheckDir ensures the directory exists and is writable
func initCheckDir(path string) error {
	// Construct the path if missing
	if err := os.MkdirAll(path, os.ModePerm); err != nil {
		return err
	}

	// Check the directory is writeable
	if f, err := os.Create(filepath.Join(path, "._check_writeable")); err == nil {
		os.Remove(f.Name())
	} else {
		return errors.New("'" + path + "' is not writeable")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"go/ast"
	"go/parser"
	"go/token"

	"github.com/reusee/ccg"
)

var (
	pt = fmt.Printf

	outputFile  = flag.String("output", "", "output file")
	packageName = flag.String("package", "", "output package")
	uses        = flag.String("uses", "", "filter names")
)

func init() {
	flag.Parse()
}

func main() {
	args := flag.Args()
	if len(args) < 1 {
		pt("usage: %s [command] [args...]\n", os.Args[0])
		return
	}

	type CmdSpec struct {
		Usage   string
		Params  []string
		Renames []string
	}

	specs := map[string]CmdSpec{
		"sorter": {
			"[element type] [sorter name]",
			[]string{"T"},
			[]string{"Sorter"},
		},
		"set": {
			"[element type] [set type] [constructor name]",
			[]string{"T"},
			[]string{"Set", "New"},
		},
		"infchan": {
			"[element type]",
			[]string{"T"},
			[]string{"New"},
		},
		"slice": {
			"[element type] [slice type]",
			[]string{"T"},
			[]string{"Ts"},
		},
	}

	spec, ok := specs[args[0]]
	if !ok {
		log.Fatalf("unknown subcommand %s", args[0])
	}
	if len(args[1:]) != len(spec.Params)+len(spec.Renames) {
		log.Fatalf("usage: %s %s %s", os.Args[0], args[0], spec.Usage)
	}
	params := map[string]string{}
	for i, param := range spec.Params {
		params[param] = args[1+i]
	}
	renames := map[string]string{}
	start := len(spec.Params)
	for i, orig := range spec.Renames {
		renames[orig] = args[1+start+i]
	}

	buf := new(bytes.Buffer)
	var decls []ast.Decl
	fileSet := new(token.FileSet)
	if *outputFile != "" {
		content, err := ioutil.ReadFile(*outputFile)
		if err == nil {
			astFile, err := parser.ParseFile(fileSet, *outputFile, content, 0)
			if err == nil {
				decls = astFile.Decls
			}
		}
		if *packageName == "" {
			main := "main"
			packageName = &main
		}
	}

	nameSet := map[string]struct{}{}
	if len(*uses) > 0 {
		for _, name := range strings.Split(*uses, ",") {
			nameSet[name] = struct{}{}
		}
	}
	filters := []func(string) bool{}
	if len(nameSet) > 0 {
		filters = append(filters, func(name string) bool {
			_, in := nameSet[name]
			return in
		})
	}

	err := ccg.Copy(ccg.Config{
		From:        "github.com/reusee/ccg/" + args[0],
		Params:      params,
		Renames:     renames,
		Writer:      buf,
		Package:     *packageName,
		Decls:       decls,
		FileSet:     fileSet,
		NameFilters: filters,
	})
	if err != nil {
		log.Fatalf("ccg: copy error %v", err)
	}
	if *outputFile == "" {
		pt("%s\n", buf.Bytes())
	} else {
		err = ioutil.WriteFile(*outputFile, buf.Bytes(), 0644)
		if err != nil {
			log.Fatalf("ccg: write file error %v", err)
		}
	}
}
<commit_msg>myccg: fix uses option<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"go/ast"
	"go/parser"
	"go/token"

	"github.com/reusee/ccg"
)

var (
	pt = fmt.Printf

	outputFile  = flag.String("output", "", "output file")
	packageName = flag.String("package", "", "output package")
	uses        = flag.String("uses", "", "comma-separated functions to be used only")
)

func init() {
	flag.Parse()
}

func main() {
	args := flag.Args()
	if len(args) < 1 {
		pt("usage: %s [command] [args...]\n", os.Args[0])
		return
	}

	type CmdSpec struct {
		Usage   string
		Params  []string
		Renames []string
	}

	specs := map[string]CmdSpec{
		"sorter": {
			"[element type] [sorter name]",
			[]string{"T"},
			[]string{"Sorter"},
		},
		"set": {
			"[element type] [set type] [constructor name]",
			[]string{"T"},
			[]string{"Set", "New"},
		},
		"infchan": {
			"[element type]",
			[]string{"T"},
			[]string{"New"},
		},
		"slice": {
			"[element type] [slice type]",
			[]string{"T"},
			[]string{"Ts"},
		},
	}

	spec, ok := specs[args[0]]
	if !ok {
		log.Fatalf("unknown subcommand %s", args[0])
	}
	if len(args[1:]) != len(spec.Params)+len(spec.Renames) {
		log.Fatalf("usage: %s %s %s", os.Args[0], args[0], spec.Usage)
	}
	params := map[string]string{}
	for i, param := range spec.Params {
		params[param] = args[1+i]
	}
	renames := map[string]string{}
	start := len(spec.Params)
	for i, orig := range spec.Renames {
		renames[orig] = args[1+start+i]
	}

	buf := new(bytes.Buffer)
	var decls []ast.Decl
	fileSet := new(token.FileSet)
	if *outputFile != "" {
		content, err := ioutil.ReadFile(*outputFile)
		if err == nil {
			astFile, err := parser.ParseFile(fileSet, *outputFile, content, 0)
			if err == nil {
				decls = astFile.Decls
			}
		}
		if *packageName == "" {
			main := "main"
			packageName = &main
		}
	}

	var usesNames []string
	if len(*uses) > 0 {
		for _, name := range strings.Split(*uses, ",") {
			usesNames = append(usesNames, name)
		}
	}

	err := ccg.Copy(ccg.Config{
		From:    "github.com/reusee/ccg/" + args[0],
		Params:  params,
		Renames: renames,
		Writer:  buf,
		Package: *packageName,
		Decls:   decls,
		FileSet: fileSet,
		Uses:    usesNames,
	})
	if err != nil {
		log.Fatalf("ccg: copy error %v", err)
	}
	if *outputFile == "" {
		pt("%s\n", buf.Bytes())
	} else {
		err = ioutil.WriteFile(*outputFile, buf.Bytes(), 0644)
		if err != nil {
			log.Fatalf("ccg: write file error %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/bosssauce/ponzu/system/admin"
	"github.com/bosssauce/ponzu/system/api"
	"github.com/bosssauce/ponzu/system/api/analytics"
	"github.com/bosssauce/ponzu/system/db"
	"github.com/bosssauce/ponzu/system/tls"
)

var year = fmt.Sprintf("%d", time.Now().Year())

var usageHeader = `
$ ponzu [specifiers] command <params>

Ponzu is a powerful and efficient open-source "Content-as-a-Service" system
framework. It provides automatic, free, and secure HTTP/2 over TLS (certificates
obtained via Let's Encrypt - https://letsencrypt.org), a useful CMS and
scaffolding to generate content editors, and a fast HTTP API on which to build
modern applications.

Ponzu is released under the BSD-3-Clause license (see LICENSE).
(c) ` + year + ` Boss Sauce Creative, LLC

COMMANDS

`

var usageHelp = `
help, h (command):

	Help command will print the usage for Ponzu, or if a command is entered, it
	will show only the usage for that specific command.

	Example:
	$ ponzu help generate

`

var usageNew = `
new <directory>:

	Creates a 'ponzu' directorty, or one by the name supplied as a parameter
	immediately following the 'new' option in the $GOPATH/src directory. Note:
	'new' depends on the program 'git' and possibly a network connection. If
	there is no local repository to clone from at the local machine's $GOPATH,
	'new' will attempt to clone the 'github.com/bosssauce/ponzu' package from
	over the network.

	Example:
	$ ponzu new myProject
	> New ponzu project created at $GOPATH/src/myProject

	Errors will be reported, but successful commands retrun nothing.

`

var usageGenerate = `
generate, gen, g <type (,...fields)>:

	Generate a content type file with boilerplate code to implement
	the editor.Editable interface. Must be given one (1) parameter of
	the name of the type for the new content. The fields following a
	type determine the field names and types of the content struct to
	be generated. These must be in the following format:
	fieldName:"T"

	Example:
	$ ponzu gen review title:"string" body:"string" rating:"int" tags:"[]string"

	The command above will generate a file 'content/review.go' with boilerplate
	methods, as well as struct definition, and cooresponding field tags like:

	type Review struct {
		Title  string   ` + "`json:" + `"title"` + "`" + `
		Body   string   ` + "`json:" + `"body"` + "`" + `
		Rating int      ` + "`json:" + `"rating"` + "`" + `
		Tags   []string ` + "`json:" + `"tags"` + "`" + `
	}

	The generate command will intelligently parse more sophisticated field names
	such as 'field_name' and convert it to 'FieldName' and vice versa, only where
	appropriate as per common Go idioms. Errors will be reported, but successful
	generate commands retrun nothing.

`

var usageBuild = `
build

	From within your Ponzu project directory, running build will copy and move
	the necessary files from your workspace into the vendored directory, and
	will build/compile the project to then be run.

	Example:
	$ ponzu build

	Errors will be reported, but successful build commands return nothing.

`

var usageRun = `
[[--port=8080] [--https]] run <service(,service)>:

	Starts the 'ponzu' HTTP server for the JSON API, Admin System, or both.
	The segments, separated by a comma, describe which services to start, either
	'admin' (Admin System / CMS backend) or 'api' (JSON API), and, optionally,
	if the server should utilize TLS encryption - served over HTTPS, which is
	automatically managed using Let's Encrypt (https://letsencrypt.org)

	Example:
	$ ponzu run
	(or)
	$ ponzu --port=8080 --https run admin,api
	(or)
	$ ponzu run admin
	(or)
	$ ponzu --port=8888 run api

	Defaults to '--port=8080 run admin,api' (running Admin & API on port 8080, without TLS)

	Note:
	Admin and API cannot run on separate processes unless you use a copy of the
	database, since the first process to open it recieves a lock. If you intend
	to run the Admin and API on separate processes, you must call them with the
	'ponzu' command independently.

`

var (
	usage = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port  int
	https bool

	// for ponzu internal / core development
	dev  bool
	fork string
)

func init() {
	flag.Usage = func() {
		fmt.Println(usage)
	}
}

func main() {
	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usage)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 2 {
			flag.PrintDefaults()
			os.Exit(0)
		}

		err := generateContentType(args[1:])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "serve", "s":
		db.Init()
		defer db.Close()

		analytics.Init()
		defer analytics.Close()

		if len(args) > 1 {
			services := strings.Split(args[1], ",")

			for i := range services {
				if services[i] == "api" {
					api.Run()
				} else if services[i] == "admin" {
					admin.Run()
				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		if https {
			fmt.Println("Enabling HTTPS...")
			tls.Enable()
		}

		// save the port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err := db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.")
		}

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<commit_msg>adding _ import to register content types for item.Types<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/bosssauce/ponzu/system/admin"
	"github.com/bosssauce/ponzu/system/api"
	"github.com/bosssauce/ponzu/system/api/analytics"
	"github.com/bosssauce/ponzu/system/db"
	"github.com/bosssauce/ponzu/system/tls"

	// import registers content types
	_ "github.com/bosssauce/ponzu/content"
)

var year = fmt.Sprintf("%d", time.Now().Year())

var usageHeader = `
$ ponzu [specifiers] command <params>

Ponzu is a powerful and efficient open-source "Content-as-a-Service" system
framework. It provides automatic, free, and secure HTTP/2 over TLS (certificates
obtained via Let's Encrypt - https://letsencrypt.org), a useful CMS and
scaffolding to generate content editors, and a fast HTTP API on which to build
modern applications.

Ponzu is released under the BSD-3-Clause license (see LICENSE).
(c) ` + year + ` Boss Sauce Creative, LLC

COMMANDS

`

var usageHelp = `
help, h (command):

	Help command will print the usage for Ponzu, or if a command is entered, it
	will show only the usage for that specific command.

	Example:
	$ ponzu help generate

`

var usageNew = `
new <directory>:

	Creates a 'ponzu' directorty, or one by the name supplied as a parameter
	immediately following the 'new' option in the $GOPATH/src directory. Note:
	'new' depends on the program 'git' and possibly a network connection. If
	there is no local repository to clone from at the local machine's $GOPATH,
	'new' will attempt to clone the 'github.com/bosssauce/ponzu' package from
	over the network.

	Example:
	$ ponzu new myProject
	> New ponzu project created at $GOPATH/src/myProject

	Errors will be reported, but successful commands retrun nothing.

`

var usageGenerate = `
generate, gen, g <type (,...fields)>:

	Generate a content type file with boilerplate code to implement
	the editor.Editable interface. Must be given one (1) parameter of
	the name of the type for the new content. The fields following a
	type determine the field names and types of the content struct to
	be generated. These must be in the following format:
	fieldName:"T"

	Example:
	$ ponzu gen review title:"string" body:"string" rating:"int" tags:"[]string"

	The command above will generate a file 'content/review.go' with boilerplate
	methods, as well as struct definition, and cooresponding field tags like:

	type Review struct {
		Title  string   ` + "`json:" + `"title"` + "`" + `
		Body   string   ` + "`json:" + `"body"` + "`" + `
		Rating int      ` + "`json:" + `"rating"` + "`" + `
		Tags   []string ` + "`json:" + `"tags"` + "`" + `
	}

	The generate command will intelligently parse more sophisticated field names
	such as 'field_name' and convert it to 'FieldName' and vice versa, only where
	appropriate as per common Go idioms. Errors will be reported, but successful
	generate commands retrun nothing.

`

var usageBuild = `
build

	From within your Ponzu project directory, running build will copy and move
	the necessary files from your workspace into the vendored directory, and
	will build/compile the project to then be run.

	Example:
	$ ponzu build

	Errors will be reported, but successful build commands return nothing.

`

var usageRun = `
[[--port=8080] [--https]] run <service(,service)>:

	Starts the 'ponzu' HTTP server for the JSON API, Admin System, or both.
	The segments, separated by a comma, describe which services to start, either
	'admin' (Admin System / CMS backend) or 'api' (JSON API), and, optionally,
	if the server should utilize TLS encryption - served over HTTPS, which is
	automatically managed using Let's Encrypt (https://letsencrypt.org)

	Example:
	$ ponzu run
	(or)
	$ ponzu --port=8080 --https run admin,api
	(or)
	$ ponzu run admin
	(or)
	$ ponzu --port=8888 run api

	Defaults to '--port=8080 run admin,api' (running Admin & API on port 8080, without TLS)

	Note:
	Admin and API cannot run on separate processes unless you use a copy of the
	database, since the first process to open it recieves a lock. If you intend
	to run the Admin and API on separate processes, you must call them with the
	'ponzu' command independently.

`

var (
	usage = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port  int
	https bool

	// for ponzu internal / core development
	dev  bool
	fork string
)

func init() {
	flag.Usage = func() {
		fmt.Println(usage)
	}
}

func main() {
	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usage)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 2 {
			flag.PrintDefaults()
			os.Exit(0)
		}

		err := generateContentType(args[1:])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "serve", "s":
		db.Init()
		defer db.Close()

		analytics.Init()
		defer analytics.Close()

		if len(args) > 1 {
			services := strings.Split(args[1], ",")

			for i := range services {
				if services[i] == "api" {
					api.Run()
				} else if services[i] == "admin" {
					admin.Run()
				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		if https {
			fmt.Println("Enabling HTTPS...")
			tls.Enable()
		}

		// save the port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err := db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.")
		}

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<|endoftext|>


<commit_before>// assembler for iris1
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"unicode"
	"unicode/utf8"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if len(line) == 0 {
			continue
		} else {
			fmt.Println(line)
			stmt := carveLine(line)
			for ind, str := range stmt {
				fmt.Printf("\t%d: %s\n", ind, str)
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

type statement []string

func carveLine(line string) statement {
	var s statement
	oldStart := 0
	start := 0
	// skip the strings at the beginning
	for width := 0; start < len(line); start += width {
		var r rune
		r, width = utf8.DecodeRuneInString(line[start:])
		if unicode.IsSpace(r) || r == '=' || r == ',' {
			str := strings.TrimSpace(line[oldStart:start])
			if len(str) > 0 {
				s = append(s, str)
			}
			oldStart = start
		} else if r == ';' {
			// consume the rest of the line
			preComment := strings.TrimSpace(line[oldStart:start])
			if len(preComment) > 0 {
				s = append(s, preComment)
			}
			// then capture the comment
			s = append(s, line[start:])
			oldStart = start
			break
		}
	}
	if oldStart < start {
		s = append(s, line[oldStart:])
	}
	return s
}
<commit_msg>Expanded parsing of symbols in the assembler carver<commit_after>// assembler for iris1
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"unicode"
	"unicode/utf8"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if len(line) == 0 {
			continue
		} else {
			fmt.Println(line)
			stmt := carveLine(line)
			for ind, str := range stmt {
				fmt.Printf("\t%d: %s\n", ind, str.Value)
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

type NodeType int

const (
	TypeUnknown NodeType = iota
	TypeEquals
	TypeComma
	TypeLabel
	TypeRegister
	TypeImmediate
	TypeComment
)

type Node struct {
	Value string
	Type  NodeType
}

func (this *Node) IsComment() bool {
	return this.Type == TypeComment
}
func (this *Node) IsLabel() bool {
	return this.Type == TypeLabel
}

func (this *Node) NeedsAnalysis() bool {
	return this.Type == TypeUnknown
}

type Statement []Node

func carveLine(line string) Statement {
	// trim the damn line first
	captureSequence := func(nodes Statement, dat string, from, to int) Statement {
		str := strings.TrimSpace(dat[from:to])
		if len(str) > 0 {
			return append(nodes, Node{Value: str, Type: TypeUnknown})
		} else {
			return nodes
		}
	}
	data := strings.TrimSpace(line)
	var s Statement
	if len(data) == 0 {
		return s
	}
	oldStart := 0
	start := 0
	// skip the strings at the beginning
	for width := 0; start < len(data); start += width {
		var r rune
		r, width = utf8.DecodeRuneInString(data[start:])
		if unicode.IsSpace(r) {
			s = captureSequence(s, data, oldStart, start)
			oldStart = start
		} else if r == '=' {
			s = captureSequence(s, data, oldStart, start)
			s = append(s, Node{Value: "=", Type: TypeEquals})
			oldStart = start + width
		} else if r == ',' {
			s = captureSequence(s, data, oldStart, start)
			s = append(s, Node{Value: ",", Type: TypeComma})
			oldStart = start + width
		} else if r == ';' {
			// consume the rest of the data
			s = captureSequence(s, data, oldStart, start)
			// then capture the comment
			s = append(s, Node{Value: data[start:], Type: TypeComment})
			oldStart = start
			break
		}
	}
	if oldStart < start {
		s = append(s, Node{Value: data[oldStart:]})
	}
	return s
}
<|endoftext|>


<commit_before>package shell

import (
	"fmt"

	"github.com/kardianos/osext"
)

const template = `#!/usr/bin/env zsh
ANTIBODY_BINARY="%s"
antibody() {
	case "$1" in
	bundle)
		source <( $ANTIBODY_BINARY $@ )
		;;
	*)
		$ANTIBODY_BINARY $@
		;;
	esac
}

_antibody() {
	IFS=' ' read -A reply <<< "$(echo "bundle update list home init help")"
}
compctl -K _antibody antibody
`

// Init returns the shell that should be loaded to antibody to work correctly.
func Init() string {
	executable, _ := osext.Executable()
	return fmt.Sprintf(template, executable)
}
<commit_msg>fix antibody bundle -h<commit_after>package shell

import (
	"fmt"

	"github.com/kardianos/osext"
)

const template = `#!/usr/bin/env zsh
ANTIBODY_BINARY="%s"
antibody() {
	case "$1" in
	bundle)
		source <( $ANTIBODY_BINARY $@ ) 2> /dev/null || $ANTIBODY_BINARY $@
		;;
	*)
		$ANTIBODY_BINARY $@
		;;
	esac
}

_antibody() {
	IFS=' ' read -A reply <<< "$(echo "bundle update list home init help")"
}
compctl -K _antibody antibody
`

// Init returns the shell that should be loaded to antibody to work correctly.
func Init() string {
	executable, _ := osext.Executable()
	return fmt.Sprintf(template, executable)
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/client"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/sesha3"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/spf13/cobra"
)

var targets []string

func StackExecCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "exec",
		Short: "execute a script in stack instance(s)",
		Long: `Execute a script in stack instance(s). You can use the --target flag more than once.

Examples:

  $ ` + cmdline.Args0() + ` stack exec --target "stackid|ip:flag" --script /path/to/script
  $ ` + cmdline.Args0() + ` stack exec --target "stackid|ip1:flag1" \
      --target "stackid|ip2:flag2" \
      --script /path/to/script`,
		Run: stackExec,
	}

	cmd.Flags().SortFlags = false
	cmd.Flags().StringSliceVar(&targets, "target", targets, "`fmt`: stackid|ip:flag")
	cmd.Flags().String("script", "", "your script path")
	return cmd
}

func stackExec(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	cli.ErrorExit(err, 1)

	svc := sesha3.New(sess)
	sfile := cli.GetCliStringFlag(cmd, "script")
	scriptdata, err := ioutil.ReadFile(sfile)
	cli.ErrorExit(err, 1)

	in := &sesha3.ExecScriptInput{
		Targets: targets,
		OutputCallback: func(idx int, cr *client.Response, body []byte, th *sesha3.TargetHeader, err error) {
			d.Info("["+fmt.Sprintf("%d", idx)+"]output:", th.StackId+",", "instance:", th.VmUser+"@"+th.Ip+",", "flag:", th.Flag)
			var res sesha3.ExecScriptStackResponse
			err = json.Unmarshal(body, &res)
			if err != nil {
				d.Error(err)
			}

			fmt.Println(string(res.Outputs[0].CmdOut))
		},
		Script: scriptdata,
	}

	_, _, err = svc.ExecScript(in)
	cli.ErrorExit(err, 1)
}
<commit_msg>Print error in exec if any.<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/client"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/sesha3"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/spf13/cobra"
)

var targets []string

func StackExecCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "exec",
		Short: "execute a script in stack instance(s)",
		Long: `Execute a script in stack instance(s). You can use the --target flag more than once.

Examples:

  $ ` + cmdline.Args0() + ` stack exec --target "stackid|ip:flag" --script /path/to/script
  $ ` + cmdline.Args0() + ` stack exec --target "stackid|ip1:flag1" \
      --target "stackid|ip2:flag2" \
      --script /path/to/script`,
		Run: stackExec,
	}

	cmd.Flags().SortFlags = false
	cmd.Flags().StringSliceVar(&targets, "target", targets, "`fmt`: stackid|ip:flag")
	cmd.Flags().String("script", "", "your script path")
	return cmd
}

func stackExec(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	cli.ErrorExit(err, 1)

	svc := sesha3.New(sess)
	sfile := cli.GetCliStringFlag(cmd, "script")
	scriptdata, err := ioutil.ReadFile(sfile)
	cli.ErrorExit(err, 1)

	in := &sesha3.ExecScriptInput{
		Targets: targets,
		OutputCallback: func(idx int, cr *client.Response, body []byte, th *sesha3.TargetHeader, err error) {
			if err != nil {
				d.Error(th.StackId+"|"+th.VmUser+"@"+th.Ip+":"+th.Flag+" failed:", err)
			}

			d.Info("["+fmt.Sprintf("%d", idx)+"]output:", th.StackId+",", "instance:", th.VmUser+"@"+th.Ip+",", "flag:", th.Flag)
			var res sesha3.ExecScriptStackResponse
			err = json.Unmarshal(body, &res)
			if err != nil {
				d.Error(err)
			}

			fmt.Println(string(res.Outputs[0].CmdOut))
		},
		Script: scriptdata,
	}

	_, _, err = svc.ExecScript(in)
	cli.ErrorExit(err, 1)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/penberg/ustat"
	"gopkg.in/urfave/cli.v1"
	"os"
	"os/signal"
	"regexp"
	"strconv"
	"syscall"
	"time"
)

const defaultDelay = 1

func main() {
	app := cli.NewApp()
	app.Name = "ustat"
	app.Usage = "Unified system statistics collector"
	app.HideHelp = true
	app.ArgsUsage = "[delay]"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "c,cpu",
			Usage: "enable CPU stats collection",
		},
		cli.BoolFlag{
			Name:  "i,int",
			Usage: "enable interrupt stats collection",
		},
		cli.BoolFlag{
			Name:  "n,net",
			Usage: "enable network stats collection",
		},
		cli.BoolFlag{
			Name:  "d,disk",
			Usage: "enable disk stats collection",
		},
		cli.StringFlag{
			Name:  "o,output",
			Usage: "write output to `FILE`",
		},
		cli.StringFlag{
			Name:  "delimiter",
			Usage: "delimiter used in the output file",
			Value: "\t",
		},
		cli.StringFlag{
			Name:  "grep",
			Usage: "filter stats using an regular expression `PATTERN`",
		},
		cli.HelpFlag,
	}
	app.Action = func(ctx *cli.Context) error {
		var stats []*ustat.Stat
		if ctx.Bool("help") {
			cli.ShowAppHelp(ctx)
			return nil
		}
		if ctx.Bool("cpu") {
			stats = append(stats, ustat.NewCPUsStat())
		}
		if ctx.Bool("int") {
			stats = append(stats, ustat.NewInterruptsStat())
		}
		if ctx.Bool("net") {
			stats = append(stats, ustat.NewNetStat())
		}
		if ctx.Bool("disk") {
			stats = append(stats, ustat.NewDiskStat())
		}
		output := os.Stdout
		outputPath := ctx.String("output")
		if outputPath != "" {
			file, err := os.Create(outputPath)
			if err != nil {
				return cli.NewExitError(fmt.Sprintf("Unable to open file: %v", err), 2)
			}
			defer file.Close()
			output = file
		}
		pattern := ctx.String("grep")
		if len(stats) == 0 {
			stats = []*ustat.Stat{
				ustat.NewCPUsStat(),
				ustat.NewInterruptsStat(),
				ustat.NewNetStat(),
				ustat.NewDiskStat(),
			}
		}
		delimiter := ctx.String("delimiter")
		delay := defaultDelay
		args := ctx.Args()
		if len(args) > 0 {
			rawDelay := args[0]
			var err error
			delay, err = strconv.Atoi(rawDelay)
			if err != nil {
				return cli.NewExitError(fmt.Sprintf("Failed to parse delay argument: '%s'", rawDelay), 3)
			}

		}
		fmt.Fprintf(output, "# This file has been generated by ustat.\n")
		fmt.Fprintf(output, "#\n")
		fmt.Fprintf(output, "# Column descriptions:\n")
		for _, stat := range stats {
			for _, description := range stat.Descriptions {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, description)
					if err != nil || !matched {
						continue
					}
				}
				fmt.Fprintf(output, "# %s\n", description)
			}
		}
		for statIdx, stat := range stats {
			for nameIdx, name := range stat.Names {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, name)
					if err != nil || !matched {
						continue
					}
				}
				if statIdx+nameIdx == 0 {
					fmt.Fprintf(output, "%s", name)
				} else {
					fmt.Fprintf(output, "%s%s", delimiter, name)
				}
			}
		}
		fmt.Fprintln(output, "")
		sigs := make(chan os.Signal, 1)
		done := make(chan bool, 1)
		signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
		go func() {
			sig := <-sigs
			fmt.Println()
			fmt.Println(sig)
			done <- true
		}()
		ticker := time.NewTicker(time.Duration(delay) * time.Second)
		go func() {
			for _ = range ticker.C {
				for statIdx, stat := range stats {
					values := stat.Collector.Collect()
					for valueIdx, value := range values {
						if pattern != "" {
							matched, err := regexp.MatchString(pattern, stat.Names[valueIdx])
							if err != nil || !matched {
								continue
							}
						}
						if statIdx+valueIdx == 0 {
							fmt.Fprintf(output, "%d", value)
						} else {
							fmt.Fprintf(output, "%s%d", delimiter, value)
						}
					}
				}
				fmt.Fprintln(output, "")
			}
		}()
		<-done

		return nil
	}
	app.Run(os.Args)
}
<commit_msg>Add myself as an author to help text<commit_after>package main

import (
	"fmt"
	"github.com/penberg/ustat"
	"gopkg.in/urfave/cli.v1"
	"os"
	"os/signal"
	"regexp"
	"strconv"
	"syscall"
	"time"
)

const defaultDelay = 1

func main() {
	app := cli.NewApp()
	app.Name = "ustat"
	app.Usage = "Unified system statistics collector"
	app.Authors = []cli.Author{
		cli.Author{
			Name:  "Pekka Enberg",
			Email: "penberg@iki.fi",
		},
	}
	app.HideHelp = true
	app.ArgsUsage = "[delay]"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "c,cpu",
			Usage: "enable CPU stats collection",
		},
		cli.BoolFlag{
			Name:  "i,int",
			Usage: "enable interrupt stats collection",
		},
		cli.BoolFlag{
			Name:  "n,net",
			Usage: "enable network stats collection",
		},
		cli.BoolFlag{
			Name:  "d,disk",
			Usage: "enable disk stats collection",
		},
		cli.StringFlag{
			Name:  "o,output",
			Usage: "write output to `FILE`",
		},
		cli.StringFlag{
			Name:  "delimiter",
			Usage: "delimiter used in the output file",
			Value: "\t",
		},
		cli.StringFlag{
			Name:  "grep",
			Usage: "filter stats using an regular expression `PATTERN`",
		},
		cli.HelpFlag,
	}
	app.Action = func(ctx *cli.Context) error {
		var stats []*ustat.Stat
		if ctx.Bool("help") {
			cli.ShowAppHelp(ctx)
			return nil
		}
		if ctx.Bool("cpu") {
			stats = append(stats, ustat.NewCPUsStat())
		}
		if ctx.Bool("int") {
			stats = append(stats, ustat.NewInterruptsStat())
		}
		if ctx.Bool("net") {
			stats = append(stats, ustat.NewNetStat())
		}
		if ctx.Bool("disk") {
			stats = append(stats, ustat.NewDiskStat())
		}
		output := os.Stdout
		outputPath := ctx.String("output")
		if outputPath != "" {
			file, err := os.Create(outputPath)
			if err != nil {
				return cli.NewExitError(fmt.Sprintf("Unable to open file: %v", err), 2)
			}
			defer file.Close()
			output = file
		}
		pattern := ctx.String("grep")
		if len(stats) == 0 {
			stats = []*ustat.Stat{
				ustat.NewCPUsStat(),
				ustat.NewInterruptsStat(),
				ustat.NewNetStat(),
				ustat.NewDiskStat(),
			}
		}
		delimiter := ctx.String("delimiter")
		delay := defaultDelay
		args := ctx.Args()
		if len(args) > 0 {
			rawDelay := args[0]
			var err error
			delay, err = strconv.Atoi(rawDelay)
			if err != nil {
				return cli.NewExitError(fmt.Sprintf("Failed to parse delay argument: '%s'", rawDelay), 3)
			}

		}
		fmt.Fprintf(output, "# This file has been generated by ustat.\n")
		fmt.Fprintf(output, "#\n")
		fmt.Fprintf(output, "# Column descriptions:\n")
		for _, stat := range stats {
			for _, description := range stat.Descriptions {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, description)
					if err != nil || !matched {
						continue
					}
				}
				fmt.Fprintf(output, "# %s\n", description)
			}
		}
		for statIdx, stat := range stats {
			for nameIdx, name := range stat.Names {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, name)
					if err != nil || !matched {
						continue
					}
				}
				if statIdx+nameIdx == 0 {
					fmt.Fprintf(output, "%s", name)
				} else {
					fmt.Fprintf(output, "%s%s", delimiter, name)
				}
			}
		}
		fmt.Fprintln(output, "")
		sigs := make(chan os.Signal, 1)
		done := make(chan bool, 1)
		signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
		go func() {
			sig := <-sigs
			fmt.Println()
			fmt.Println(sig)
			done <- true
		}()
		ticker := time.NewTicker(time.Duration(delay) * time.Second)
		go func() {
			for _ = range ticker.C {
				for statIdx, stat := range stats {
					values := stat.Collector.Collect()
					for valueIdx, value := range values {
						if pattern != "" {
							matched, err := regexp.MatchString(pattern, stat.Names[valueIdx])
							if err != nil || !matched {
								continue
							}
						}
						if statIdx+valueIdx == 0 {
							fmt.Fprintf(output, "%d", value)
						} else {
							fmt.Fprintf(output, "%s%d", delimiter, value)
						}
					}
				}
				fmt.Fprintln(output, "")
			}
		}()
		<-done

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


<commit_before>package leafnodes_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/internal/leafnodes"
	. "github.com/onsi/gomega"

	"time"

	"github.com/onsi/ginkgo/internal/codelocation"
	Failer "github.com/onsi/ginkgo/internal/failer"
	"github.com/onsi/ginkgo/types"
)

var _ = Describe("Measure Nodes", func() {
	It("should report the correct type, text, flag, and code location", func() {
		codeLocation := codelocation.New(0)
		measure := NewMeasureNode("my measure node", func(b Benchmarker) {}, types.FlagTypeFocused, codeLocation, 10, nil, 3)
		Ω(measure.Type()).Should(Equal(types.SpecComponentTypeMeasure))
		Ω(measure.Flag()).Should(Equal(types.FlagTypeFocused))
		Ω(measure.Text()).Should(Equal("my measure node"))
		Ω(measure.CodeLocation()).Should(Equal(codeLocation))
		Ω(measure.Samples()).Should(Equal(10))
	})

	Describe("benchmarking", func() {
		var measure *MeasureNode

		Describe("Value", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.RecordValue("foo", 7, "info!")
					b.RecordValue("foo", 2)
					b.RecordValue("foo", 3)
					b.RecordValue("bar", 0.3)
					b.RecordValue("bar", 0.1)
					b.RecordValue("bar", 0.5)
					b.RecordValue("bar", 0.7)
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(2))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].Order).Should(Equal(0))
				Ω(report["foo"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["foo"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["foo"].AverageLabel).Should(Equal(" Average"))
				Ω(report["foo"].Units).Should(Equal(""))
				Ω(report["foo"].Results).Should(Equal([]float64{7, 2, 3}))
				Ω(report["foo"].Smallest).Should(BeNumerically("==", 2))
				Ω(report["foo"].Largest).Should(BeNumerically("==", 7))
				Ω(report["foo"].Average).Should(BeNumerically("==", 4))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 2.16, 0.01))

				Ω(report["bar"].Name).Should(Equal("bar"))
				Ω(report["bar"].Info).Should(BeNil())
				Ω(report["bar"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["bar"].Order).Should(Equal(1))
				Ω(report["bar"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["bar"].AverageLabel).Should(Equal(" Average"))
				Ω(report["bar"].Units).Should(Equal(""))
				Ω(report["bar"].Results).Should(Equal([]float64{0.3, 0.1, 0.5, 0.7}))
				Ω(report["bar"].Smallest).Should(BeNumerically("==", 0.1))
				Ω(report["bar"].Largest).Should(BeNumerically("==", 0.7))
				Ω(report["bar"].Average).Should(BeNumerically("==", 0.4))
				Ω(report["bar"].StdDeviation).Should(BeNumerically("~", 0.22, 0.01))
			})
		})

		Describe("Value with precision", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.RecordValueWithPrecision("foo", 7, "ms", 7, "info!")
					b.RecordValueWithPrecision("foo", 2, "ms", 6)
					b.RecordValueWithPrecision("foo", 3, "ms", 5)
					b.RecordValueWithPrecision("bar", 0.3, "ns", 4)
					b.RecordValueWithPrecision("bar", 0.1, "ns", 3)
					b.RecordValueWithPrecision("bar", 0.5, "ns", 2)
					b.RecordValueWithPrecision("bar", 0.7, "ns", 1)
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(2))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].Order).Should(Equal(0))
				Ω(report["foo"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["foo"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["foo"].AverageLabel).Should(Equal(" Average"))
				Ω(report["foo"].Units).Should(Equal("ms"))
				Ω(report["foo"].Results).Should(Equal([]float64{7, 2, 3}))
				Ω(report["foo"].Smallest).Should(BeNumerically("==", 2))
				Ω(report["foo"].Largest).Should(BeNumerically("==", 7))
				Ω(report["foo"].Average).Should(BeNumerically("==", 4))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 2.16, 0.01))

				Ω(report["bar"].Name).Should(Equal("bar"))
				Ω(report["bar"].Info).Should(BeNil())
				Ω(report["bar"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["bar"].Order).Should(Equal(1))
				Ω(report["bar"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["bar"].AverageLabel).Should(Equal(" Average"))
				Ω(report["bar"].Units).Should(Equal("ns"))
				Ω(report["bar"].Results).Should(Equal([]float64{0.3, 0.1, 0.5, 0.7}))
				Ω(report["bar"].Smallest).Should(BeNumerically("==", 0.1))
				Ω(report["bar"].Largest).Should(BeNumerically("==", 0.7))
				Ω(report["bar"].Average).Should(BeNumerically("==", 0.4))
				Ω(report["bar"].StdDeviation).Should(BeNumerically("~", 0.22, 0.01))
			})
		})

		Describe("Time", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.Time("foo", func() {
						time.Sleep(100 * time.Millisecond)
					}, "info!")
					b.Time("foo", func() {
						time.Sleep(200 * time.Millisecond)
					})
					b.Time("foo", func() {
						time.Sleep(170 * time.Millisecond)
					})
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(1))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].SmallestLabel).Should(Equal("Fastest Time"))
				Ω(report["foo"].LargestLabel).Should(Equal("Slowest Time"))
				Ω(report["foo"].AverageLabel).Should(Equal("Average Time"))
				Ω(report["foo"].Units).Should(Equal("s"))
				Ω(report["foo"].Results).Should(HaveLen(3))
				Ω(report["foo"].Results[0]).Should(BeNumerically("~", 0.1, 0.01))
				Ω(report["foo"].Results[1]).Should(BeNumerically("~", 0.2, 0.01))
				Ω(report["foo"].Results[2]).Should(BeNumerically("~", 0.17, 0.01))
				Ω(report["foo"].Smallest).Should(BeNumerically("~", 0.1, 0.01))
				Ω(report["foo"].Largest).Should(BeNumerically("~", 0.2, 0.01))
				Ω(report["foo"].Average).Should(BeNumerically("~", 0.16, 0.01))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 0.04, 0.01))
			})
		})
	})
})
<commit_msg>Increase the threshold when checking time measuments<commit_after>package leafnodes_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/internal/leafnodes"
	. "github.com/onsi/gomega"

	"time"

	"github.com/onsi/ginkgo/internal/codelocation"
	Failer "github.com/onsi/ginkgo/internal/failer"
	"github.com/onsi/ginkgo/types"
)

var _ = Describe("Measure Nodes", func() {
	It("should report the correct type, text, flag, and code location", func() {
		codeLocation := codelocation.New(0)
		measure := NewMeasureNode("my measure node", func(b Benchmarker) {}, types.FlagTypeFocused, codeLocation, 10, nil, 3)
		Ω(measure.Type()).Should(Equal(types.SpecComponentTypeMeasure))
		Ω(measure.Flag()).Should(Equal(types.FlagTypeFocused))
		Ω(measure.Text()).Should(Equal("my measure node"))
		Ω(measure.CodeLocation()).Should(Equal(codeLocation))
		Ω(measure.Samples()).Should(Equal(10))
	})

	Describe("benchmarking", func() {
		var measure *MeasureNode

		Describe("Value", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.RecordValue("foo", 7, "info!")
					b.RecordValue("foo", 2)
					b.RecordValue("foo", 3)
					b.RecordValue("bar", 0.3)
					b.RecordValue("bar", 0.1)
					b.RecordValue("bar", 0.5)
					b.RecordValue("bar", 0.7)
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(2))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].Order).Should(Equal(0))
				Ω(report["foo"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["foo"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["foo"].AverageLabel).Should(Equal(" Average"))
				Ω(report["foo"].Units).Should(Equal(""))
				Ω(report["foo"].Results).Should(Equal([]float64{7, 2, 3}))
				Ω(report["foo"].Smallest).Should(BeNumerically("==", 2))
				Ω(report["foo"].Largest).Should(BeNumerically("==", 7))
				Ω(report["foo"].Average).Should(BeNumerically("==", 4))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 2.16, 0.01))

				Ω(report["bar"].Name).Should(Equal("bar"))
				Ω(report["bar"].Info).Should(BeNil())
				Ω(report["bar"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["bar"].Order).Should(Equal(1))
				Ω(report["bar"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["bar"].AverageLabel).Should(Equal(" Average"))
				Ω(report["bar"].Units).Should(Equal(""))
				Ω(report["bar"].Results).Should(Equal([]float64{0.3, 0.1, 0.5, 0.7}))
				Ω(report["bar"].Smallest).Should(BeNumerically("==", 0.1))
				Ω(report["bar"].Largest).Should(BeNumerically("==", 0.7))
				Ω(report["bar"].Average).Should(BeNumerically("==", 0.4))
				Ω(report["bar"].StdDeviation).Should(BeNumerically("~", 0.22, 0.01))
			})
		})

		Describe("Value with precision", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.RecordValueWithPrecision("foo", 7, "ms", 7, "info!")
					b.RecordValueWithPrecision("foo", 2, "ms", 6)
					b.RecordValueWithPrecision("foo", 3, "ms", 5)
					b.RecordValueWithPrecision("bar", 0.3, "ns", 4)
					b.RecordValueWithPrecision("bar", 0.1, "ns", 3)
					b.RecordValueWithPrecision("bar", 0.5, "ns", 2)
					b.RecordValueWithPrecision("bar", 0.7, "ns", 1)
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(2))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].Order).Should(Equal(0))
				Ω(report["foo"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["foo"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["foo"].AverageLabel).Should(Equal(" Average"))
				Ω(report["foo"].Units).Should(Equal("ms"))
				Ω(report["foo"].Results).Should(Equal([]float64{7, 2, 3}))
				Ω(report["foo"].Smallest).Should(BeNumerically("==", 2))
				Ω(report["foo"].Largest).Should(BeNumerically("==", 7))
				Ω(report["foo"].Average).Should(BeNumerically("==", 4))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 2.16, 0.01))

				Ω(report["bar"].Name).Should(Equal("bar"))
				Ω(report["bar"].Info).Should(BeNil())
				Ω(report["bar"].SmallestLabel).Should(Equal("Smallest"))
				Ω(report["bar"].Order).Should(Equal(1))
				Ω(report["bar"].LargestLabel).Should(Equal(" Largest"))
				Ω(report["bar"].AverageLabel).Should(Equal(" Average"))
				Ω(report["bar"].Units).Should(Equal("ns"))
				Ω(report["bar"].Results).Should(Equal([]float64{0.3, 0.1, 0.5, 0.7}))
				Ω(report["bar"].Smallest).Should(BeNumerically("==", 0.1))
				Ω(report["bar"].Largest).Should(BeNumerically("==", 0.7))
				Ω(report["bar"].Average).Should(BeNumerically("==", 0.4))
				Ω(report["bar"].StdDeviation).Should(BeNumerically("~", 0.22, 0.01))
			})
		})

		Describe("Time", func() {
			BeforeEach(func() {
				measure = NewMeasureNode("the measurement", func(b Benchmarker) {
					b.Time("foo", func() {
						time.Sleep(200 * time.Millisecond)
					}, "info!")
					b.Time("foo", func() {
						time.Sleep(300 * time.Millisecond)
					})
					b.Time("foo", func() {
						time.Sleep(250 * time.Millisecond)
					})
				}, types.FlagTypeFocused, codelocation.New(0), 1, Failer.New(), 3)
				Ω(measure.Run()).Should(Equal(types.SpecStatePassed))
			})

			It("records passed in values and reports on them", func() {
				report := measure.MeasurementsReport()
				Ω(report).Should(HaveLen(1))
				Ω(report["foo"].Name).Should(Equal("foo"))
				Ω(report["foo"].Info).Should(Equal("info!"))
				Ω(report["foo"].SmallestLabel).Should(Equal("Fastest Time"))
				Ω(report["foo"].LargestLabel).Should(Equal("Slowest Time"))
				Ω(report["foo"].AverageLabel).Should(Equal("Average Time"))
				Ω(report["foo"].Units).Should(Equal("s"))
				Ω(report["foo"].Results).Should(HaveLen(3))
				Ω(report["foo"].Results[0]).Should(BeNumerically("~", 0.2, 0.06))
				Ω(report["foo"].Results[1]).Should(BeNumerically("~", 0.3, 0.06))
				Ω(report["foo"].Results[2]).Should(BeNumerically("~", 0.25, 0.06))
				Ω(report["foo"].Smallest).Should(BeNumerically("~", 0.2, 0.06))
				Ω(report["foo"].Largest).Should(BeNumerically("~", 0.3, 0.06))
				Ω(report["foo"].Average).Should(BeNumerically("~", 0.25, 0.06))
				Ω(report["foo"].StdDeviation).Should(BeNumerically("~", 0.07, 0.04))
			})
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2020 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package logstream

import (
	"bytes"
	"context"
	"os"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	"github.com/google/mtail/internal/logline"
	"github.com/google/mtail/internal/waker"
)

type pipeStream struct {
	ctx   context.Context
	lines chan<- *logline.LogLine

	pathname string // Given name for the underlying named pipe on the filesystem

	mu           sync.RWMutex // protects following fields
	completed    bool         // This pipestream is completed and can no longer be used.
	lastReadTime time.Time    // Last time a log line was read from this named pipe
}

func newPipeStream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, pathname string, fi os.FileInfo, lines chan<- *logline.LogLine) (LogStream, error) {
	ps := &pipeStream{ctx: ctx, pathname: pathname, lastReadTime: time.Now(), lines: lines}
	if err := ps.stream(ctx, wg, waker, fi); err != nil {
		return nil, err
	}
	return ps, nil
}

func (ps *pipeStream) LastReadTime() time.Time {
	ps.mu.RLock()
	defer ps.mu.RUnlock()
	return ps.lastReadTime
}

func (ps *pipeStream) stream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, fi os.FileInfo) error {
	// Open in nonblocking mode because the write end of the pipe may not have started yet.
	fd, err := os.OpenFile(ps.pathname, os.O_RDONLY|syscall.O_NONBLOCK, 0600)
	if err != nil {
		logErrors.Add(ps.pathname, 1)
		return err
	}
	glog.V(2).Infof("opened new pipe %v", fd)

	var total int
	wg.Add(1)
	go func() {
		defer wg.Done()
		defer func() {
			glog.V(2).Infof("%v: read total %d bytes from %s", fd, total, ps.pathname)
			glog.V(2).Infof("%v: closing file descriptor", fd)
			err := fd.Close()
			if err != nil {
				logErrors.Add(ps.pathname, 1)
				glog.Info(err)
			}
			logCloses.Add(ps.pathname, 1)
			ps.mu.Lock()
			ps.completed = true
			ps.mu.Unlock()
		}()
		ctx, cancel := context.WithCancel(ctx)
		defer cancel()
		SetReadDeadlineOnDone(ctx, fd)

		b := make([]byte, 0, defaultReadBufferSize)
		capB := cap(b)
		partial := bytes.NewBufferString("")
		for {
			n, err := fd.Read(b[:capB])
			glog.V(2).Infof("%v: read %d bytes, err is %v", fd, n, err)

			if n > 0 {
				total += n
				decodeAndSend(ps.ctx, ps.lines, ps.pathname, n, b[:n], partial)
				// Update the last read time if we were able to read anything.
				ps.mu.Lock()
				ps.lastReadTime = time.Now()
				ps.mu.Unlock()
			}

			if err != nil && IsEndOrCancel(err) {
				glog.V(2).Infof("%v: %s: exiting", fd, err)
				if partial.Len() > 0 {
					sendLine(ctx, ps.pathname, partial, ps.lines)
				}
				ps.mu.Lock()
				ps.completed = true
				ps.mu.Unlock()
				return
			}

			// Yield and wait
			glog.V(2).Infof("%v: waiting", fd)
			select {
			case <-ctx.Done():
				// Exit immediately; cancelled context is going to cause the
				// next read to be interrupted and exit, so don't bother going
				// around the loop again.
				return
			case <-waker.Wake():
				// sleep until next Wake()
				glog.V(2).Infof("%v: Wake received", fd)
			}
		}
	}()
	return nil
}

func (ps *pipeStream) IsComplete() bool {
	ps.mu.RLock()
	defer ps.mu.RUnlock()
	return ps.completed
}

// Stop implements the Logstream interface.
// Calling Stop on a pipe is a no-op; Pipes always read until the pipe is closed, which is what calling Stop means on a Logstream.
func (ps *pipeStream) Stop() {
}
<commit_msg>Improve debug logs for pipestream.<commit_after>// Copyright 2020 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package logstream

import (
	"bytes"
	"context"
	"os"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	"github.com/google/mtail/internal/logline"
	"github.com/google/mtail/internal/waker"
)

type pipeStream struct {
	ctx   context.Context
	lines chan<- *logline.LogLine

	pathname string // Given name for the underlying named pipe on the filesystem

	mu           sync.RWMutex // protects following fields
	completed    bool         // This pipestream is completed and can no longer be used.
	lastReadTime time.Time    // Last time a log line was read from this named pipe
}

func newPipeStream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, pathname string, fi os.FileInfo, lines chan<- *logline.LogLine) (LogStream, error) {
	ps := &pipeStream{ctx: ctx, pathname: pathname, lastReadTime: time.Now(), lines: lines}
	if err := ps.stream(ctx, wg, waker, fi); err != nil {
		return nil, err
	}
	return ps, nil
}

func (ps *pipeStream) LastReadTime() time.Time {
	ps.mu.RLock()
	defer ps.mu.RUnlock()
	return ps.lastReadTime
}

func (ps *pipeStream) stream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, fi os.FileInfo) error {
	// Open in nonblocking mode because the write end of the pipe may not have started yet.
	fd, err := os.OpenFile(ps.pathname, os.O_RDONLY|syscall.O_NONBLOCK, 0600)
	if err != nil {
		logErrors.Add(ps.pathname, 1)
		return err
	}
	glog.V(2).Infof("opened new pipe %v", fd)

	var total int
	wg.Add(1)
	go func() {
		defer wg.Done()
		defer func() {
			glog.V(2).Infof("%v: read total %d bytes from %s", fd, total, ps.pathname)
			glog.V(2).Infof("%v: closing file descriptor", fd)
			err := fd.Close()
			if err != nil {
				logErrors.Add(ps.pathname, 1)
				glog.Info(err)
			}
			logCloses.Add(ps.pathname, 1)
			ps.mu.Lock()
			ps.completed = true
			ps.mu.Unlock()
		}()
		ctx, cancel := context.WithCancel(ctx)
		defer cancel()
		SetReadDeadlineOnDone(ctx, fd)

		b := make([]byte, 0, defaultReadBufferSize)
		capB := cap(b)
		partial := bytes.NewBufferString("")
		for {
			n, err := fd.Read(b[:capB])
			glog.V(2).Infof("%v: read %d bytes, err is %v", fd, n, err)

			if n > 0 {
				total += n
				decodeAndSend(ps.ctx, ps.lines, ps.pathname, n, b[:n], partial)
				// Update the last read time if we were able to read anything.
				ps.mu.Lock()
				ps.lastReadTime = time.Now()
				ps.mu.Unlock()
			}

			if err != nil && IsEndOrCancel(err) {
				glog.V(2).Infof("%v: %s: exiting", fd, err)
				if partial.Len() > 0 {
					sendLine(ctx, ps.pathname, partial, ps.lines)
				}
				glog.V(2).Infof("%v: exiting, stream has error %s", fd, err)
				ps.mu.Lock()
				ps.completed = true
				ps.mu.Unlock()
				return
			}

			// Yield and wait
			glog.V(2).Infof("%v: waiting", fd)
			select {
			case <-ctx.Done():
				// Exit immediately; cancelled context is going to cause the
				// next read to be interrupted and exit, so don't bother going
				// around the loop again.
				return
			case <-waker.Wake():
				// sleep until next Wake()
				glog.V(2).Infof("%v: Wake received", fd)
			}
		}
	}()
	return nil
}

func (ps *pipeStream) IsComplete() bool {
	ps.mu.RLock()
	defer ps.mu.RUnlock()
	return ps.completed
}

// Stop implements the Logstream interface.
// Calling Stop on a pipe is a no-op; Pipes always read until the pipe is closed, which is what calling Stop means on a Logstream.
func (ps *pipeStream) Stop() {
}
<|endoftext|>


<commit_before>/*
The syslog package provides a syslog client.

Unlike the core log/syslog package it uses the newer rfc5424 syslog protocol,
reliably reconnects on failure, and supports TLS encrypted TCP connections.
*/
package syslog

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"net"
	"time"
)

// A net.Conn with added reconnection logic
type conn struct {
	netConn net.Conn
	errors  chan error
}

// watch watches the connection for error, sends detected error to c.errors
func (c *conn) watch() {
	for {
		data := make([]byte, 1)
		_, err := c.netConn.Read(data)
		if err != nil {
			c.netConn.Close()
			c.errors <- err
			return
		}
	}
}

// reconnectNeeded determines if a reconnect is needed by checking for a
// message on the readErrors channel
func (c *conn) reconnectNeeded() bool {
	if c == nil {
		return true
	}
	select {
	case <-c.errors:
		return true
	default:
		return false
	}
}

// dial connects to the server and set up a watching goroutine
func dial(network, raddr string, rootCAs *x509.CertPool) (*conn, error) {
	var netConn net.Conn
	var err error

	switch network {
	case "tls":
		var config *tls.Config
		if rootCAs != nil {
			config = &tls.Config{RootCAs: rootCAs}
		}
		netConn, err = tls.Dial("tcp", raddr, config)
	case "udp", "tcp":
		netConn, err = net.Dial(network, raddr)
	default:
		return nil, fmt.Errorf("Network protocol %s not supported", network)
	}
	if err != nil {
		return nil, err
	} else {
		c := &conn{netConn, make(chan error)}
		go c.watch()
		return c, nil
	}
}

// A Logger is a connection to a syslog server. It reconnects on error.
// Clients log by sending a Packet to the logger.Packets channel.
type Logger struct {
	conn           *conn
	Packets        chan Packet
	Errors         chan error
	ClientHostname string

	network string
	raddr   string
	rootCAs *x509.CertPool
}

// Dial connects to the syslog server at raddr, using the optional certBundle,
// and launches a goroutine to watch logger.Packets for messages to log.
func Dial(clientHostname, network, raddr string, rootCAs *x509.CertPool) (*Logger, error) {
	// dial once, just to make sure the network is working
	conn, err := dial(network, raddr, rootCAs)

	if err != nil {
		return nil, err
	} else {
		logger := &Logger{
			ClientHostname: clientHostname,
			network:        network,
			raddr:          raddr,
			rootCAs:        rootCAs,
			Packets:        make(chan Packet, 100),
			Errors:         make(chan error, 0),
			conn:           conn,
		}
		go logger.writeLoop()
		return logger, nil
	}
}

// Connect to the server, retrying every 10 seconds until successful.
func (l *Logger) connect() {
	for {
		c, err := dial(l.network, l.raddr, l.rootCAs)
		if err == nil {
			l.conn = c
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
	panic("unreachable")
}

// Send an error to the Error channel, but don't block if nothing is listening
func (l *Logger) handleError(err error) {
	select {
	case l.Errors <- err:
	default:
	}
}

// Write a packet, reconnecting if needed. It is not safe to call this
// method concurrently.
func (l *Logger) writePacket(p Packet) {
	var err error
	for {
		if l.conn.reconnectNeeded() {
			l.connect()
		}

		switch l.conn.netConn.(type) {
		case *net.TCPConn, *tls.Conn:
			_, err = io.WriteString(l.conn.netConn, p.Generate(0)+"\n")
		case *net.UDPConn:
			_, err = io.WriteString(l.conn.netConn, p.Generate(1024))
		default:
			panic(fmt.Errorf("Network protocol %s not supported", l.network))
		}
		if err == nil {
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
}

// writeloop writes any packets recieved on l.Packets() to the syslog server.
func (l *Logger) writeLoop() {
	for p := range l.Packets {
		l.writePacket(p)
	}
}
<commit_msg>Add support for SHA384 and SHA512<commit_after>/*
The syslog package provides a syslog client.

Unlike the core log/syslog package it uses the newer rfc5424 syslog protocol,
reliably reconnects on failure, and supports TLS encrypted TCP connections.
*/
package syslog

import (
	"crypto/tls"
	"crypto/x509"
	_ "crypto/sha512"
	"fmt"
	"io"
	"net"
	"time"
)

// A net.Conn with added reconnection logic
type conn struct {
	netConn net.Conn
	errors  chan error
}

// watch watches the connection for error, sends detected error to c.errors
func (c *conn) watch() {
	for {
		data := make([]byte, 1)
		_, err := c.netConn.Read(data)
		if err != nil {
			c.netConn.Close()
			c.errors <- err
			return
		}
	}
}

// reconnectNeeded determines if a reconnect is needed by checking for a
// message on the readErrors channel
func (c *conn) reconnectNeeded() bool {
	if c == nil {
		return true
	}
	select {
	case <-c.errors:
		return true
	default:
		return false
	}
}

// dial connects to the server and set up a watching goroutine
func dial(network, raddr string, rootCAs *x509.CertPool) (*conn, error) {
	var netConn net.Conn
	var err error

	switch network {
	case "tls":
		var config *tls.Config
		if rootCAs != nil {
			config = &tls.Config{RootCAs: rootCAs}
		}
		netConn, err = tls.Dial("tcp", raddr, config)
	case "udp", "tcp":
		netConn, err = net.Dial(network, raddr)
	default:
		return nil, fmt.Errorf("Network protocol %s not supported", network)
	}
	if err != nil {
		return nil, err
	} else {
		c := &conn{netConn, make(chan error)}
		go c.watch()
		return c, nil
	}
}

// A Logger is a connection to a syslog server. It reconnects on error.
// Clients log by sending a Packet to the logger.Packets channel.
type Logger struct {
	conn           *conn
	Packets        chan Packet
	Errors         chan error
	ClientHostname string

	network string
	raddr   string
	rootCAs *x509.CertPool
}

// Dial connects to the syslog server at raddr, using the optional certBundle,
// and launches a goroutine to watch logger.Packets for messages to log.
func Dial(clientHostname, network, raddr string, rootCAs *x509.CertPool) (*Logger, error) {
	// dial once, just to make sure the network is working
	conn, err := dial(network, raddr, rootCAs)

	if err != nil {
		return nil, err
	} else {
		logger := &Logger{
			ClientHostname: clientHostname,
			network:        network,
			raddr:          raddr,
			rootCAs:        rootCAs,
			Packets:        make(chan Packet, 100),
			Errors:         make(chan error, 0),
			conn:           conn,
		}
		go logger.writeLoop()
		return logger, nil
	}
}

// Connect to the server, retrying every 10 seconds until successful.
func (l *Logger) connect() {
	for {
		c, err := dial(l.network, l.raddr, l.rootCAs)
		if err == nil {
			l.conn = c
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
	panic("unreachable")
}

// Send an error to the Error channel, but don't block if nothing is listening
func (l *Logger) handleError(err error) {
	select {
	case l.Errors <- err:
	default:
	}
}

// Write a packet, reconnecting if needed. It is not safe to call this
// method concurrently.
func (l *Logger) writePacket(p Packet) {
	var err error
	for {
		if l.conn.reconnectNeeded() {
			l.connect()
		}

		switch l.conn.netConn.(type) {
		case *net.TCPConn, *tls.Conn:
			_, err = io.WriteString(l.conn.netConn, p.Generate(0)+"\n")
		case *net.UDPConn:
			_, err = io.WriteString(l.conn.netConn, p.Generate(1024))
		default:
			panic(fmt.Errorf("Network protocol %s not supported", l.network))
		}
		if err == nil {
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
}

// writeloop writes any packets recieved on l.Packets() to the syslog server.
func (l *Logger) writeLoop() {
	for p := range l.Packets {
		l.writePacket(p)
	}
}
<|endoftext|>


<commit_before>package main

// Commands to get/set ACLs.

import (
	"fmt"

	"v.io/core/veyron2/security"
	"v.io/core/veyron2/services/mgmt/device"
	"v.io/core/veyron2/services/security/access"
	verror "v.io/core/veyron2/verror2"
	"v.io/lib/cmdline"
)

var cmdGet = &cmdline.Command{
	Run:      runGet,
	Name:     "get",
	Short:    "Get ACLs for the given target.",
	Long:     "Get ACLs for the given target.",
	ArgsName: "<device manager name>",
	ArgsLong: `
<device manager name> can be a Vanadium name for a device manager,
application installation or instance.`,
}

func runGet(cmd *cmdline.Command, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return cmd.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
	}

	vanaName := args[0]
	objACL, _, err := device.ApplicationClient(vanaName).GetACL(gctx)
	if err != nil {
		return fmt.Errorf("GetACL on %s failed: %v", vanaName, err)
	}
	// Convert objACL (TaggedACLMap) into aclEntries for pretty printing.
	entries := make(aclEntries)
	for tag, acl := range objACL {
		for _, p := range acl.In {
			entries.Tags(string(p))[tag] = false
		}
		for _, b := range acl.NotIn {
			entries.Tags(b)[tag] = true
		}
	}
	fmt.Fprintf(cmd.Stdout(), "%v", entries)
	return nil
}

var cmdSet = &cmdline.Command{
	Run:      runSet,
	Name:     "set",
	Short:    "Set ACLs for the given target.",
	Long:     "Set ACLs for the given target",
	ArgsName: "<device manager name>  (<blessing> [!]<tag>(,[!]<tag>)*",
	ArgsLong: `
<device manager name> can be a Vanadium name for a device manager,
application installation or instance.

<blessing> is a blessing pattern.
If the same pattern is repeated multiple times in the command, then
the only the last occurrence will be honored.

<tag> is a subset of defined access types ("Admin", "Read", "Write" etc.).
If the access right is prefixed with a '!' then <blessing> is added to the
NotIn list for that right. Using "^" as a "tag" causes all occurrences of
<blessing> in the current ACL to be cleared.

Examples:
set root/self ^
will remove "root/self" from the In and NotIn lists for all access rights.

set root/self Read,!Write
will add "root/self" to the In list for Read access and the NotIn list
for Write access (and remove "root/self" from both the In and NotIn
lists of all other access rights)`,
}

func runSet(cmd *cmdline.Command, args []string) error {
	if got := len(args); !((got%2) == 1 && got >= 3) {
		return cmd.UsageErrorf("set: incorrect number of arguments %d, must be 1 + 2n", got)
	}

	vanaName := args[0]
	pairs := args[1:]

	entries := make(aclEntries)
	for i := 0; i < len(pairs); i += 2 {
		blessing := pairs[i]
		tags, err := parseAccessTags(pairs[i+1])
		if err != nil {
			return cmd.UsageErrorf("failed to parse access tags for %q: %v", blessing, err)
		}
		entries[blessing] = tags
	}

	// Set the ACLs on the specified names.
	for {
		objACL, etag, err := device.ApplicationClient(vanaName).GetACL(gctx)
		if err != nil {
			return cmd.UsageErrorf("GetACL(%s) failed: %v", vanaName, err)
		}
		for blessingOrPattern, tags := range entries {
			objACL.Clear(blessingOrPattern) // Clear out any existing references
			for tag, blacklist := range tags {
				if blacklist {
					objACL.Blacklist(blessingOrPattern, tag)
				} else {
					objACL.Add(security.BlessingPattern(blessingOrPattern), tag)
				}
			}
		}
		switch err := device.ApplicationClient(vanaName).SetACL(gctx, objACL, etag); {
		case err != nil && !verror.Is(err, access.ErrBadEtag):
			return cmd.UsageErrorf("SetACL(%s) failed: %v", vanaName, err)
		case err == nil:
			return nil
		}
		fmt.Fprintf(cmd.Stderr(), "WARNING: trying again because of asynchronous change\n")
	}
	return nil
}

func aclRoot() *cmdline.Command {
	return &cmdline.Command{
		Name:  "acl",
		Short: "Tool for setting device manager ACLs",
		Long: `
The acl tool manages ACLs on the device manger, installations and instances.
`,
		Children: []*cmdline.Command{cmdGet, cmdSet},
	}
}
<commit_msg>veyron/tools/mgmt/device: Add missing \n<commit_after>package main

// Commands to get/set ACLs.

import (
	"fmt"

	"v.io/core/veyron2/security"
	"v.io/core/veyron2/services/mgmt/device"
	"v.io/core/veyron2/services/security/access"
	verror "v.io/core/veyron2/verror2"
	"v.io/lib/cmdline"
)

var cmdGet = &cmdline.Command{
	Run:      runGet,
	Name:     "get",
	Short:    "Get ACLs for the given target.",
	Long:     "Get ACLs for the given target.",
	ArgsName: "<device manager name>",
	ArgsLong: `
<device manager name> can be a Vanadium name for a device manager,
application installation or instance.`,
}

func runGet(cmd *cmdline.Command, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return cmd.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
	}

	vanaName := args[0]
	objACL, _, err := device.ApplicationClient(vanaName).GetACL(gctx)
	if err != nil {
		return fmt.Errorf("GetACL on %s failed: %v", vanaName, err)
	}
	// Convert objACL (TaggedACLMap) into aclEntries for pretty printing.
	entries := make(aclEntries)
	for tag, acl := range objACL {
		for _, p := range acl.In {
			entries.Tags(string(p))[tag] = false
		}
		for _, b := range acl.NotIn {
			entries.Tags(b)[tag] = true
		}
	}
	fmt.Fprintln(cmd.Stdout(), entries)
	return nil
}

var cmdSet = &cmdline.Command{
	Run:      runSet,
	Name:     "set",
	Short:    "Set ACLs for the given target.",
	Long:     "Set ACLs for the given target",
	ArgsName: "<device manager name>  (<blessing> [!]<tag>(,[!]<tag>)*",
	ArgsLong: `
<device manager name> can be a Vanadium name for a device manager,
application installation or instance.

<blessing> is a blessing pattern.
If the same pattern is repeated multiple times in the command, then
the only the last occurrence will be honored.

<tag> is a subset of defined access types ("Admin", "Read", "Write" etc.).
If the access right is prefixed with a '!' then <blessing> is added to the
NotIn list for that right. Using "^" as a "tag" causes all occurrences of
<blessing> in the current ACL to be cleared.

Examples:
set root/self ^
will remove "root/self" from the In and NotIn lists for all access rights.

set root/self Read,!Write
will add "root/self" to the In list for Read access and the NotIn list
for Write access (and remove "root/self" from both the In and NotIn
lists of all other access rights)`,
}

func runSet(cmd *cmdline.Command, args []string) error {
	if got := len(args); !((got%2) == 1 && got >= 3) {
		return cmd.UsageErrorf("set: incorrect number of arguments %d, must be 1 + 2n", got)
	}

	vanaName := args[0]
	pairs := args[1:]

	entries := make(aclEntries)
	for i := 0; i < len(pairs); i += 2 {
		blessing := pairs[i]
		tags, err := parseAccessTags(pairs[i+1])
		if err != nil {
			return cmd.UsageErrorf("failed to parse access tags for %q: %v", blessing, err)
		}
		entries[blessing] = tags
	}

	// Set the ACLs on the specified names.
	for {
		objACL, etag, err := device.ApplicationClient(vanaName).GetACL(gctx)
		if err != nil {
			return cmd.UsageErrorf("GetACL(%s) failed: %v", vanaName, err)
		}
		for blessingOrPattern, tags := range entries {
			objACL.Clear(blessingOrPattern) // Clear out any existing references
			for tag, blacklist := range tags {
				if blacklist {
					objACL.Blacklist(blessingOrPattern, tag)
				} else {
					objACL.Add(security.BlessingPattern(blessingOrPattern), tag)
				}
			}
		}
		switch err := device.ApplicationClient(vanaName).SetACL(gctx, objACL, etag); {
		case err != nil && !verror.Is(err, access.ErrBadEtag):
			return cmd.UsageErrorf("SetACL(%s) failed: %v", vanaName, err)
		case err == nil:
			return nil
		}
		fmt.Fprintln(cmd.Stderr(), "WARNING: trying again because of asynchronous change")
	}
	return nil
}

func aclRoot() *cmdline.Command {
	return &cmdline.Command{
		Name:  "acl",
		Short: "Tool for setting device manager ACLs",
		Long: `
The acl tool manages ACLs on the device manger, installations and instances.
`,
		Children: []*cmdline.Command{cmdGet, cmdSet},
	}
}
<|endoftext|>