<commit_before>package btcwallet

import (
	"encoding/hex"
	"errors"
	"fmt"

	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"

	"github.com/btcsuite/btcwallet/chain"
	"github.com/lightninglabs/neutrino"
	"github.com/lightninglabs/neutrino/headerfs"
	"github.com/lightningnetwork/lnd/lnwallet"
)

var (
	// ErrOutputSpent is returned by the GetUtxo method if the target output
	// for lookup has already been spent.
	ErrOutputSpent = errors.New("target output has been spent")

	// ErrOutputNotFound signals that the desired output could not be
	// located.
	ErrOutputNotFound = errors.New("target output was not found")
)

// GetBestBlock returns the current height and hash of the best known block
// within the main chain.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBestBlock() (*chainhash.Hash, int32, error) {
	return b.chain.GetBestBlock()
}

// GetUtxo returns the original output referenced by the passed outpoint that
// creates the target pkScript.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetUtxo(op *wire.OutPoint, pkScript []byte,
	heightHint uint32, cancel <-chan struct{}) (*wire.TxOut, error) {

	switch backend := b.chain.(type) {

	case *chain.NeutrinoClient:
		spendReport, err := backend.CS.GetUtxo(
			neutrino.WatchInputs(neutrino.InputWithScript{
				OutPoint: *op,
				PkScript: pkScript,
			}),
			neutrino.StartBlock(&headerfs.BlockStamp{
				Height: int32(heightHint),
			}),
			neutrino.QuitChan(cancel),
		)
		if err != nil {
			return nil, err
		}

		// If the spend report is nil, then the output was not found in
		// the rescan.
		if spendReport == nil {
			return nil, ErrOutputNotFound
		}

		// If the spending transaction is populated in the spend report,
		// this signals that the output has already been spent.
		if spendReport.SpendingTx != nil {
			return nil, ErrOutputSpent
		}

		// Otherwise, the output is assumed to be in the UTXO.
		return spendReport.Output, nil

	case *chain.RPCClient:
		txout, err := backend.GetTxOut(&op.Hash, op.Index, false)
		if err != nil {
			return nil, err
		} else if txout == nil {
			return nil, ErrOutputSpent
		}

		pkScript, err := hex.DecodeString(txout.ScriptPubKey.Hex)
		if err != nil {
			return nil, err
		}

		// We'll ensure we properly convert the amount given in BTC to
		// satoshis.
		amt, err := btcutil.NewAmount(txout.Value)
		if err != nil {
			return nil, err
		}

		return &wire.TxOut{
			Value:    int64(amt),
			PkScript: pkScript,
		}, nil

	case *chain.BitcoindClient:
		txout, err := backend.GetTxOut(&op.Hash, op.Index, false)
		if err != nil {
			return nil, err
		} else if txout == nil {
			return nil, ErrOutputSpent
		}

		pkScript, err := hex.DecodeString(txout.ScriptPubKey.Hex)
		if err != nil {
			return nil, err
		}

		// Sadly, gettxout returns the output value in BTC instead of
		// satoshis.
		amt, err := btcutil.NewAmount(txout.Value)
		if err != nil {
			return nil, err
		}

		return &wire.TxOut{
			Value:    int64(amt),
			PkScript: pkScript,
		}, nil

	default:
		return nil, fmt.Errorf("unknown backend")
	}
}

// GetBlock returns a raw block from the server given its hash.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
	return b.blockCache.GetBlock(blockHash, b.chain.GetBlock)
}

// GetBlockHash returns the hash of the block in the best blockchain at the
// given height.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
	return b.chain.GetBlockHash(blockHeight)
}

// A compile time check to ensure that BtcWallet implements the BlockChainIO
// interface.
var _ lnwallet.WalletController = (*BtcWallet)(nil)
<commit_msg>btcwallet: lock blockcache for Neutrino GetBlock<commit_after>package btcwallet

import (
	"encoding/hex"
	"errors"
	"fmt"

	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
	"github.com/btcsuite/btcwallet/chain"
	"github.com/lightninglabs/neutrino"
	"github.com/lightninglabs/neutrino/headerfs"
	"github.com/lightningnetwork/lnd/lntypes"
	"github.com/lightningnetwork/lnd/lnwallet"
)

var (
	// ErrOutputSpent is returned by the GetUtxo method if the target output
	// for lookup has already been spent.
	ErrOutputSpent = errors.New("target output has been spent")

	// ErrOutputNotFound signals that the desired output could not be
	// located.
	ErrOutputNotFound = errors.New("target output was not found")
)

// GetBestBlock returns the current height and hash of the best known block
// within the main chain.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBestBlock() (*chainhash.Hash, int32, error) {
	return b.chain.GetBestBlock()
}

// GetUtxo returns the original output referenced by the passed outpoint that
// creates the target pkScript.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetUtxo(op *wire.OutPoint, pkScript []byte,
	heightHint uint32, cancel <-chan struct{}) (*wire.TxOut, error) {

	switch backend := b.chain.(type) {

	case *chain.NeutrinoClient:
		spendReport, err := backend.CS.GetUtxo(
			neutrino.WatchInputs(neutrino.InputWithScript{
				OutPoint: *op,
				PkScript: pkScript,
			}),
			neutrino.StartBlock(&headerfs.BlockStamp{
				Height: int32(heightHint),
			}),
			neutrino.QuitChan(cancel),
		)
		if err != nil {
			return nil, err
		}

		// If the spend report is nil, then the output was not found in
		// the rescan.
		if spendReport == nil {
			return nil, ErrOutputNotFound
		}

		// If the spending transaction is populated in the spend report,
		// this signals that the output has already been spent.
		if spendReport.SpendingTx != nil {
			return nil, ErrOutputSpent
		}

		// Otherwise, the output is assumed to be in the UTXO.
		return spendReport.Output, nil

	case *chain.RPCClient:
		txout, err := backend.GetTxOut(&op.Hash, op.Index, false)
		if err != nil {
			return nil, err
		} else if txout == nil {
			return nil, ErrOutputSpent
		}

		pkScript, err := hex.DecodeString(txout.ScriptPubKey.Hex)
		if err != nil {
			return nil, err
		}

		// We'll ensure we properly convert the amount given in BTC to
		// satoshis.
		amt, err := btcutil.NewAmount(txout.Value)
		if err != nil {
			return nil, err
		}

		return &wire.TxOut{
			Value:    int64(amt),
			PkScript: pkScript,
		}, nil

	case *chain.BitcoindClient:
		txout, err := backend.GetTxOut(&op.Hash, op.Index, false)
		if err != nil {
			return nil, err
		} else if txout == nil {
			return nil, ErrOutputSpent
		}

		pkScript, err := hex.DecodeString(txout.ScriptPubKey.Hex)
		if err != nil {
			return nil, err
		}

		// Sadly, gettxout returns the output value in BTC instead of
		// satoshis.
		amt, err := btcutil.NewAmount(txout.Value)
		if err != nil {
			return nil, err
		}

		return &wire.TxOut{
			Value:    int64(amt),
			PkScript: pkScript,
		}, nil

	default:
		return nil, fmt.Errorf("unknown backend")
	}
}

// GetBlock returns a raw block from the server given its hash. For the Neutrino
// implementation of the lnwallet.BlockChainIO interface, the Neutrino GetBlock
// method is called directly. For other implementations, the block cache is used
// to wrap the call to GetBlock.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
	_, ok := b.chain.(*chain.NeutrinoClient)
	if !ok {
		return b.blockCache.GetBlock(blockHash, b.chain.GetBlock)
	}

	// For the neutrino implementation of lnwallet.BlockChainIO the neutrino
	// GetBlock function can be called directly since it uses the same block
	// cache. However, it does not lock the block cache mutex for the given
	// block hash and so that is done here.
	b.blockCache.HashMutex.Lock(lntypes.Hash(*blockHash))
	defer b.blockCache.HashMutex.Unlock(lntypes.Hash(*blockHash))

	return b.chain.GetBlock(blockHash)
}

// GetBlockHash returns the hash of the block in the best blockchain at the
// given height.
//
// This method is a part of the lnwallet.BlockChainIO interface.
func (b *BtcWallet) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
	return b.chain.GetBlockHash(blockHeight)
}

// A compile time check to ensure that BtcWallet implements the BlockChainIO
// interface.
var _ lnwallet.WalletController = (*BtcWallet)(nil)
<|endoftext|>


<commit_before>package main

import (
	"github.com/codegangsta/cli"
)

func listUnits(c *cli.Context) {
	println("UNIT\tLOAD\tACTIVE\tSUB\tDESC\tMACHINE")
}
<commit_msg>feat(cmd): list units lists things, maybe?<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"

	"github.com/coreos/coreinit/registry"
)

func listUnits(c *cli.Context) {
	r := registry.New()

	machines := r.GetActiveMachines()

	println("UNIT\tLOAD\tACTIVE\tSUB\tDESC\tMACHINE")

	for _, m := range machines {
		for _, j := range r.GetMachineJobs(&m) {
			fmt.Printf("%s\t\t\t\t\t%s\n", j.Name, m.String())
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Copyright (C) 2015-2017 The Lightning Network Developers

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	macaroon "gopkg.in/macaroon.v2"

	"github.com/btcsuite/btcutil"
	"github.com/lightningnetwork/lnd/lncfg"
	"github.com/lightningnetwork/lnd/lnrpc"
	"github.com/lightningnetwork/lnd/macaroons"
	"github.com/urfave/cli"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

const (
	defaultTLSCertFilename  = "tls.cert"
	defaultMacaroonFilename = "admin.macaroon"
	defaultRPCPort          = "10009"
	defaultRPCHostPort      = "localhost:" + defaultRPCPort
)

var (
	//Commit stores the current commit hash of this build. This should be
	//set using -ldflags during compilation.
	Commit string

	defaultLndDir       = btcutil.AppDataDir("lnd", false)
	defaultTLSCertPath  = filepath.Join(defaultLndDir, defaultTLSCertFilename)
	defaultMacaroonPath = filepath.Join(defaultLndDir, defaultMacaroonFilename)
)

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "[lncli] %v\n", err)
	os.Exit(1)
}

func getWalletUnlockerClient(ctx *cli.Context) (lnrpc.WalletUnlockerClient, func()) {
	conn := getClientConn(ctx, true)

	cleanUp := func() {
		conn.Close()
	}

	return lnrpc.NewWalletUnlockerClient(conn), cleanUp
}

func getClient(ctx *cli.Context) (lnrpc.LightningClient, func()) {
	conn := getClientConn(ctx, false)

	cleanUp := func() {
		conn.Close()
	}

	return lnrpc.NewLightningClient(conn), cleanUp
}

func getClientConn(ctx *cli.Context, skipMacaroons bool) *grpc.ClientConn {
	lndDir := cleanAndExpandPath(ctx.GlobalString("lnddir"))
	if lndDir != defaultLndDir {
		// If a custom lnd directory was set, we'll also check if custom
		// paths for the TLS cert and macaroon file were set as well. If
		// not, we'll override their paths so they can be found within
		// the custom lnd directory set. This allows us to set a custom
		// lnd directory, along with custom paths to the TLS cert and
		// macaroon file.
		tlsCertPath := cleanAndExpandPath(ctx.GlobalString("tlscertpath"))
		if tlsCertPath == defaultTLSCertPath {
			ctx.GlobalSet("tlscertpath",
				filepath.Join(lndDir, defaultTLSCertFilename))
		}

		macPath := cleanAndExpandPath(ctx.GlobalString("macaroonpath"))
		if macPath == defaultMacaroonPath {
			ctx.GlobalSet("macaroonpath",
				filepath.Join(lndDir, defaultMacaroonFilename))
		}
	}

	// Load the specified TLS certificate and build transport credentials
	// with it.
	tlsCertPath := cleanAndExpandPath(ctx.GlobalString("tlscertpath"))
	creds, err := credentials.NewClientTLSFromFile(tlsCertPath, "")
	if err != nil {
		fatal(err)
	}

	// Create a dial options array.
	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(creds),
	}

	// Only process macaroon credentials if --no-macaroons isn't set and
	// if we're not skipping macaroon processing.
	if !ctx.GlobalBool("no-macaroons") && !skipMacaroons {
		// Load the specified macaroon file.
		macPath := cleanAndExpandPath(ctx.GlobalString("macaroonpath"))
		macBytes, err := ioutil.ReadFile(macPath)
		if err != nil {
			fatal(err)
		}
		mac := &macaroon.Macaroon{}
		if err = mac.UnmarshalBinary(macBytes); err != nil {
			fatal(err)
		}

		macConstraints := []macaroons.Constraint{
			// We add a time-based constraint to prevent replay of the
			// macaroon. It's good for 60 seconds by default to make up for
			// any discrepancy between client and server clocks, but leaking
			// the macaroon before it becomes invalid makes it possible for
			// an attacker to reuse the macaroon. In addition, the validity
			// time of the macaroon is extended by the time the server clock
			// is behind the client clock, or shortened by the time the
			// server clock is ahead of the client clock (or invalid
			// altogether if, in the latter case, this time is more than 60
			// seconds).
			// TODO(aakselrod): add better anti-replay protection.
			macaroons.TimeoutConstraint(ctx.GlobalInt64("macaroontimeout")),

			// Lock macaroon down to a specific IP address.
			macaroons.IPLockConstraint(ctx.GlobalString("macaroonip")),

			// ... Add more constraints if needed.
		}

		// Apply constraints to the macaroon.
		constrainedMac, err := macaroons.AddConstraints(mac, macConstraints...)
		if err != nil {
			fatal(err)
		}

		// Now we append the macaroon credentials to the dial options.
		cred := macaroons.NewMacaroonCredential(constrainedMac)
		opts = append(opts, grpc.WithPerRPCCredentials(cred))
	}

	// We need to use a custom dialer so we can also connect to unix sockets
	// and not just TCP addresses.
	opts = append(
		opts, grpc.WithDialer(
			lncfg.ClientAddressDialer(defaultRPCPort),
		),
	)
	conn, err := grpc.Dial(ctx.GlobalString("rpcserver"), opts...)
	if err != nil {
		fatal(err)
	}

	return conn
}

func main() {
	app := cli.NewApp()
	app.Name = "lncli"
	app.Version = fmt.Sprintf("%s commit=%s", "0.4.2", Commit)
	app.Usage = "control plane for your Lightning Network Daemon (lnd)"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "rpcserver",
			Value: defaultRPCHostPort,
			Usage: "host:port of ln daemon",
		},
		cli.StringFlag{
			Name:  "lnddir",
			Value: defaultLndDir,
			Usage: "path to lnd's base directory",
		},
		cli.StringFlag{
			Name:  "tlscertpath",
			Value: defaultTLSCertPath,
			Usage: "path to TLS certificate",
		},
		cli.StringFlag{
			Name:  "chain, c",
			Usage: "the chain lnd is running on e.g. bitcoin",
			Value: "bitcoin",
		},
		cli.StringFlag{
			Name: "network, n",
			Usage: "the network lnd is running on e.g. mainnet, " +
				"testnet, etc.",
			Value: "mainnet",
		},
		cli.BoolFlag{
			Name:  "no-macaroons",
			Usage: "disable macaroon authentication",
		},
		cli.StringFlag{
			Name:  "macaroonpath",
			Value: defaultMacaroonPath,
			Usage: "path to macaroon file",
		},
		cli.Int64Flag{
			Name:  "macaroontimeout",
			Value: 60,
			Usage: "anti-replay macaroon validity time in seconds",
		},
		cli.StringFlag{
			Name:  "macaroonip",
			Usage: "if set, lock macaroon to specific IP address",
		},
	}
	app.Commands = []cli.Command{
		createCommand,
		unlockCommand,
		changePasswordCommand,
		newAddressCommand,
		sendManyCommand,
		sendCoinsCommand,
		connectCommand,
		disconnectCommand,
		openChannelCommand,
		closeChannelCommand,
		closeAllChannelsCommand,
		listPeersCommand,
		walletBalanceCommand,
		channelBalanceCommand,
		getInfoCommand,
		pendingChannelsCommand,
		sendPaymentCommand,
		payInvoiceCommand,
		sendToRouteCommand,
		addInvoiceCommand,
		lookupInvoiceCommand,
		listInvoicesCommand,
		listChannelsCommand,
		closedChannelsCommand,
		listPaymentsCommand,
		describeGraphCommand,
		getChanInfoCommand,
		getNodeInfoCommand,
		queryRoutesCommand,
		getNetworkInfoCommand,
		debugLevelCommand,
		decodePayReqCommand,
		listChainTxnsCommand,
		stopCommand,
		signMessageCommand,
		verifyMessageCommand,
		feeReportCommand,
		updateChannelPolicyCommand,
		forwardingHistoryCommand,
	}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// cleanAndExpandPath expands environment variables and leading ~ in the
// passed path, cleans the result, and returns it.
// This function is taken from https://github.com/btcsuite/btcd
func cleanAndExpandPath(path string) string {
	if path == "" {
		return ""
	}

	// Expand initial ~ to OS specific home directory.
	if strings.HasPrefix(path, "~") {
		var homeDir string
		user, err := user.Current()
		if err == nil {
			homeDir = user.HomeDir
		} else {
			homeDir = os.Getenv("HOME")
		}

		path = strings.Replace(path, "~", homeDir, 1)
	}

	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
	// but the variables can still be expanded via POSIX-style $VARIABLE.
	return filepath.Clean(os.ExpandEnv(path))
}
<commit_msg>cmd/lncli: retrieve the macaroon for the current chain and network<commit_after>// Copyright (c) 2013-2017 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Copyright (C) 2015-2017 The Lightning Network Developers

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	macaroon "gopkg.in/macaroon.v2"

	"github.com/btcsuite/btcutil"
	"github.com/lightningnetwork/lnd/lncfg"
	"github.com/lightningnetwork/lnd/lnrpc"
	"github.com/lightningnetwork/lnd/macaroons"
	"github.com/urfave/cli"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

const (
	defaultDataDir          = "data"
	defaultChainSubDir      = "chain"
	defaultTLSCertFilename  = "tls.cert"
	defaultMacaroonFilename = "admin.macaroon"
	defaultRPCPort          = "10009"
	defaultRPCHostPort      = "localhost:" + defaultRPCPort
)

var (
	// Commit stores the current commit hash of this build. This should be
	// set using -ldflags during compilation.
	Commit string

	defaultLndDir      = btcutil.AppDataDir("lnd", false)
	defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename)
)

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "[lncli] %v\n", err)
	os.Exit(1)
}

func getWalletUnlockerClient(ctx *cli.Context) (lnrpc.WalletUnlockerClient, func()) {
	conn := getClientConn(ctx, true)

	cleanUp := func() {
		conn.Close()
	}

	return lnrpc.NewWalletUnlockerClient(conn), cleanUp
}

func getClient(ctx *cli.Context) (lnrpc.LightningClient, func()) {
	conn := getClientConn(ctx, false)

	cleanUp := func() {
		conn.Close()
	}

	return lnrpc.NewLightningClient(conn), cleanUp
}

func getClientConn(ctx *cli.Context, skipMacaroons bool) *grpc.ClientConn {
	// First, we'll parse the args from the command.
	tlsCertPath, macPath := parseArgs(ctx)

	// Load the specified TLS certificate and build transport credentials
	// with it.
	creds, err := credentials.NewClientTLSFromFile(tlsCertPath, "")
	if err != nil {
		fatal(err)
	}

	// Create a dial options array.
	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(creds),
	}

	// Only process macaroon credentials if --no-macaroons isn't set and
	// if we're not skipping macaroon processing.
	if !ctx.GlobalBool("no-macaroons") && !skipMacaroons {
		// Load the specified macaroon file.
		macBytes, err := ioutil.ReadFile(macPath)
		if err != nil {
			fatal(err)
		}
		mac := &macaroon.Macaroon{}
		if err = mac.UnmarshalBinary(macBytes); err != nil {
			fatal(err)
		}

		macConstraints := []macaroons.Constraint{
			// We add a time-based constraint to prevent replay of the
			// macaroon. It's good for 60 seconds by default to make up for
			// any discrepancy between client and server clocks, but leaking
			// the macaroon before it becomes invalid makes it possible for
			// an attacker to reuse the macaroon. In addition, the validity
			// time of the macaroon is extended by the time the server clock
			// is behind the client clock, or shortened by the time the
			// server clock is ahead of the client clock (or invalid
			// altogether if, in the latter case, this time is more than 60
			// seconds).
			// TODO(aakselrod): add better anti-replay protection.
			macaroons.TimeoutConstraint(ctx.GlobalInt64("macaroontimeout")),

			// Lock macaroon down to a specific IP address.
			macaroons.IPLockConstraint(ctx.GlobalString("macaroonip")),

			// ... Add more constraints if needed.
		}

		// Apply constraints to the macaroon.
		constrainedMac, err := macaroons.AddConstraints(mac, macConstraints...)
		if err != nil {
			fatal(err)
		}

		// Now we append the macaroon credentials to the dial options.
		cred := macaroons.NewMacaroonCredential(constrainedMac)
		opts = append(opts, grpc.WithPerRPCCredentials(cred))
	}

	// We need to use a custom dialer so we can also connect to unix sockets
	// and not just TCP addresses.
	opts = append(
		opts, grpc.WithDialer(
			lncfg.ClientAddressDialer(defaultRPCPort),
		),
	)
	conn, err := grpc.Dial(ctx.GlobalString("rpcserver"), opts...)
	if err != nil {
		fatal(err)
	}

	return conn
}

// parseArgs parses the TLS certificate and macaroon paths from the command.
func parseArgs(ctx *cli.Context) (string, string) {
	// We'll start off by parsing the active chain and network. These are
	// needed to determine the correct path to the macaroon when not
	// specified.
	chain := strings.ToLower(ctx.GlobalString("chain"))
	switch chain {
	case "bitcoin", "litecoin":
	default:
		err := fmt.Errorf("unknown chain: %v", chain)
		fatal(err)
	}

	network := strings.ToLower(ctx.GlobalString("network"))
	switch network {
	case "mainnet", "testnet", "regtest", "simnet":
	default:
		err := fmt.Errorf("unknown network: %v", network)
		fatal(err)
	}

	var tlsCertPath, macPath string
	lndDir := cleanAndExpandPath(ctx.GlobalString("lnddir"))
	if lndDir != defaultLndDir {
		// If a custom lnd directory was set, we'll also check if custom
		// paths for the TLS cert and macaroon file were set as well. If
		// not, we'll override their paths so they can be found within
		// the custom lnd directory set. This allows us to set a custom
		// lnd directory, along with custom paths to the TLS cert and
		// macaroon file.
		tlsCertPath = cleanAndExpandPath(ctx.GlobalString("tlscertpath"))
		if tlsCertPath == defaultTLSCertPath {
			tlsCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
		}

		macPath = cleanAndExpandPath(ctx.GlobalString("macaroonpath"))
		if macPath == "" {
			macPath = filepath.Join(
				lndDir, defaultDataDir, defaultChainSubDir,
				chain, network, defaultMacaroonFilename,
			)
		}
	}

	return tlsCertPath, macPath
}

func main() {
	app := cli.NewApp()
	app.Name = "lncli"
	app.Version = fmt.Sprintf("%s commit=%s", "0.4.2", Commit)
	app.Usage = "control plane for your Lightning Network Daemon (lnd)"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "rpcserver",
			Value: defaultRPCHostPort,
			Usage: "host:port of ln daemon",
		},
		cli.StringFlag{
			Name:  "lnddir",
			Value: defaultLndDir,
			Usage: "path to lnd's base directory",
		},
		cli.StringFlag{
			Name:  "tlscertpath",
			Value: defaultTLSCertPath,
			Usage: "path to TLS certificate",
		},
		cli.StringFlag{
			Name:  "chain, c",
			Usage: "the chain lnd is running on e.g. bitcoin",
			Value: "bitcoin",
		},
		cli.StringFlag{
			Name: "network, n",
			Usage: "the network lnd is running on e.g. mainnet, " +
				"testnet, etc.",
			Value: "mainnet",
		},
		cli.BoolFlag{
			Name:  "no-macaroons",
			Usage: "disable macaroon authentication",
		},
		cli.StringFlag{
			Name:  "macaroonpath",
			Usage: "path to macaroon file",
		},
		cli.Int64Flag{
			Name:  "macaroontimeout",
			Value: 60,
			Usage: "anti-replay macaroon validity time in seconds",
		},
		cli.StringFlag{
			Name:  "macaroonip",
			Usage: "if set, lock macaroon to specific IP address",
		},
	}
	app.Commands = []cli.Command{
		createCommand,
		unlockCommand,
		changePasswordCommand,
		newAddressCommand,
		sendManyCommand,
		sendCoinsCommand,
		connectCommand,
		disconnectCommand,
		openChannelCommand,
		closeChannelCommand,
		closeAllChannelsCommand,
		listPeersCommand,
		walletBalanceCommand,
		channelBalanceCommand,
		getInfoCommand,
		pendingChannelsCommand,
		sendPaymentCommand,
		payInvoiceCommand,
		sendToRouteCommand,
		addInvoiceCommand,
		lookupInvoiceCommand,
		listInvoicesCommand,
		listChannelsCommand,
		closedChannelsCommand,
		listPaymentsCommand,
		describeGraphCommand,
		getChanInfoCommand,
		getNodeInfoCommand,
		queryRoutesCommand,
		getNetworkInfoCommand,
		debugLevelCommand,
		decodePayReqCommand,
		listChainTxnsCommand,
		stopCommand,
		signMessageCommand,
		verifyMessageCommand,
		feeReportCommand,
		updateChannelPolicyCommand,
		forwardingHistoryCommand,
	}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// cleanAndExpandPath expands environment variables and leading ~ in the
// passed path, cleans the result, and returns it.
// This function is taken from https://github.com/btcsuite/btcd
func cleanAndExpandPath(path string) string {
	if path == "" {
		return ""
	}

	// Expand initial ~ to OS specific home directory.
	if strings.HasPrefix(path, "~") {
		var homeDir string
		user, err := user.Current()
		if err == nil {
			homeDir = user.HomeDir
		} else {
			homeDir = os.Getenv("HOME")
		}

		path = strings.Replace(path, "~", homeDir, 1)
	}

	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
	// but the variables can still be expanded via POSIX-style $VARIABLE.
	return filepath.Clean(os.ExpandEnv(path))
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	term "github.com/buger/goterm"
	"github.com/mobingilabs/mocli/client"
	"github.com/mobingilabs/mocli/pkg/check"
	"github.com/mobingilabs/mocli/pkg/cli"
	d "github.com/mobingilabs/mocli/pkg/debug"
	"github.com/mobingilabs/mocli/pkg/pretty"
	"github.com/mobingilabs/mocli/pkg/stack"
	"github.com/spf13/cobra"
)

func StackListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "list",
		Short: "list all stacks",
		Long: `List all stacks. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.

Valid format values: min (default), text, json

For now, the 'min' format option cannot yet write to a file
using the '--out=[filename]' option. You need to specify either
'text' or 'json'.

Examples:

  $ mocli stack list
  $ mocli stack list --fmt=text
  $ mocli stack list --fmt=json`,
		Run: stackList,
	}

	return cmd
}

func stackList(cmd *cobra.Command, args []string) {
	c := client.NewClient(client.NewApiConfig(cmd))
	body, err := c.GetStack()
	check.ErrorExit(err, 1)

	var stacks []stack.ListStack
	err = json.Unmarshal(body, &stacks)
	check.ErrorExit(err, 1)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "text":
		indent := cli.GetCliIntFlag(cmd, "indent")
		stack.PrintR(os.Stdout, &stacks[0], 0, indent)

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			fp, err := os.Create(f)
			check.ErrorExit(err, 1)

			defer fp.Close()
			w := bufio.NewWriter(fp)
			defer w.Flush()
			stack.PrintR(w, &stacks[0], 0, indent)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		mi, err := json.MarshalIndent(stacks, "", pretty.Indent(indent))
		check.ErrorExit(err, 1)

		fmt.Println(string(mi))

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, mi, 0644)
			check.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	default:
		if pfmt == "min" || pfmt == "" {
			stbl := term.NewTable(0, 10, 5, ' ', 0)
			fmt.Fprintf(stbl, "STACK ID\tSTACK NAME\tPLATFORM\tSTATUS\tREGION\tLAUNCHED\n")
			for _, s := range stacks {
				timestr := s.CreateTime
				t, err := time.Parse(time.RFC3339, s.CreateTime)
				if err == nil {
					timestr = t.Format(time.RFC1123)
				}

				platform := "?"
				if s.Configuration.AWS != "" {
					platform = "AWS"
				}

				fmt.Fprintf(stbl, "%s\t%s\t%s\t%s\t%s\t%s\n",
					s.StackId,
					s.Nickname,
					platform,
					s.StackStatus,
					s.Configuration.Region,
					timestr)
			}

			term.Print(stbl)
			term.Flush()
		}
	}
}
<commit_msg>Add raw+out to stack list.<commit_after>package cmd

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	term "github.com/buger/goterm"
	"github.com/mobingilabs/mocli/client"
	"github.com/mobingilabs/mocli/pkg/check"
	"github.com/mobingilabs/mocli/pkg/cli"
	d "github.com/mobingilabs/mocli/pkg/debug"
	"github.com/mobingilabs/mocli/pkg/pretty"
	"github.com/mobingilabs/mocli/pkg/stack"
	"github.com/spf13/cobra"
)

func StackListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "list",
		Short: "list all stacks",
		Long: `List all stacks. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.

Valid format values: min (default), text, json, raw

For now, the 'min' format option cannot yet write to a file
using the '--out=[filename]' option. You need to specify either
'text', 'json', or 'raw'.

Examples:

  $ mocli stack list
  $ mocli stack list --fmt=text
  $ mocli stack list --fmt=json --verbose
  $ mocli stack list --fmt=raw --out=/home/foo/tmp.txt`,
		Run: stackList,
	}

	return cmd
}

func stackList(cmd *cobra.Command, args []string) {
	c := client.NewClient(client.NewApiConfig(cmd))
	body, err := c.GetStack()
	check.ErrorExit(err, 1)

	var stacks []stack.ListStack
	err = json.Unmarshal(body, &stacks)
	check.ErrorExit(err, 1)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, body, 0644)
			check.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	case "text":
		indent := cli.GetCliIntFlag(cmd, "indent")
		stack.PrintR(os.Stdout, &stacks[0], 0, indent)

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			fp, err := os.Create(f)
			check.ErrorExit(err, 1)

			defer fp.Close()
			w := bufio.NewWriter(fp)
			defer w.Flush()
			stack.PrintR(w, &stacks[0], 0, indent)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		mi, err := json.MarshalIndent(stacks, "", pretty.Indent(indent))
		check.ErrorExit(err, 1)

		fmt.Println(string(mi))

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, mi, 0644)
			check.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	default:
		if pfmt == "min" || pfmt == "" {
			stbl := term.NewTable(0, 10, 5, ' ', 0)
			fmt.Fprintf(stbl, "STACK ID\tSTACK NAME\tPLATFORM\tSTATUS\tREGION\tLAUNCHED\n")
			for _, s := range stacks {
				timestr := s.CreateTime
				t, err := time.Parse(time.RFC3339, s.CreateTime)
				if err == nil {
					timestr = t.Format(time.RFC1123)
				}

				platform := "?"
				if s.Configuration.AWS != "" {
					platform = "AWS"
				}

				fmt.Fprintf(stbl, "%s\t%s\t%s\t%s\t%s\t%s\n",
					s.StackId,
					s.Nickname,
					platform,
					s.StackStatus,
					s.Configuration.Region,
					timestr)
			}

			term.Print(stbl)
			term.Flush()
		}
	}
}
<|endoftext|>


<commit_before>package rubberneck

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

var (
	expr *regexp.Regexp
)

// AddLineFeed will direct the Printer to add line feeds
// at the end of each output. NoAddLineFeed will not. This
// is useful for controlling the display of output when
// functions exhibit different behavior. For example,
// fmt.Printf wants line feeds added, whereas logrus.Infof
// does not.
const (
	AddLineFeed = iota
	NoAddLineFeed = iota
)

func init() {
	expr = regexp.MustCompile("^[a-z]")
}

// Conforms to the signature used by fmt.Printf and log.Printf among
// many functions available in other packages.
type PrinterFunc func(format string, v ...interface{})

// Printer defines the signature of a function that can be
// used to display the configuration. This signature is used
// by fmt.Printf, log.Printf, various logging output levels
// from the logrus package, and others.
type Printer struct {
	Show  PrinterFunc
}

func addLineFeed(fn PrinterFunc) PrinterFunc {
	return func(format string, v ...interface{}) {
		format = format + "\n"
		fn(format, v...)
	}
}

// NewDefaultPrinter returns a Printer configured to write to stdout.
func NewDefaultPrinter() *Printer {
	return &Printer{
		Show: func(format string, v ...interface{}) {
			fmt.Printf(format+"\n", v...)
		},
	}
}

// NewPrinter returns a Printer configured to use the supplied function
// to output to the supplied function.
func NewPrinter(fn PrinterFunc, lineFeed int) *Printer {
	p := &Printer{Show: fn}

	if lineFeed == AddLineFeed {
		p.Show = addLineFeed(fn)
	}

	return p
}

// Print attempts to pretty print the contents of each obj in a format suitable
// for displaying the configuration of an application on startup. It uses a
// default label of 'Settings' for the output.
func (p *Printer) Print(objs ...interface{}) {
	// Add some protection against accidentally providing this method with
	// a label.
	if len(objs) > 0 {
		switch objs[0].(type) {
		case string:
			p.Show(" *** Expected to print a struct, got: '%s' ***", objs[0])
			return
		}
	}
	p.PrintWithLabel("Settings", objs...)
}

// PrintWithLabel attempts to pretty print the contents of each obj in a format
// suitable for displaying the configuration of an application on startup. It
// takes a label argument which is a string to be printed into the title bar in
// the output.
func (p *Printer) PrintWithLabel(label string, objs ...interface{}) {
	p.Show("%s %s", label, strings.Repeat("-", 50 - len(label) - 1))
	for _, obj := range objs {
		p.processOne(reflect.ValueOf(obj), 0)
	}
	p.Show("%s", strings.Repeat("-", 50))

}

func (p *Printer) processOne(value reflect.Value, indent int) {
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()

	for i := 0; i < value.NumField(); i++ {
		name := t.Field(i).Name

		// Other methods of detecting unexported fields seem unreliable
		// or different between Go versions and Go compilers (gc vs gccgo)
		if expr.MatchString(name) {
			continue
		}

		field := value.Field(i)

		if field.Kind() == reflect.Ptr {
			field = field.Elem()
		}

		switch field.Kind() {
		case reflect.Struct:
			p.Show(" %s * %s:", strings.Repeat("  ", indent), name)
			p.processOne(reflect.ValueOf(field.Interface()), indent+1)
		default:
			p.Show(" %s * %s: %v", strings.Repeat("  ", indent), name, field.Interface())
		}
	}
}

// Print configures a default printer to output to stdout and
// then prints the object.
func Print(obj interface{}) {
	NewDefaultPrinter().Print(obj)
}
<commit_msg>gofmt -s<commit_after>package rubberneck

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

var (
	expr *regexp.Regexp
)

// AddLineFeed will direct the Printer to add line feeds
// at the end of each output. NoAddLineFeed will not. This
// is useful for controlling the display of output when
// functions exhibit different behavior. For example,
// fmt.Printf wants line feeds added, whereas logrus.Infof
// does not.
const (
	AddLineFeed   = iota
	NoAddLineFeed = iota
)

func init() {
	expr = regexp.MustCompile("^[a-z]")
}

// Conforms to the signature used by fmt.Printf and log.Printf among
// many functions available in other packages.
type PrinterFunc func(format string, v ...interface{})

// Printer defines the signature of a function that can be
// used to display the configuration. This signature is used
// by fmt.Printf, log.Printf, various logging output levels
// from the logrus package, and others.
type Printer struct {
	Show PrinterFunc
}

func addLineFeed(fn PrinterFunc) PrinterFunc {
	return func(format string, v ...interface{}) {
		format = format + "\n"
		fn(format, v...)
	}
}

// NewDefaultPrinter returns a Printer configured to write to stdout.
func NewDefaultPrinter() *Printer {
	return &Printer{
		Show: func(format string, v ...interface{}) {
			fmt.Printf(format+"\n", v...)
		},
	}
}

// NewPrinter returns a Printer configured to use the supplied function
// to output to the supplied function.
func NewPrinter(fn PrinterFunc, lineFeed int) *Printer {
	p := &Printer{Show: fn}

	if lineFeed == AddLineFeed {
		p.Show = addLineFeed(fn)
	}

	return p
}

// Print attempts to pretty print the contents of each obj in a format suitable
// for displaying the configuration of an application on startup. It uses a
// default label of 'Settings' for the output.
func (p *Printer) Print(objs ...interface{}) {
	// Add some protection against accidentally providing this method with
	// a label.
	if len(objs) > 0 {
		switch objs[0].(type) {
		case string:
			p.Show(" *** Expected to print a struct, got: '%s' ***", objs[0])
			return
		}
	}
	p.PrintWithLabel("Settings", objs...)
}

// PrintWithLabel attempts to pretty print the contents of each obj in a format
// suitable for displaying the configuration of an application on startup. It
// takes a label argument which is a string to be printed into the title bar in
// the output.
func (p *Printer) PrintWithLabel(label string, objs ...interface{}) {
	p.Show("%s %s", label, strings.Repeat("-", 50-len(label)-1))
	for _, obj := range objs {
		p.processOne(reflect.ValueOf(obj), 0)
	}
	p.Show("%s", strings.Repeat("-", 50))

}

func (p *Printer) processOne(value reflect.Value, indent int) {
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()

	for i := 0; i < value.NumField(); i++ {
		name := t.Field(i).Name

		// Other methods of detecting unexported fields seem unreliable
		// or different between Go versions and Go compilers (gc vs gccgo)
		if expr.MatchString(name) {
			continue
		}

		field := value.Field(i)

		if field.Kind() == reflect.Ptr {
			field = field.Elem()
		}

		switch field.Kind() {
		case reflect.Struct:
			p.Show(" %s * %s:", strings.Repeat("  ", indent), name)
			p.processOne(reflect.ValueOf(field.Interface()), indent+1)
		default:
			p.Show(" %s * %s: %v", strings.Repeat("  ", indent), name, field.Interface())
		}
	}
}

// Print configures a default printer to output to stdout and
// then prints the object.
func Print(obj interface{}) {
	NewDefaultPrinter().Print(obj)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"runtime"
	"strings"

	"github.com/ready-steady/hdf5"
	"github.com/ready-steady/linear"

	"../internal"
)

var (
	parameters = flag.String("s", "[]", "the parameters to sweep")
	pointCount = flag.Uint("n", 10, "the number of points per parameter")
)

func main() {
	internal.Run(command)
}

func command(config internal.Config, _ *hdf5.File, output *hdf5.File) error {
	problem, err := internal.NewProblem(config)
	if err != nil {
		return err
	}

	target, err := internal.NewTarget(problem)
	if err != nil {
		return err
	}

	points, err := generate(target)
	if err != nil {
		return err
	}

	ni, no := target.Dimensions()
	np := uint(len(points)) / ni

	if config.Verbose {
		fmt.Printf("Evaluating the reduced model at %v points...\n", np)
		fmt.Println(problem)
		fmt.Println(target)
	}

	values := internal.Invoke(target, points, uint(runtime.GOMAXPROCS(0)))

	if config.Verbose {
		fmt.Println("Done.")
	}

	if output == nil {
		return nil
	}

	if err := output.Put("values", values, no, np); err != nil {
		return err
	}
	if err := output.Put("points", points, ni, np); err != nil {
		return err
	}

	return nil
}

func generate(target internal.Target) ([]float64, error) {
	ni, _ := target.Dimensions()
	np := *pointCount

	index, err := detect(target)
	if err != nil {
		return nil, err
	}

	parameters := make([][]float64, ni)

	steady := []float64{0.5}
	for i := uint(0); i < ni; i++ {
		parameters[i] = steady
	}

	sweep := make([]float64, np)
	for i := uint(0); i < np; i++ {
		sweep[i] = float64(i) * 1.0 / float64(np-1)
	}
	for _, i := range index {
		parameters[i] = sweep
	}

	return linear.Tensor(parameters...), nil
}

func detect(target internal.Target) ([]uint, error) {
	ni, _ := target.Dimensions()

	index := []uint{}

	decoder := json.NewDecoder(strings.NewReader(*parameters))
	if err := decoder.Decode(&index); err != nil {
		return nil, err
	}

	if len(index) == 0 {
		index = make([]uint, ni)
		for i := uint(0); i < ni; i++ {
			index[i] = i
		}
	}

	for _, i := range index {
		if i >= ni {
			return nil, errors.New(fmt.Sprintf("the indices should be less that %v", ni))
		}
	}

	return index, nil
}
<commit_msg>cmd/sweep: add -d (default point)<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"runtime"
	"strings"

	"github.com/ready-steady/hdf5"
	"github.com/ready-steady/linear"

	"../internal"
)

var (
	parameterIndex = flag.String("s", "[]", "the parameters to sweep")
	numberOfPoints = flag.Uint("n", 10, "the number of points per parameter")
	defaultPoint   = flag.Float64("d", 0.5, "the default value of parameters")
)

func main() {
	internal.Run(command)
}

func command(config internal.Config, _ *hdf5.File, output *hdf5.File) error {
	problem, err := internal.NewProblem(config)
	if err != nil {
		return err
	}

	target, err := internal.NewTarget(problem)
	if err != nil {
		return err
	}

	points, err := generate(target)
	if err != nil {
		return err
	}

	ni, no := target.Dimensions()
	np := uint(len(points)) / ni

	if config.Verbose {
		fmt.Printf("Evaluating the reduced model at %v points...\n", np)
		fmt.Println(problem)
		fmt.Println(target)
	}

	values := internal.Invoke(target, points, uint(runtime.GOMAXPROCS(0)))

	if config.Verbose {
		fmt.Println("Done.")
	}

	if output == nil {
		return nil
	}

	if err := output.Put("values", values, no, np); err != nil {
		return err
	}
	if err := output.Put("points", points, ni, np); err != nil {
		return err
	}

	return nil
}

func generate(target internal.Target) ([]float64, error) {
	ni, _ := target.Dimensions()
	np := *numberOfPoints

	index, err := detect(target)
	if err != nil {
		return nil, err
	}

	parameters := make([][]float64, ni)

	steady := []float64{*defaultPoint}
	for i := uint(0); i < ni; i++ {
		parameters[i] = steady
	}

	sweep := make([]float64, np)
	for i := uint(0); i < np; i++ {
		sweep[i] = float64(i) * 1.0 / float64(np-1)
	}
	for _, i := range index {
		parameters[i] = sweep
	}

	return linear.Tensor(parameters...), nil
}

func detect(target internal.Target) ([]uint, error) {
	ni, _ := target.Dimensions()

	index := []uint{}

	decoder := json.NewDecoder(strings.NewReader(*parameterIndex))
	if err := decoder.Decode(&index); err != nil {
		return nil, err
	}

	if len(index) == 0 {
		index = make([]uint, ni)
		for i := uint(0); i < ni; i++ {
			index[i] = i
		}
	}

	for _, i := range index {
		if i >= ni {
			return nil, errors.New(fmt.Sprintf("the indices should be less that %v", ni))
		}
	}

	return index, nil
}
<|endoftext|>


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

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.7"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<commit_msg>cmd/tsuru: version 0.7.1<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.7.1"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

/*
This file contains the code to check for shadowed variables.
A shadowed variable is a variable declared in an inner scope
with the same name and type as a variable in an outer scope,
and where the outer variable is mentioned after the inner one
is declared.

(This definition can be refined; the module generates too many
false positives and is not yet enabled by default.)

For example:

	func BadRead(f *os.File, buf []byte) error {
		var err error
		for {
			n, err := f.Read(buf) // shadows the function variable 'err'
			if err != nil {
				break // causes return of wrong value
			}
			foo(buf)
		}
		return err
	}

*/

package main

import (
	"flag"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/types"
)

var strictShadowing = flag.Bool("shadowstrict", false, "whether to be strict about shadowing; can be noisy")

func init() {
	register("shadow",
		"check for shadowed variables (experimental; must be set explicitly)",
		checkShadow,
		assignStmt, genDecl)
	experimental["shadow"] = true
}

func checkShadow(f *File, node ast.Node) {
	switch n := node.(type) {
	case *ast.AssignStmt:
		checkShadowAssignment(f, n)
	case *ast.GenDecl:
		checkShadowDecl(f, n)
	}
}

// Span stores the minimum range of byte positions in the file in which a
// given variable (types.Object) is mentioned. It is lexically defined: it spans
// from the beginning of its first mention to the end of its last mention.
// A variable is considered shadowed (if *strictShadowing is off) only if the
// shadowing variable is declared within the span of the shadowed variable.
// In other words, if a variable is shadowed but not used after the shadowed
// variable is declared, it is inconsequential and not worth complaining about.
// This simple check dramatically reduces the nuisance rate for the shadowing
// check, at least until something cleverer comes along.
//
// One wrinkle: A "naked return" is a silent use of a variable that the Span
// will not capture, but the compilers catch naked returns of shadowed
// variables so we don't need to.
//
// Cases this gets wrong (TODO):
// - If a for loop's continuation statement mentions a variable redeclared in
// the block, we should complain about it but don't.
// - A variable declared inside a function literal can falsely be identified
// as shadowing a variable in the outer function.
//
type Span struct {
	min token.Pos
	max token.Pos
}

// contains reports whether the position is inside the span.
func (s Span) contains(pos token.Pos) bool {
	return s.min <= pos && pos < s.max
}

// growSpan expands the span for the object to contain the instance represented
// by the identifier.
func (pkg *Package) growSpan(ident *ast.Ident, obj types.Object) {
	if *strictShadowing {
		return // No need
	}
	pos := ident.Pos()
	end := ident.End()
	span, ok := pkg.spans[obj]
	if ok {
		if span.min > pos {
			span.min = pos
		}
		if span.max < end {
			span.max = end
		}
	} else {
		span = Span{pos, end}
	}
	pkg.spans[obj] = span
}

// checkShadowAssignment checks for shadowing in a short variable declaration.
func checkShadowAssignment(f *File, a *ast.AssignStmt) {
	if a.Tok != token.DEFINE {
		return
	}
	if f.idiomaticShortRedecl(a) {
		return
	}
	for _, expr := range a.Lhs {
		ident, ok := expr.(*ast.Ident)
		if !ok {
			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
			return
		}
		checkShadowing(f, ident)
	}
}

// idiomaticShortRedecl reports whether this short declaration can be ignored for
// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
	// Don't complain about deliberate redeclarations of the form
	//	i := i
	// Such constructs are idiomatic in range loops to create a new variable
	// for each iteration. Another example is
	//	switch n := n.(type)
	if len(a.Rhs) != len(a.Lhs) {
		return false
	}
	// We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)
	for i, expr := range a.Lhs {
		lhs, ok := expr.(*ast.Ident)
		if !ok {
			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
			return true // Don't do any more processing.
		}
		switch rhs := a.Rhs[i].(type) {
		case *ast.Ident:
			if lhs.Name != rhs.Name {
				return false
			}
		case *ast.TypeAssertExpr:
			if id, ok := rhs.X.(*ast.Ident); ok {
				if lhs.Name != id.Name {
					return false
				}
			}
		}
	}
	return true
}

// idiomaticRedecl reports whether this declaration spec can be ignored for
// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
func (f *File) idiomaticRedecl(d *ast.ValueSpec) bool {
	// Don't complain about deliberate redeclarations of the form
	//	var i, j = i, j
	if len(d.Names) != len(d.Values) {
		return false
	}
	for i, lhs := range d.Names {
		if rhs, ok := d.Values[i].(*ast.Ident); ok {
			if lhs.Name != rhs.Name {
				return false
			}
		}
	}
	return true
}

// checkShadowDecl checks for shadowing in a general variable declaration.
func checkShadowDecl(f *File, d *ast.GenDecl) {
	if d.Tok != token.VAR {
		return
	}
	for _, spec := range d.Specs {
		valueSpec, ok := spec.(*ast.ValueSpec)
		if !ok {
			f.Badf(spec.Pos(), "invalid AST: var GenDecl not ValueSpec")
			return
		}
		// Don't complain about deliberate redeclarations of the form
		//	var i = i
		if f.idiomaticRedecl(valueSpec) {
			return
		}
		for _, ident := range valueSpec.Names {
			checkShadowing(f, ident)
		}
	}
}

// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
func checkShadowing(f *File, ident *ast.Ident) {
	if ident.Name == "_" {
		// Can't shadow the blank identifier.
		return
	}
	obj := f.pkg.defs[ident]
	if obj == nil {
		return
	}
	// obj.Parent.Parent is the surrounding scope. If we can find another declaration
	// starting from there, we have a shadowed variable.
	shadowed := obj.Parent().Parent().LookupParent(obj.Name())
	if shadowed == nil {
		return
	}
	// Don't complain if it's shadowing a universe-declared variable; that's fine.
	if shadowed.Parent() == types.Universe {
		return
	}
	if *strictShadowing {
		// The shadowed variable must appear before this one to be an instance of shadowing.
		if shadowed.Pos() > ident.Pos() {
			return
		}
	} else {
		// Don't complain if the span of validity of the shadowed variable doesn't include
		// the shadowing variable.
		span, ok := f.pkg.spans[shadowed]
		if !ok {
			f.Badf(ident.Pos(), "internal error: no range for %s", ident.Name)
			return
		}
		if !span.contains(ident.Pos()) {
			return
		}
	}
	// Don't complain if the types differ: that implies the programmer really wants two variables.
	if types.Identical(obj.Type(), shadowed.Type()) {
		f.Badf(ident.Pos(), "declaration of %s shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
	}
}
<commit_msg>cmd/vet: use changed types.LookupParent API (fix build)<commit_after>// Copyright 2013 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.

/*
This file contains the code to check for shadowed variables.
A shadowed variable is a variable declared in an inner scope
with the same name and type as a variable in an outer scope,
and where the outer variable is mentioned after the inner one
is declared.

(This definition can be refined; the module generates too many
false positives and is not yet enabled by default.)

For example:

	func BadRead(f *os.File, buf []byte) error {
		var err error
		for {
			n, err := f.Read(buf) // shadows the function variable 'err'
			if err != nil {
				break // causes return of wrong value
			}
			foo(buf)
		}
		return err
	}

*/

package main

import (
	"flag"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/types"
)

var strictShadowing = flag.Bool("shadowstrict", false, "whether to be strict about shadowing; can be noisy")

func init() {
	register("shadow",
		"check for shadowed variables (experimental; must be set explicitly)",
		checkShadow,
		assignStmt, genDecl)
	experimental["shadow"] = true
}

func checkShadow(f *File, node ast.Node) {
	switch n := node.(type) {
	case *ast.AssignStmt:
		checkShadowAssignment(f, n)
	case *ast.GenDecl:
		checkShadowDecl(f, n)
	}
}

// Span stores the minimum range of byte positions in the file in which a
// given variable (types.Object) is mentioned. It is lexically defined: it spans
// from the beginning of its first mention to the end of its last mention.
// A variable is considered shadowed (if *strictShadowing is off) only if the
// shadowing variable is declared within the span of the shadowed variable.
// In other words, if a variable is shadowed but not used after the shadowed
// variable is declared, it is inconsequential and not worth complaining about.
// This simple check dramatically reduces the nuisance rate for the shadowing
// check, at least until something cleverer comes along.
//
// One wrinkle: A "naked return" is a silent use of a variable that the Span
// will not capture, but the compilers catch naked returns of shadowed
// variables so we don't need to.
//
// Cases this gets wrong (TODO):
// - If a for loop's continuation statement mentions a variable redeclared in
// the block, we should complain about it but don't.
// - A variable declared inside a function literal can falsely be identified
// as shadowing a variable in the outer function.
//
type Span struct {
	min token.Pos
	max token.Pos
}

// contains reports whether the position is inside the span.
func (s Span) contains(pos token.Pos) bool {
	return s.min <= pos && pos < s.max
}

// growSpan expands the span for the object to contain the instance represented
// by the identifier.
func (pkg *Package) growSpan(ident *ast.Ident, obj types.Object) {
	if *strictShadowing {
		return // No need
	}
	pos := ident.Pos()
	end := ident.End()
	span, ok := pkg.spans[obj]
	if ok {
		if span.min > pos {
			span.min = pos
		}
		if span.max < end {
			span.max = end
		}
	} else {
		span = Span{pos, end}
	}
	pkg.spans[obj] = span
}

// checkShadowAssignment checks for shadowing in a short variable declaration.
func checkShadowAssignment(f *File, a *ast.AssignStmt) {
	if a.Tok != token.DEFINE {
		return
	}
	if f.idiomaticShortRedecl(a) {
		return
	}
	for _, expr := range a.Lhs {
		ident, ok := expr.(*ast.Ident)
		if !ok {
			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
			return
		}
		checkShadowing(f, ident)
	}
}

// idiomaticShortRedecl reports whether this short declaration can be ignored for
// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
	// Don't complain about deliberate redeclarations of the form
	//	i := i
	// Such constructs are idiomatic in range loops to create a new variable
	// for each iteration. Another example is
	//	switch n := n.(type)
	if len(a.Rhs) != len(a.Lhs) {
		return false
	}
	// We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)
	for i, expr := range a.Lhs {
		lhs, ok := expr.(*ast.Ident)
		if !ok {
			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
			return true // Don't do any more processing.
		}
		switch rhs := a.Rhs[i].(type) {
		case *ast.Ident:
			if lhs.Name != rhs.Name {
				return false
			}
		case *ast.TypeAssertExpr:
			if id, ok := rhs.X.(*ast.Ident); ok {
				if lhs.Name != id.Name {
					return false
				}
			}
		}
	}
	return true
}

// idiomaticRedecl reports whether this declaration spec can be ignored for
// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
func (f *File) idiomaticRedecl(d *ast.ValueSpec) bool {
	// Don't complain about deliberate redeclarations of the form
	//	var i, j = i, j
	if len(d.Names) != len(d.Values) {
		return false
	}
	for i, lhs := range d.Names {
		if rhs, ok := d.Values[i].(*ast.Ident); ok {
			if lhs.Name != rhs.Name {
				return false
			}
		}
	}
	return true
}

// checkShadowDecl checks for shadowing in a general variable declaration.
func checkShadowDecl(f *File, d *ast.GenDecl) {
	if d.Tok != token.VAR {
		return
	}
	for _, spec := range d.Specs {
		valueSpec, ok := spec.(*ast.ValueSpec)
		if !ok {
			f.Badf(spec.Pos(), "invalid AST: var GenDecl not ValueSpec")
			return
		}
		// Don't complain about deliberate redeclarations of the form
		//	var i = i
		if f.idiomaticRedecl(valueSpec) {
			return
		}
		for _, ident := range valueSpec.Names {
			checkShadowing(f, ident)
		}
	}
}

// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
func checkShadowing(f *File, ident *ast.Ident) {
	if ident.Name == "_" {
		// Can't shadow the blank identifier.
		return
	}
	obj := f.pkg.defs[ident]
	if obj == nil {
		return
	}
	// obj.Parent.Parent is the surrounding scope. If we can find another declaration
	// starting from there, we have a shadowed variable.
	_, shadowed := obj.Parent().Parent().LookupParent(obj.Name())
	if shadowed == nil {
		return
	}
	// Don't complain if it's shadowing a universe-declared variable; that's fine.
	if shadowed.Parent() == types.Universe {
		return
	}
	if *strictShadowing {
		// The shadowed variable must appear before this one to be an instance of shadowing.
		if shadowed.Pos() > ident.Pos() {
			return
		}
	} else {
		// Don't complain if the span of validity of the shadowed variable doesn't include
		// the shadowing variable.
		span, ok := f.pkg.spans[shadowed]
		if !ok {
			f.Badf(ident.Pos(), "internal error: no range for %s", ident.Name)
			return
		}
		if !span.contains(ident.Pos()) {
			return
		}
	}
	// Don't complain if the types differ: that implies the programmer really wants two variables.
	if types.Identical(obj.Type(), shadowed.Type()) {
		f.Badf(ident.Pos(), "declaration of %s shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package build

import (
	"flag"
	"fmt"
	"os"
)

var (
	// These flags override values in build env.
	GitCommitFlag   = flag.String("git-commit", "", `Overrides git commit hash embedded into executables`)
	GitBranchFlag   = flag.String("git-branch", "", `Overrides git branch being built`)
	GitTagFlag      = flag.String("git-tag", "", `Overrides git tag being built`)
	BuildnumFlag    = flag.String("buildnum", "", `Overrides CI build number`)
	PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`)
)

// Environment contains metadata provided by the build environment.
type Environment struct {
	Name                string // name of the environment
	Repo                string // name of GitHub repo
	Commit, Branch, Tag string // Git info
	Buildnum            string
	IsPullRequest       bool
}

func (env Environment) String() string {
	return fmt.Sprintf("%s env (commit:%s branch:%s tag:%s buildnum:%s pr:%t)",
		env.Name, env.Commit, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest)
}

// Env returns metadata about the current CI environment, falling back to LocalEnv
// if not running on CI.
func Env() Environment {
	switch {
	case os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true":
		return Environment{
			Name:          "travis",
			Repo:          os.Getenv("TRAVIS_REPO_SLUG"),
			Commit:        os.Getenv("TRAVIS_COMMIT"),
			Branch:        os.Getenv("TRAVIS_BRANCH"),
			Tag:           os.Getenv("TRAVIS_TAG"),
			Buildnum:      os.Getenv("TRAVIS_BUILD_NUMBER"),
			IsPullRequest: os.Getenv("TRAVIS_PULL_REQUEST") != "false",
		}
	case os.Getenv("CI") == "True" && os.Getenv("APPVEYOR") == "True":
		return Environment{
			Name:          "appveyor",
			Repo:          os.Getenv("APPVEYOR_REPO_NAME"),
			Commit:        os.Getenv("APPVEYOR_REPO_COMMIT"),
			Branch:        os.Getenv("APPVEYOR_REPO_BRANCH"),
			Tag:           os.Getenv("APPVEYOR_REPO_TAG_NAME"),
			Buildnum:      os.Getenv("APPVEYOR_BUILD_NUMBER"),
			IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "",
		}
	default:
		return LocalEnv()
	}
}

// LocalEnv returns build environment metadata gathered from git.
func LocalEnv() Environment {
	env := applyEnvFlags(Environment{Name: "local", Repo: "ethereum/go-ethereum"})
	if _, err := os.Stat(".git"); err != nil {
		return env
	}
	if env.Commit == "" {
		env.Commit = RunGit("rev-parse", "HEAD")
	}
	if env.Branch == "" {
		if b := RunGit("rev-parse", "--abbrev-ref", "HEAD"); b != "HEAD" {
			env.Branch = b
		}
	}
	if env.Tag == "" {
		env.Tag = RunGit("for-each-ref", "--points-at=HEAD", "--count=1", "--format=%(refname:short)", "refs/tags")
	}
	return env
}

func applyEnvFlags(env Environment) Environment {
	if !flag.Parsed() {
		panic("you need to call flag.Parse before Env or LocalEnv")
	}
	if *GitCommitFlag != "" {
		env.Commit = *GitCommitFlag
	}
	if *GitBranchFlag != "" {
		env.Branch = *GitBranchFlag
	}
	if *GitTagFlag != "" {
		env.Tag = *GitTagFlag
	}
	if *BuildnumFlag != "" {
		env.Buildnum = *BuildnumFlag
	}
	if *PullRequestFlag {
		env.IsPullRequest = true
	}
	return env
}
<commit_msg>internal/build: use 'git tag --points-at' to get the current tag<commit_after>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package build

import (
	"flag"
	"fmt"
	"os"
	"strings"
)

var (
	// These flags override values in build env.
	GitCommitFlag   = flag.String("git-commit", "", `Overrides git commit hash embedded into executables`)
	GitBranchFlag   = flag.String("git-branch", "", `Overrides git branch being built`)
	GitTagFlag      = flag.String("git-tag", "", `Overrides git tag being built`)
	BuildnumFlag    = flag.String("buildnum", "", `Overrides CI build number`)
	PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`)
)

// Environment contains metadata provided by the build environment.
type Environment struct {
	Name                string // name of the environment
	Repo                string // name of GitHub repo
	Commit, Branch, Tag string // Git info
	Buildnum            string
	IsPullRequest       bool
}

func (env Environment) String() string {
	return fmt.Sprintf("%s env (commit:%s branch:%s tag:%s buildnum:%s pr:%t)",
		env.Name, env.Commit, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest)
}

// Env returns metadata about the current CI environment, falling back to LocalEnv
// if not running on CI.
func Env() Environment {
	switch {
	case os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true":
		return Environment{
			Name:          "travis",
			Repo:          os.Getenv("TRAVIS_REPO_SLUG"),
			Commit:        os.Getenv("TRAVIS_COMMIT"),
			Branch:        os.Getenv("TRAVIS_BRANCH"),
			Tag:           os.Getenv("TRAVIS_TAG"),
			Buildnum:      os.Getenv("TRAVIS_BUILD_NUMBER"),
			IsPullRequest: os.Getenv("TRAVIS_PULL_REQUEST") != "false",
		}
	case os.Getenv("CI") == "True" && os.Getenv("APPVEYOR") == "True":
		return Environment{
			Name:          "appveyor",
			Repo:          os.Getenv("APPVEYOR_REPO_NAME"),
			Commit:        os.Getenv("APPVEYOR_REPO_COMMIT"),
			Branch:        os.Getenv("APPVEYOR_REPO_BRANCH"),
			Tag:           os.Getenv("APPVEYOR_REPO_TAG_NAME"),
			Buildnum:      os.Getenv("APPVEYOR_BUILD_NUMBER"),
			IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "",
		}
	default:
		return LocalEnv()
	}
}

// LocalEnv returns build environment metadata gathered from git.
func LocalEnv() Environment {
	env := applyEnvFlags(Environment{Name: "local", Repo: "ethereum/go-ethereum"})
	if _, err := os.Stat(".git"); err != nil {
		return env
	}
	if env.Commit == "" {
		env.Commit = RunGit("rev-parse", "HEAD")
	}
	if env.Branch == "" {
		if b := RunGit("rev-parse", "--abbrev-ref", "HEAD"); b != "HEAD" {
			env.Branch = b
		}
	}
	if env.Tag == "" {
		env.Tag = firstLine(RunGit("tag", "-l", "--points-at", "HEAD"))
	}
	return env
}

func firstLine(s string) string {
	return strings.Split(s, "\n")[0]
}

func applyEnvFlags(env Environment) Environment {
	if !flag.Parsed() {
		panic("you need to call flag.Parse before Env or LocalEnv")
	}
	if *GitCommitFlag != "" {
		env.Commit = *GitCommitFlag
	}
	if *GitBranchFlag != "" {
		env.Branch = *GitBranchFlag
	}
	if *GitTagFlag != "" {
		env.Tag = *GitTagFlag
	}
	if *BuildnumFlag != "" {
		env.Buildnum = *BuildnumFlag
	}
	if *PullRequestFlag {
		env.IsPullRequest = true
	}
	return env
}
<|endoftext|>


<commit_before>package user

import (
	"os/user"
	"path/filepath"

	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"io/ioutil"
	"os"

	"github.com/micro/micro/v3/service/logger"
)

var (
	Dir  = ""
	path = ".micro"
)

func init() {
	user, err := user.Current()
	if err != nil {
		logger.Fatalf(err.Error())
	}
	Dir = filepath.Join(user.HomeDir, path)
	err = os.MkdirAll(Dir, 0700)
	if err != nil {
		logger.Fatalf(err.Error())
	}
}

// GetConfigSecretKey returns local keys or generates and returns them for
// config secret encoding/decoding.
func GetConfigSecretKey() (string, error) {
	key := filepath.Join(Dir, "config_secret_key")
	if !fileExists(key) {
		err := setupConfigSecretKey(key)
		if err != nil {
			return "", err
		}
	}
	logger.Infof("Loading config key from %v", key)
	dat, err := ioutil.ReadFile(key)
	if err != nil {
		return "", err
	}
	return string(dat), nil
}

func setupConfigSecretKey(path string) error {
	logger.Infof("Setting up config key to %v", path)
	bytes := make([]byte, 32) //generate a random 32 byte key for AES-256
	if _, err := rand.Read(bytes); err != nil {
		return err
	}
	file, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	file.Close()

	err = ioutil.WriteFile(path, []byte(base64.StdEncoding.EncodeToString(bytes)), 0600)
	if err != nil {
		return err
	}

	return nil
}

// GetJWTCerts returns local keys or generates and returns them for JWT auth.GetJWTCerts
// This is only here for "0 dep", so people don't have to create and load the certs themselves,
// not really intended for serious production use.
func GetJWTCerts() ([]byte, []byte, error) {
	privKey := filepath.Join(Dir, "id_rsa")
	pubKey := filepath.Join(Dir, "id_rsa.pub")

	logger.Infof("Loading keys %v and %v", privKey, pubKey)
	if !fileExists(privKey) || !fileExists(pubKey) {
		err := setupKeys(privKey, pubKey)
		if err != nil {
			return nil, nil, err
		}
	}
	privDat, err := ioutil.ReadFile(privKey)
	if err != nil {
		return nil, nil, err
	}
	pubDat, err := ioutil.ReadFile(pubKey)
	if err != nil {
		return nil, nil, err
	}
	return privDat, pubDat, nil
}

func setupKeys(privKey, pubKey string) error {
	logger.Infof("Setting up keys for JWT at %v and %v", privKey, pubKey)
	bitSize := 4096
	privateKey, err := generatePrivateKey(bitSize)
	if err != nil {
		return err
	}

	publicKeyBytes, err := generatePublicKey(&privateKey.PublicKey)
	if err != nil {
		return err
	}

	privateKeyBytes, err := encodePrivateKeyToPEM(privateKey)
	if err != nil {
		return err
	}

	err = writeKeyToFile(privateKeyBytes, privKey)
	if err != nil {
		return err
	}

	err = writeKeyToFile([]byte(publicKeyBytes), pubKey)
	if err != nil {
		return err
	}
	return nil
}

func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return false
	}
	return !info.IsDir()
}

// taken from https://gist.github.com/devinodaniel/8f9b8a4f31573f428f29ec0e884e6673

// generatePrivateKey creates a RSA Private Key of specified byte size
func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) {
	// Private Key generation
	privateKey, err := rsa.GenerateKey(rand.Reader, bitSize)
	if err != nil {
		return nil, err
	}

	// Validate Private Key
	err = privateKey.Validate()
	if err != nil {
		return nil, err
	}

	return privateKey, nil
}

// encodePrivateKeyToPEM encodes Private Key from RSA to PEM format
func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) ([]byte, error) {
	// Get ASN.1 DER format
	privDER := x509.MarshalPKCS1PrivateKey(privateKey)

	// pem.Block
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privDER,
	}

	// Private key in PEM format
	privatePEM := pem.EncodeToMemory(&privBlock)

	return privatePEM, nil
}

func generatePublicKey(publickey *rsa.PublicKey) ([]byte, error) {
	pubDER, err := x509.MarshalPKIXPublicKey(publickey)
	if err != nil {
		return nil, err
	}
	pubBlock := pem.Block{
		Type:    "PUBLIC KEY",
		Headers: nil,
		Bytes:   pubDER,
	}
	pubPEM := pem.EncodeToMemory(&pubBlock)

	return pubPEM, nil
}

// writePemToFile writes keys to a file
func writeKeyToFile(keyBytes []byte, saveFileTo string) error {
	file, err := os.OpenFile(saveFileTo, os.O_RDONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	file.Close()

	err = ioutil.WriteFile(saveFileTo, []byte(base64.StdEncoding.EncodeToString(keyBytes)), 0600)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>lower log level of user keys related stuff<commit_after>package user

import (
	"os/user"
	"path/filepath"

	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"io/ioutil"
	"os"

	"github.com/micro/micro/v3/service/logger"
)

var (
	Dir  = ""
	path = ".micro"
)

func init() {
	user, err := user.Current()
	if err != nil {
		logger.Fatalf(err.Error())
	}
	Dir = filepath.Join(user.HomeDir, path)
	err = os.MkdirAll(Dir, 0700)
	if err != nil {
		logger.Fatalf(err.Error())
	}
}

// GetConfigSecretKey returns local keys or generates and returns them for
// config secret encoding/decoding.
func GetConfigSecretKey() (string, error) {
	key := filepath.Join(Dir, "config_secret_key")
	if !fileExists(key) {
		err := setupConfigSecretKey(key)
		if err != nil {
			return "", err
		}
	}
	logger.Debugf("Loading config key from %v", key)
	dat, err := ioutil.ReadFile(key)
	if err != nil {
		return "", err
	}
	return string(dat), nil
}

func setupConfigSecretKey(path string) error {
	logger.Debugf("Setting up config key to %v", path)
	bytes := make([]byte, 32) //generate a random 32 byte key for AES-256
	if _, err := rand.Read(bytes); err != nil {
		return err
	}
	file, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	file.Close()

	err = ioutil.WriteFile(path, []byte(base64.StdEncoding.EncodeToString(bytes)), 0600)
	if err != nil {
		return err
	}

	return nil
}

// GetJWTCerts returns local keys or generates and returns them for JWT auth.GetJWTCerts
// This is only here for "0 dep", so people don't have to create and load the certs themselves,
// not really intended for serious production use.
func GetJWTCerts() ([]byte, []byte, error) {
	privKey := filepath.Join(Dir, "id_rsa")
	pubKey := filepath.Join(Dir, "id_rsa.pub")

	logger.Debugf("Loading keys %v and %v", privKey, pubKey)
	if !fileExists(privKey) || !fileExists(pubKey) {
		err := setupKeys(privKey, pubKey)
		if err != nil {
			return nil, nil, err
		}
	}
	privDat, err := ioutil.ReadFile(privKey)
	if err != nil {
		return nil, nil, err
	}
	pubDat, err := ioutil.ReadFile(pubKey)
	if err != nil {
		return nil, nil, err
	}
	return privDat, pubDat, nil
}

func setupKeys(privKey, pubKey string) error {
	logger.Infof("Setting up keys for JWT at %v and %v", privKey, pubKey)
	bitSize := 4096
	privateKey, err := generatePrivateKey(bitSize)
	if err != nil {
		return err
	}

	publicKeyBytes, err := generatePublicKey(&privateKey.PublicKey)
	if err != nil {
		return err
	}

	privateKeyBytes, err := encodePrivateKeyToPEM(privateKey)
	if err != nil {
		return err
	}

	err = writeKeyToFile(privateKeyBytes, privKey)
	if err != nil {
		return err
	}

	err = writeKeyToFile([]byte(publicKeyBytes), pubKey)
	if err != nil {
		return err
	}
	return nil
}

func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return false
	}
	return !info.IsDir()
}

// taken from https://gist.github.com/devinodaniel/8f9b8a4f31573f428f29ec0e884e6673

// generatePrivateKey creates a RSA Private Key of specified byte size
func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) {
	// Private Key generation
	privateKey, err := rsa.GenerateKey(rand.Reader, bitSize)
	if err != nil {
		return nil, err
	}

	// Validate Private Key
	err = privateKey.Validate()
	if err != nil {
		return nil, err
	}

	return privateKey, nil
}

// encodePrivateKeyToPEM encodes Private Key from RSA to PEM format
func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) ([]byte, error) {
	// Get ASN.1 DER format
	privDER := x509.MarshalPKCS1PrivateKey(privateKey)

	// pem.Block
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privDER,
	}

	// Private key in PEM format
	privatePEM := pem.EncodeToMemory(&privBlock)

	return privatePEM, nil
}

func generatePublicKey(publickey *rsa.PublicKey) ([]byte, error) {
	pubDER, err := x509.MarshalPKIXPublicKey(publickey)
	if err != nil {
		return nil, err
	}
	pubBlock := pem.Block{
		Type:    "PUBLIC KEY",
		Headers: nil,
		Bytes:   pubDER,
	}
	pubPEM := pem.EncodeToMemory(&pubBlock)

	return pubPEM, nil
}

// writePemToFile writes keys to a file
func writeKeyToFile(keyBytes []byte, saveFileTo string) error {
	file, err := os.OpenFile(saveFileTo, os.O_RDONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	file.Close()

	err = ioutil.WriteFile(saveFileTo, []byte(base64.StdEncoding.EncodeToString(keyBytes)), 0600)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Ceph-CSI Authors.

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 util

import (
	"context"
	"errors"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
	"time"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"k8s.io/apimachinery/pkg/util/validation"
	"k8s.io/cloud-provider/volume/helpers"
	klog "k8s.io/klog/v2"
	"k8s.io/utils/mount"
)

// RoundOffVolSize rounds up given quantity upto chunks of MiB/GiB.
func RoundOffVolSize(size int64) int64 {
	size = RoundOffBytes(size)
	// convert size back to MiB for rbd CLI
	return size / helpers.MiB
}

// RoundOffBytes converts roundoff the size
// 1.1Mib will be round off to 2Mib same for GiB
// size less than 1MiB will be round off to 1MiB.
func RoundOffBytes(bytes int64) int64 {
	var num int64
	floatBytes := float64(bytes)
	// round off the value if its in decimal
	if floatBytes < helpers.GiB {
		num = int64(math.Ceil(floatBytes / helpers.MiB))
		num *= helpers.MiB
	} else {
		num = int64(math.Ceil(floatBytes / helpers.GiB))
		num *= helpers.GiB
	}
	return num
}

// variables which will be set during the build time.
var (
	// GitCommit tell the latest git commit image is built from
	GitCommit string
	// DriverVersion which will be driver version
	DriverVersion string
)

// Config holds the parameters list which can be configured.
type Config struct {
	Vtype        string // driver type [rbd|cephfs|liveness]
	Endpoint     string // CSI endpoint
	DriverName   string // name of the driver
	NodeID       string // node id
	InstanceID   string // unique ID distinguishing this instance of Ceph CSI
	PluginPath   string // location of cephcsi plugin
	DomainLabels string // list of domain labels to read from the node

	// metrics related flags
	MetricsPath       string        // path of prometheus endpoint where metrics will be available
	HistogramOption   string        // Histogram option for grpc metrics, should be comma separated value, ex:= "0.5,2,6" where start=0.5 factor=2, count=6
	MetricsIP         string        // TCP port for liveness/ metrics requests
	PidLimit          int           // PID limit to configure through cgroups")
	MetricsPort       int           // TCP port for liveness/grpc metrics requests
	PollTime          time.Duration // time interval in seconds between each poll
	PoolTimeout       time.Duration // probe timeout in seconds
	EnableGRPCMetrics bool          // option to enable grpc metrics

	IsControllerServer bool // if set to true start provisoner server
	IsNodeServer       bool // if set to true start node server
	Version            bool // cephcsi version

	// SkipForceFlatten is set to false if the kernel supports mounting of
	// rbd image or the image chain has the deep-flatten feature.
	SkipForceFlatten bool

	// cephfs related flags
	ForceKernelCephFS bool // force to use the ceph kernel client even if the kernel is < 4.17

	// RbdHardMaxCloneDepth is the hard limit for maximum number of nested volume clones that are taken before a flatten occurs
	RbdHardMaxCloneDepth uint

	// RbdSoftMaxCloneDepth is the soft limit for maximum number of nested volume clones that are taken before a flatten occurs
	RbdSoftMaxCloneDepth uint

	// MaxSnapshotsOnImage represents the maximum number of snapshots allowed
	// on rbd image without flattening, once the limit is reached cephcsi will
	// start flattening the older rbd images to allow more snapshots
	MaxSnapshotsOnImage uint
}

// ValidateDriverName validates the driver name.
func ValidateDriverName(driverName string) error {
	if driverName == "" {
		return errors.New("driver name is empty")
	}

	const reqDriverNameLen = 63
	if len(driverName) > reqDriverNameLen {
		return errors.New("driver name length should be less than 63 chars")
	}
	var err error
	for _, msg := range validation.IsDNS1123Subdomain(strings.ToLower(driverName)) {
		if err == nil {
			err = errors.New(msg)
			continue
		}
		err = fmt.Errorf("%s: %w", msg, err)
	}
	return err
}

// GetKernelVersion returns the version of the running Unix (like) system from the
// 'utsname' structs 'release' component.
func GetKernelVersion() (string, error) {
	utsname := unix.Utsname{}
	err := unix.Uname(&utsname)
	if err != nil {
		return "", err
	}
	return strings.TrimRight(string(utsname.Release[:]), "\x00"), nil
}

// KernelVersion holds kernel related informations.
type KernelVersion struct {
	Version      int
	PatchLevel   int
	SubLevel     int
	ExtraVersion int    // prefix of the part after the first "-"
	Distribution string // component of full extraversion
	Backport     bool   // backports have a fixed version/patchlevel/sublevel
}

// CheckKernelSupport checks the running kernel and comparing it to known
// versions that have support for required features . Distributors of
// enterprise Linux have backported quota support to previous versions. This
// function checks if the running kernel is one of the versions that have the
// feature/fixes backported.
//
// `uname -r` (or Uname().Utsname.Release has a format like 1.2.3-rc.vendor
// This can be slit up in the following components: - version (1) - patchlevel
// (2) - sublevel (3) - optional, defaults to 0 - extraversion (rc) - optional,
// matching integers only - distribution (.vendor) - optional, match against
// whole `uname -r` string
//
// For matching multiple versions, the kernelSupport type contains a backport
// bool, which will cause matching
// version+patchlevel+sublevel+(>=extraversion)+(~distribution)
//
// In case the backport bool is false, a simple check for higher versions than
// version+patchlevel+sublevel is done.
func CheckKernelSupport(release string, supportedVersions []KernelVersion) bool {
	vers := strings.Split(strings.SplitN(release, "-", 2)[0], ".")
	version, err := strconv.Atoi(vers[0])
	if err != nil {
		klog.Errorf("failed to parse version from %s: %v", release, err)
		return false
	}
	patchlevel, err := strconv.Atoi(vers[1])
	if err != nil {
		klog.Errorf("failed to parse patchlevel from %s: %v", release, err)
		return false
	}
	sublevel := 0
	const minLenForSublvl = 3
	if len(vers) >= minLenForSublvl {
		sublevel, err = strconv.Atoi(vers[2])
		if err != nil {
			klog.Errorf("failed to parse sublevel from %s: %v", release, err)
			return false
		}
	}
	extra := strings.SplitN(release, "-", 2)
	extraversion := 0
	const expectedExtraLen = 2
	if len(extra) == expectedExtraLen {
		// ignore errors, 1st component of extraversion does not need to be an int
		extraversion, err = strconv.Atoi(strings.Split(extra[1], ".")[0])
		if err != nil {
			// "go lint" wants err to be checked...
			extraversion = 0
		}
	}

	// compare running kernel against known versions
	for _, kernel := range supportedVersions {
		if !kernel.Backport {
			// deal with the default case(s), find >= match for version, patchlevel, sublevel
			if version > kernel.Version || (version == kernel.Version && patchlevel > kernel.PatchLevel) ||
				(version == kernel.Version && patchlevel == kernel.PatchLevel && sublevel >= kernel.SubLevel) {
				return true
			}
		} else {
			// specific backport, match distribution initially
			if !strings.Contains(release, kernel.Distribution) {
				continue
			}

			// strict match version, patchlevel, sublevel, and >= match extraversion
			if version == kernel.Version && patchlevel == kernel.PatchLevel &&
				sublevel == kernel.SubLevel && extraversion >= kernel.ExtraVersion {
				return true
			}
		}
	}
	klog.Errorf("kernel %s does not support required features", release)
	return false
}

// GenerateVolID generates a volume ID based on passed in parameters and version, to be returned
// to the CO system.
func GenerateVolID(ctx context.Context, monitors string, cr *Credentials, locationID int64, pool, clusterID, objUUID string, volIDVersion uint16) (string, error) {
	var err error

	if locationID == InvalidPoolID {
		locationID, err = GetPoolID(monitors, cr, pool)
		if err != nil {
			return "", err
		}
	}

	// generate the volume ID to return to the CO system
	vi := CSIIdentifier{
		LocationID:      locationID,
		EncodingVersion: volIDVersion,
		ClusterID:       clusterID,
		ObjectUUID:      objUUID,
	}

	volID, err := vi.ComposeCSIID()

	return volID, err
}

// CreateMountPoint creates the directory with given path.
func CreateMountPoint(mountPath string) error {
	return os.MkdirAll(mountPath, 0750)
}

// checkDirExists checks directory  exists or not.
func checkDirExists(p string) bool {
	if _, err := os.Stat(p); os.IsNotExist(err) {
		return false
	}
	return true
}

// IsMountPoint checks if the given path is mountpoint or not.
func IsMountPoint(p string) (bool, error) {
	dummyMount := mount.New("")
	notMnt, err := dummyMount.IsLikelyNotMountPoint(p)
	if err != nil {
		return false, status.Error(codes.Internal, err.Error())
	}

	return !notMnt, nil
}

// Mount mounts the source to target path.
func Mount(source, target, fstype string, options []string) error {
	dummyMount := mount.New("")
	return dummyMount.Mount(source, target, fstype, options)
}

// MountOptionsAdd adds the `add` mount options to the `options` and returns a
// new string. In case `add` is already present in the `options`, `add` is not
// added again.
func MountOptionsAdd(options string, add ...string) string {
	opts := strings.Split(options, ",")
	newOpts := []string{}
	// clean original options from empty strings
	for _, opt := range opts {
		if opt != "" {
			newOpts = append(newOpts, opt)
		}
	}

	for _, opt := range add {
		if opt != "" && !contains(newOpts, opt) {
			newOpts = append(newOpts, opt)
		}
	}

	return strings.Join(newOpts, ",")
}

func contains(s []string, key string) bool {
	for _, v := range s {
		if v == key {
			return true
		}
	}

	return false
}
<commit_msg>util: use local ErrorLog() for CheckKernelSupport() instead of klog<commit_after>/*
Copyright 2019 The Ceph-CSI Authors.

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 util

import (
	"context"
	"errors"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
	"time"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"k8s.io/apimachinery/pkg/util/validation"
	"k8s.io/cloud-provider/volume/helpers"
	"k8s.io/utils/mount"
)

// RoundOffVolSize rounds up given quantity upto chunks of MiB/GiB.
func RoundOffVolSize(size int64) int64 {
	size = RoundOffBytes(size)
	// convert size back to MiB for rbd CLI
	return size / helpers.MiB
}

// RoundOffBytes converts roundoff the size
// 1.1Mib will be round off to 2Mib same for GiB
// size less than 1MiB will be round off to 1MiB.
func RoundOffBytes(bytes int64) int64 {
	var num int64
	floatBytes := float64(bytes)
	// round off the value if its in decimal
	if floatBytes < helpers.GiB {
		num = int64(math.Ceil(floatBytes / helpers.MiB))
		num *= helpers.MiB
	} else {
		num = int64(math.Ceil(floatBytes / helpers.GiB))
		num *= helpers.GiB
	}
	return num
}

// variables which will be set during the build time.
var (
	// GitCommit tell the latest git commit image is built from
	GitCommit string
	// DriverVersion which will be driver version
	DriverVersion string
)

// Config holds the parameters list which can be configured.
type Config struct {
	Vtype        string // driver type [rbd|cephfs|liveness]
	Endpoint     string // CSI endpoint
	DriverName   string // name of the driver
	NodeID       string // node id
	InstanceID   string // unique ID distinguishing this instance of Ceph CSI
	PluginPath   string // location of cephcsi plugin
	DomainLabels string // list of domain labels to read from the node

	// metrics related flags
	MetricsPath       string        // path of prometheus endpoint where metrics will be available
	HistogramOption   string        // Histogram option for grpc metrics, should be comma separated value, ex:= "0.5,2,6" where start=0.5 factor=2, count=6
	MetricsIP         string        // TCP port for liveness/ metrics requests
	PidLimit          int           // PID limit to configure through cgroups")
	MetricsPort       int           // TCP port for liveness/grpc metrics requests
	PollTime          time.Duration // time interval in seconds between each poll
	PoolTimeout       time.Duration // probe timeout in seconds
	EnableGRPCMetrics bool          // option to enable grpc metrics

	IsControllerServer bool // if set to true start provisoner server
	IsNodeServer       bool // if set to true start node server
	Version            bool // cephcsi version

	// SkipForceFlatten is set to false if the kernel supports mounting of
	// rbd image or the image chain has the deep-flatten feature.
	SkipForceFlatten bool

	// cephfs related flags
	ForceKernelCephFS bool // force to use the ceph kernel client even if the kernel is < 4.17

	// RbdHardMaxCloneDepth is the hard limit for maximum number of nested volume clones that are taken before a flatten occurs
	RbdHardMaxCloneDepth uint

	// RbdSoftMaxCloneDepth is the soft limit for maximum number of nested volume clones that are taken before a flatten occurs
	RbdSoftMaxCloneDepth uint

	// MaxSnapshotsOnImage represents the maximum number of snapshots allowed
	// on rbd image without flattening, once the limit is reached cephcsi will
	// start flattening the older rbd images to allow more snapshots
	MaxSnapshotsOnImage uint
}

// ValidateDriverName validates the driver name.
func ValidateDriverName(driverName string) error {
	if driverName == "" {
		return errors.New("driver name is empty")
	}

	const reqDriverNameLen = 63
	if len(driverName) > reqDriverNameLen {
		return errors.New("driver name length should be less than 63 chars")
	}
	var err error
	for _, msg := range validation.IsDNS1123Subdomain(strings.ToLower(driverName)) {
		if err == nil {
			err = errors.New(msg)
			continue
		}
		err = fmt.Errorf("%s: %w", msg, err)
	}
	return err
}

// GetKernelVersion returns the version of the running Unix (like) system from the
// 'utsname' structs 'release' component.
func GetKernelVersion() (string, error) {
	utsname := unix.Utsname{}
	err := unix.Uname(&utsname)
	if err != nil {
		return "", err
	}
	return strings.TrimRight(string(utsname.Release[:]), "\x00"), nil
}

// KernelVersion holds kernel related informations.
type KernelVersion struct {
	Version      int
	PatchLevel   int
	SubLevel     int
	ExtraVersion int    // prefix of the part after the first "-"
	Distribution string // component of full extraversion
	Backport     bool   // backports have a fixed version/patchlevel/sublevel
}

// CheckKernelSupport checks the running kernel and comparing it to known
// versions that have support for required features . Distributors of
// enterprise Linux have backported quota support to previous versions. This
// function checks if the running kernel is one of the versions that have the
// feature/fixes backported.
//
// `uname -r` (or Uname().Utsname.Release has a format like 1.2.3-rc.vendor
// This can be slit up in the following components: - version (1) - patchlevel
// (2) - sublevel (3) - optional, defaults to 0 - extraversion (rc) - optional,
// matching integers only - distribution (.vendor) - optional, match against
// whole `uname -r` string
//
// For matching multiple versions, the kernelSupport type contains a backport
// bool, which will cause matching
// version+patchlevel+sublevel+(>=extraversion)+(~distribution)
//
// In case the backport bool is false, a simple check for higher versions than
// version+patchlevel+sublevel is done.
func CheckKernelSupport(release string, supportedVersions []KernelVersion) bool {
	vers := strings.Split(strings.SplitN(release, "-", 2)[0], ".")
	version, err := strconv.Atoi(vers[0])
	if err != nil {
		ErrorLog("failed to parse version from %s: %v", release, err)
		return false
	}
	patchlevel, err := strconv.Atoi(vers[1])
	if err != nil {
		ErrorLog("failed to parse patchlevel from %s: %v", release, err)
		return false
	}
	sublevel := 0
	const minLenForSublvl = 3
	if len(vers) >= minLenForSublvl {
		sublevel, err = strconv.Atoi(vers[2])
		if err != nil {
			ErrorLog("failed to parse sublevel from %s: %v", release, err)
			return false
		}
	}
	extra := strings.SplitN(release, "-", 2)
	extraversion := 0
	const expectedExtraLen = 2
	if len(extra) == expectedExtraLen {
		// ignore errors, 1st component of extraversion does not need to be an int
		extraversion, err = strconv.Atoi(strings.Split(extra[1], ".")[0])
		if err != nil {
			// "go lint" wants err to be checked...
			extraversion = 0
		}
	}

	// compare running kernel against known versions
	for _, kernel := range supportedVersions {
		if !kernel.Backport {
			// deal with the default case(s), find >= match for version, patchlevel, sublevel
			if version > kernel.Version || (version == kernel.Version && patchlevel > kernel.PatchLevel) ||
				(version == kernel.Version && patchlevel == kernel.PatchLevel && sublevel >= kernel.SubLevel) {
				return true
			}
		} else {
			// specific backport, match distribution initially
			if !strings.Contains(release, kernel.Distribution) {
				continue
			}

			// strict match version, patchlevel, sublevel, and >= match extraversion
			if version == kernel.Version && patchlevel == kernel.PatchLevel &&
				sublevel == kernel.SubLevel && extraversion >= kernel.ExtraVersion {
				return true
			}
		}
	}
	ErrorLog("kernel %s does not support required features", release)
	return false
}

// GenerateVolID generates a volume ID based on passed in parameters and version, to be returned
// to the CO system.
func GenerateVolID(ctx context.Context, monitors string, cr *Credentials, locationID int64, pool, clusterID, objUUID string, volIDVersion uint16) (string, error) {
	var err error

	if locationID == InvalidPoolID {
		locationID, err = GetPoolID(monitors, cr, pool)
		if err != nil {
			return "", err
		}
	}

	// generate the volume ID to return to the CO system
	vi := CSIIdentifier{
		LocationID:      locationID,
		EncodingVersion: volIDVersion,
		ClusterID:       clusterID,
		ObjectUUID:      objUUID,
	}

	volID, err := vi.ComposeCSIID()

	return volID, err
}

// CreateMountPoint creates the directory with given path.
func CreateMountPoint(mountPath string) error {
	return os.MkdirAll(mountPath, 0750)
}

// checkDirExists checks directory  exists or not.
func checkDirExists(p string) bool {
	if _, err := os.Stat(p); os.IsNotExist(err) {
		return false
	}
	return true
}

// IsMountPoint checks if the given path is mountpoint or not.
func IsMountPoint(p string) (bool, error) {
	dummyMount := mount.New("")
	notMnt, err := dummyMount.IsLikelyNotMountPoint(p)
	if err != nil {
		return false, status.Error(codes.Internal, err.Error())
	}

	return !notMnt, nil
}

// Mount mounts the source to target path.
func Mount(source, target, fstype string, options []string) error {
	dummyMount := mount.New("")
	return dummyMount.Mount(source, target, fstype, options)
}

// MountOptionsAdd adds the `add` mount options to the `options` and returns a
// new string. In case `add` is already present in the `options`, `add` is not
// added again.
func MountOptionsAdd(options string, add ...string) string {
	opts := strings.Split(options, ",")
	newOpts := []string{}
	// clean original options from empty strings
	for _, opt := range opts {
		if opt != "" {
			newOpts = append(newOpts, opt)
		}
	}

	for _, opt := range add {
		if opt != "" && !contains(newOpts, opt) {
			newOpts = append(newOpts, opt)
		}
	}

	return strings.Join(newOpts, ",")
}

func contains(s []string, key string) bool {
	for _, v := range s {
		if v == key {
			return true
		}
	}

	return false
}
<|endoftext|>