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

// Native Client system calls.

package syscall

const OS = "nacl"

// Auto-generated

//sys	Chmod(path string, mode int) (errno int)
//sys	Clock() (clock int)
//sys	Close(fd int) (errno int)
//sys	Exit(code int)
//sys	Fstat(fd int, stat *Stat_t) (errno int)
//sys	Getdents(fd int, buf []byte) (n int, errno int)
//sys	Getpid() (pid int)
//sys	Gettimeofday(tv *Timeval) (errno int)
//sys	Open(path string, mode int, perm int) (fd int, errno int)
//sys	Read(fd int, p []byte) (n int, errno int)
//sys	read(fd int, buf *byte, nbuf int) (n int, errno int)
//sys	Stat(path string, stat *Stat_t) (errno int)
//sys	Write(fd int, p []byte) (n int, errno int)

//sys	MultimediaInit(subsys int) (errno int)
//sys	MultimediaShutdown() (errno int)

//sys	CondCreate() (cv int, errno int)
//sys	CondWait(cv int, mutex int) (errno int)
//sys	CondSignal(cv int) (errno int)
//sys	CondBroadcast(cv int) (errno int)
//sys	CondTimedWaitAbs(cv int, mutex int, abstime *Timespec) (errno int)
//sys	MutexCreate() (mutex int, errno int)
//sys	MutexLock(mutex int) (errno int)
//sys	MutexUnlock(mutex int) (errno int)
//sys	MutexTryLock(mutex int) (errno int) = SYS_MUTEX_TRYLOCK
//sys	SemCreate() (sema int, errno int)
//sys	SemWait(sema int) (errno int)
//sys	SemPost(sema int) (errno int)
//sys	VideoInit(dx int, dy int) (errno int)
//sys	VideoUpdate(data *uint32) (errno int)
//sys	VideoPollEvent(ev *byte) (errno int)
//sys	VideoShutdown() (errno int)
//sys	AudioInit(fmt int, nreq int, data *int) (errno int)
//sys	AudioShutdown() (errno int)
//sys	AudioStream(data *uint16, size *uintptr) (errno int)

// Hand-written

func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
	// Offset passed to system call is 32 bits.  Failure of vision by NaCl.
	if int64(int32(offset)) != offset {
		return 0, ERANGE
	}
	o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
	return int64(o), int(e)
}

// Sleep by waiting on a condition variable that will never be signaled.
// TODO(rsc): Replace when NaCl adds a proper sleep system call.
var tcv, tmu int

func init() {
	tmu, _ = MutexCreate()
	tcv, _ = CondCreate()
}

func Sleep(ns int64) (errno int) {
	ts := NsecToTimespec(ns)
	var tv Timeval
	if errno = Gettimeofday(&tv); errno != 0 {
		return
	}
	ts.Sec += tv.Sec
	ts.Nsec += tv.Usec * 1000
	switch {
	case ts.Nsec >= 1e9:
		ts.Nsec -= 1e9
		ts.Sec++
	case ts.Nsec <= -1e9:
		ts.Nsec += 1e9
		ts.Sec--
	}
	if errno = MutexLock(tmu); errno != 0 {
		return
	}
	errno = CondTimedWaitAbs(tcv, tmu, &ts)
	if e := MutexUnlock(tmu); e != 0 && errno == 0 {
		errno = e
	}
	return
}

// Implemented in NaCl but not here; maybe later:
//	SYS_IOCTL
//	SYS_IMC_*
//	SYS_MMAP ???
//	SYS_SRPC_*
//	SYS_SYSCONF

// Implemented in NaCl but not here; used by runtime instead:
//	SYS_SYSBRK
//	SYS_MMAP
//	SYS_MUNMAP
//	SYS_THREAD_*
//	SYS_TLS_*
//	SYS_SCHED_YIELD

// #define'd in NaCl but not picked up by mkerrors_nacl.sh.

const EWOULDBLOCK = EAGAIN

// Not implemented in NaCl but needed to compile other packages.

const (
	SIGTRAP = 5
)

func Pipe(p []int) (errno int) { return ENACL }

func fcntl(fd, cmd, arg int) (val int, errno int) {
	return 0, ENACL
}

func Pread(fd int, p []byte, offset int64) (n int, errno int) {
	return 0, ENACL
}

func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
	return 0, ENACL
}

func Mkdir(path string, mode int) (errno int) { return ENACL }

func Lstat(path string, stat *Stat_t) (errno int) {
	return Stat(path, stat)
}

func Chdir(path string) (errno int) { return ENACL }

func Fchdir(fd int) (errno int) { return ENACL }

func Unlink(path string) (errno int) { return ENACL }

func Rmdir(path string) (errno int) { return ENACL }

func Link(oldpath, newpath string) (errno int) {
	return ENACL
}

func Symlink(path, link string) (errno int) { return ENACL }

func Readlink(path string, buf []byte) (n int, errno int) {
	return 0, ENACL
}

func Rename(oldpath, newpath string) (errno int) {
	return ENACL
}

func Fchmod(fd int, mode int) (errno int) { return ENACL }

func Chown(path string, uid int, gid int) (errno int) {
	return ENACL
}

func Lchown(path string, uid int, gid int) (errno int) {
	return ENACL
}

func Fchown(fd int, uid int, gid int) (errno int) {
	return ENACL
}

func Utimes(path string, tv []Timeval) (errno int) {
	return ENACL
}

func Futimes(fd int, tv []Timeval) (errno int) {
	return ENACL
}

func Truncate(name string, size int64) (errno int) {
	return ENACL
}

func Ftruncate(fd int, length int64) (errno int) {
	return ENACL
}

// NaCL doesn't actually implement Getwd, but it also
// don't implement Chdir, so the fallback algorithm
// fails worse than calling Getwd does.

const ImplementsGetwd = true

func Getwd() (wd string, errno int) { return "", ENACL }

func Getuid() (uid int) { return -1 }

func Geteuid() (euid int) { return -1 }

func Getgid() (gid int) { return -1 }

func Getegid() (egid int) { return -1 }

func Getppid() (ppid int) { return -1 }

func Getgroups() (gids []int, errno int) { return nil, ENACL }

type Sockaddr interface {
	sockaddr()
}

type SockaddrInet4 struct {
	Port int
	Addr [4]byte
}

func (*SockaddrInet4) sockaddr() {}

type SockaddrInet6 struct {
	Port int
	Addr [16]byte
}

func (*SockaddrInet6) sockaddr() {}

type SockaddrUnix struct {
	Name string
}

func (*SockaddrUnix) sockaddr() {}

const (
	AF_INET = 1 + iota
	AF_INET6
	AF_UNIX
	IPPROTO_TCP
	SOCK_DGRAM
	SOCK_STREAM
	SOL_SOCKET
	SOMAXCONN
	SO_DONTROUTE
	SO_KEEPALIVE
	SO_LINGER
	SO_RCVBUF
	SO_REUSEADDR
	SO_SNDBUF
	TCP_NODELAY
	WNOHANG
	WSTOPPED
	PTRACE_TRACEME
	SO_BROADCAST = 0
	SHUT_RDWR    = 0
)

func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
	return 0, nil, ENACL
}

func Getsockname(fd int) (sa Sockaddr, errno int) {
	return nil, ENACL
}

func Getpeername(fd int) (sa Sockaddr, errno int) {
	return nil, ENACL
}

func Bind(fd int, sa Sockaddr) (errno int) { return ENACL }

func Connect(fd int, sa Sockaddr) (errno int) { return ENACL }

func Socket(domain, typ, proto int) (fd, errno int) {
	return 0, ENACL
}

func SetsockoptInt(fd, level, opt int, value int) (errno int) {
	return ENACL
}

func Shutdown(fd, how int) (errno int) { return ENACL }

func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
	return 0, nil, ENACL
}

func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
	return ENACL
}

func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
	return ENACL
}

type Linger struct {
	Onoff  int32
	Linger int32
}

func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
	return ENACL
}

func Listen(s int, n int) (errno int) { return ENACL }

type Rusage struct {
	Utime    Timeval
	Stime    Timeval
	Maxrss   int32
	Ixrss    int32
	Idrss    int32
	Isrss    int32
	Minflt   int32
	Majflt   int32
	Nswap    int32
	Inblock  int32
	Oublock  int32
	Msgsnd   int32
	Msgrcv   int32
	Nsignals int32
	Nvcsw    int32
	Nivcsw   int32
}

func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
	return 0, ENACL
}

type WaitStatus uint32

func (WaitStatus) Exited() bool { return false }

func (WaitStatus) ExitStatus() int { return -1 }

func (WaitStatus) Signal() int { return -1 }

func (WaitStatus) CoreDump() bool { return false }

func (WaitStatus) Stopped() bool { return false }

func (WaitStatus) Continued() bool { return false }

func (WaitStatus) StopSignal() int { return -1 }

func (WaitStatus) Signaled() bool { return false }

func (WaitStatus) TrapCause() int { return -1 }
<commit_msg>fix build - nacl stubs<commit_after>// Copyright 2009 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.

// Native Client system calls.

package syscall

const OS = "nacl"

// Auto-generated

//sys	Chmod(path string, mode int) (errno int)
//sys	Clock() (clock int)
//sys	Close(fd int) (errno int)
//sys	Exit(code int)
//sys	Fstat(fd int, stat *Stat_t) (errno int)
//sys	Getdents(fd int, buf []byte) (n int, errno int)
//sys	Getpid() (pid int)
//sys	Gettimeofday(tv *Timeval) (errno int)
//sys	Open(path string, mode int, perm int) (fd int, errno int)
//sys	Read(fd int, p []byte) (n int, errno int)
//sys	read(fd int, buf *byte, nbuf int) (n int, errno int)
//sys	Stat(path string, stat *Stat_t) (errno int)
//sys	Write(fd int, p []byte) (n int, errno int)

//sys	MultimediaInit(subsys int) (errno int)
//sys	MultimediaShutdown() (errno int)

//sys	CondCreate() (cv int, errno int)
//sys	CondWait(cv int, mutex int) (errno int)
//sys	CondSignal(cv int) (errno int)
//sys	CondBroadcast(cv int) (errno int)
//sys	CondTimedWaitAbs(cv int, mutex int, abstime *Timespec) (errno int)
//sys	MutexCreate() (mutex int, errno int)
//sys	MutexLock(mutex int) (errno int)
//sys	MutexUnlock(mutex int) (errno int)
//sys	MutexTryLock(mutex int) (errno int) = SYS_MUTEX_TRYLOCK
//sys	SemCreate() (sema int, errno int)
//sys	SemWait(sema int) (errno int)
//sys	SemPost(sema int) (errno int)
//sys	VideoInit(dx int, dy int) (errno int)
//sys	VideoUpdate(data *uint32) (errno int)
//sys	VideoPollEvent(ev *byte) (errno int)
//sys	VideoShutdown() (errno int)
//sys	AudioInit(fmt int, nreq int, data *int) (errno int)
//sys	AudioShutdown() (errno int)
//sys	AudioStream(data *uint16, size *uintptr) (errno int)

// Hand-written

func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
	// Offset passed to system call is 32 bits.  Failure of vision by NaCl.
	if int64(int32(offset)) != offset {
		return 0, ERANGE
	}
	o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
	return int64(o), int(e)
}

// Sleep by waiting on a condition variable that will never be signaled.
// TODO(rsc): Replace when NaCl adds a proper sleep system call.
var tcv, tmu int

func init() {
	tmu, _ = MutexCreate()
	tcv, _ = CondCreate()
}

func Sleep(ns int64) (errno int) {
	ts := NsecToTimespec(ns)
	var tv Timeval
	if errno = Gettimeofday(&tv); errno != 0 {
		return
	}
	ts.Sec += tv.Sec
	ts.Nsec += tv.Usec * 1000
	switch {
	case ts.Nsec >= 1e9:
		ts.Nsec -= 1e9
		ts.Sec++
	case ts.Nsec <= -1e9:
		ts.Nsec += 1e9
		ts.Sec--
	}
	if errno = MutexLock(tmu); errno != 0 {
		return
	}
	errno = CondTimedWaitAbs(tcv, tmu, &ts)
	if e := MutexUnlock(tmu); e != 0 && errno == 0 {
		errno = e
	}
	return
}

// Implemented in NaCl but not here; maybe later:
//	SYS_IOCTL
//	SYS_IMC_*
//	SYS_MMAP ???
//	SYS_SRPC_*
//	SYS_SYSCONF

// Implemented in NaCl but not here; used by runtime instead:
//	SYS_SYSBRK
//	SYS_MMAP
//	SYS_MUNMAP
//	SYS_THREAD_*
//	SYS_TLS_*
//	SYS_SCHED_YIELD

// #define'd in NaCl but not picked up by mkerrors_nacl.sh.

const EWOULDBLOCK = EAGAIN

// Not implemented in NaCl but needed to compile other packages.

const (
	SIGTRAP = 5
)

func Pipe(p []int) (errno int) { return ENACL }

func fcntl(fd, cmd, arg int) (val int, errno int) {
	return 0, ENACL
}

func Pread(fd int, p []byte, offset int64) (n int, errno int) {
	return 0, ENACL
}

func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
	return 0, ENACL
}

func Mkdir(path string, mode int) (errno int) { return ENACL }

func Lstat(path string, stat *Stat_t) (errno int) {
	return Stat(path, stat)
}

func Chdir(path string) (errno int) { return ENACL }

func Fchdir(fd int) (errno int) { return ENACL }

func Unlink(path string) (errno int) { return ENACL }

func Rmdir(path string) (errno int) { return ENACL }

func Link(oldpath, newpath string) (errno int) {
	return ENACL
}

func Symlink(path, link string) (errno int) { return ENACL }

func Readlink(path string, buf []byte) (n int, errno int) {
	return 0, ENACL
}

func Rename(oldpath, newpath string) (errno int) {
	return ENACL
}

func Fchmod(fd int, mode int) (errno int) { return ENACL }

func Chown(path string, uid int, gid int) (errno int) {
	return ENACL
}

func Lchown(path string, uid int, gid int) (errno int) {
	return ENACL
}

func Fchown(fd int, uid int, gid int) (errno int) {
	return ENACL
}

func Utimes(path string, tv []Timeval) (errno int) {
	return ENACL
}

func Futimes(fd int, tv []Timeval) (errno int) {
	return ENACL
}

func Truncate(name string, size int64) (errno int) {
	return ENACL
}

func Ftruncate(fd int, length int64) (errno int) {
	return ENACL
}

// NaCL doesn't actually implement Getwd, but it also
// don't implement Chdir, so the fallback algorithm
// fails worse than calling Getwd does.

const ImplementsGetwd = true

func Getwd() (wd string, errno int) { return "", ENACL }

func Getuid() (uid int) { return -1 }

func Geteuid() (euid int) { return -1 }

func Getgid() (gid int) { return -1 }

func Getegid() (egid int) { return -1 }

func Getppid() (ppid int) { return -1 }

func Getgroups() (gids []int, errno int) { return nil, ENACL }

type Sockaddr interface {
	sockaddr()
}

type SockaddrInet4 struct {
	Port int
	Addr [4]byte
}

func (*SockaddrInet4) sockaddr() {}

type SockaddrInet6 struct {
	Port int
	Addr [16]byte
}

func (*SockaddrInet6) sockaddr() {}

type SockaddrUnix struct {
	Name string
}

func (*SockaddrUnix) sockaddr() {}

const (
	AF_INET = 1 + iota
	AF_INET6
	AF_UNIX
	IPPROTO_TCP
	SOCK_DGRAM
	SOCK_STREAM
	SOCK_RAW
	SOL_SOCKET
	SOMAXCONN
	SO_DONTROUTE
	SO_KEEPALIVE
	SO_LINGER
	SO_RCVBUF
	SO_REUSEADDR
	SO_SNDBUF
	TCP_NODELAY
	WNOHANG
	WSTOPPED
	PTRACE_TRACEME
	SO_BROADCAST = 0
	SHUT_RDWR    = 0
)

func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
	return 0, nil, ENACL
}

func Getsockname(fd int) (sa Sockaddr, errno int) {
	return nil, ENACL
}

func Getpeername(fd int) (sa Sockaddr, errno int) {
	return nil, ENACL
}

func Bind(fd int, sa Sockaddr) (errno int) { return ENACL }

func BindToDevice(fd int, device string) (errno int) { return ENACL }

func Connect(fd int, sa Sockaddr) (errno int) { return ENACL }

func Socket(domain, typ, proto int) (fd, errno int) {
	return 0, ENACL
}

func SetsockoptInt(fd, level, opt int, value int) (errno int) {
	return ENACL
}

func Shutdown(fd, how int) (errno int) { return ENACL }

func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
	return 0, nil, ENACL
}

func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
	return ENACL
}

func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
	return ENACL
}

type Linger struct {
	Onoff  int32
	Linger int32
}

func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
	return ENACL
}

func Listen(s int, n int) (errno int) { return ENACL }

type Rusage struct {
	Utime    Timeval
	Stime    Timeval
	Maxrss   int32
	Ixrss    int32
	Idrss    int32
	Isrss    int32
	Minflt   int32
	Majflt   int32
	Nswap    int32
	Inblock  int32
	Oublock  int32
	Msgsnd   int32
	Msgrcv   int32
	Nsignals int32
	Nvcsw    int32
	Nivcsw   int32
}

func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
	return 0, ENACL
}

type WaitStatus uint32

func (WaitStatus) Exited() bool { return false }

func (WaitStatus) ExitStatus() int { return -1 }

func (WaitStatus) Signal() int { return -1 }

func (WaitStatus) CoreDump() bool { return false }

func (WaitStatus) Stopped() bool { return false }

func (WaitStatus) Continued() bool { return false }

func (WaitStatus) StopSignal() int { return -1 }

func (WaitStatus) Signaled() bool { return false }

func (WaitStatus) TrapCause() int { return -1 }
<|endoftext|>


<commit_before>package cli

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/99designs/aws-vault/server"
	"github.com/99designs/aws-vault/vault"
	"github.com/99designs/keyring"
	"gopkg.in/alecthomas/kingpin.v2"
)

type ExecCommandInput struct {
	ProfileName      string
	Command          string
	Args             []string
	Keyring          keyring.Keyring
	StartServer      bool
	CredentialHelper bool
	Signals          chan os.Signal
	Config           vault.Config
}

// json metadata for AWS credential process. Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes
type AwsCredentialHelperData struct {
	Version         int    `json:"Version"`
	AccessKeyID     string `json:"AccessKeyId"`
	SecretAccessKey string `json:"SecretAccessKey"`
	SessionToken    string `json:"SessionToken"`
	Expiration      string `json:"Expiration,omitempty"`
}

func ConfigureExecCommand(app *kingpin.Application) {
	input := ExecCommandInput{}

	cmd := app.Command("exec", "Executes a command with AWS credentials in the environment")
	cmd.Flag("no-session", "Use root credentials, no session created").
		Short('n').
		BoolVar(&input.Config.NoSession)

	cmd.Flag("session-ttl", "Expiration time for aws session").
		Default("4h").
		Envar("AWS_SESSION_TTL").
		Short('t').
		DurationVar(&input.Config.SessionDuration)

	cmd.Flag("assume-role-ttl", "Expiration time for aws assumed role").
		Default("15m").
		Envar("AWS_ASSUME_ROLE_TTL").
		DurationVar(&input.Config.AssumeRoleDuration)

	cmd.Flag("mfa-token", "The mfa token to use").
		Short('m').
		StringVar(&input.Config.MfaToken)

	cmd.Flag("mfa-serial-override", "Deprecated, use --mfa-serial instead").
		Hidden().
		StringVar(&input.Config.MfaSerial)

	cmd.Flag("mfa-serial", "The identification number of the MFA device to use").
		StringVar(&input.Config.MfaSerial)

	cmd.Flag("json", "AWS credential helper. Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes").
		Short('j').
		BoolVar(&input.CredentialHelper)

	cmd.Flag("server", "Run the server in the background for credentials").
		Short('s').
		BoolVar(&input.StartServer)

	cmd.Arg("profile", "Name of the profile").
		Required().
		HintAction(awsConfigFile.ProfileNames).
		StringVar(&input.ProfileName)

	cmd.Arg("cmd", "Command to execute").
		Default(os.Getenv("SHELL")).
		StringVar(&input.Command)

	cmd.Arg("args", "Command arguments").
		StringsVar(&input.Args)

	cmd.Action(func(c *kingpin.ParseContext) error {
		input.Keyring = keyringImpl
		input.Config.MfaPromptMethod = GlobalFlags.PromptDriver
		input.Signals = make(chan os.Signal)
		ExecCommand(app, input)
		return nil
	})
}

func ExecCommand(app *kingpin.Application, input ExecCommandInput) {
	if os.Getenv("AWS_VAULT") != "" {
		app.Fatalf("aws-vault sessions should be nested with care, unset $AWS_VAULT to force")
		return
	}

	var setEnv = true

	if input.Config.NoSession && input.StartServer {
		app.Fatalf("Can't start a credential server without a session")
		return
	}

	err := configLoader.LoadFromProfile(input.ProfileName, &input.Config)
	if err != nil {
		app.Fatalf("%v", err)
		return
	}

	creds, err := vault.NewTempCredentials(input.Keyring, &input.Config)
	if err != nil {
		app.Fatalf("%v", err)
		return
	}

	val, err := creds.Get()
	if err != nil {
		app.Fatalf(FormatCredentialError(err, input.Config.CredentialsName))
		return
	}

	if input.StartServer {
		if err := server.StartCredentialsServer(creds); err != nil {
			app.Fatalf("Failed to start credential server: %v", err)
			return
		} else {
			setEnv = false
		}
	}

	if input.CredentialHelper {
		credentialData := AwsCredentialHelperData{
			Version:         1,
			AccessKeyID:     val.AccessKeyID,
			SecretAccessKey: val.SecretAccessKey,
			SessionToken:    val.SessionToken,
		}
		if !input.Config.NoSession {
			credsExprest, err := creds.ExpiresAt()
			if err != nil {
				app.Fatalf("Error getting credential expiration: %v", err)
				return
			}
			credentialData.Expiration = credsExprest.Format("2006-01-02T15:04:05Z")
		}
		json, err := json.Marshal(&credentialData)
		if err != nil {
			app.Fatalf("Error creating credential json")
			return
		}
		fmt.Printf(string(json))
	} else {

		env := environ(os.Environ())
		env.Set("AWS_VAULT", input.ProfileName)

		env.Unset("AWS_ACCESS_KEY_ID")
		env.Unset("AWS_SECRET_ACCESS_KEY")
		env.Unset("AWS_CREDENTIAL_FILE")
		env.Unset("AWS_DEFAULT_PROFILE")
		env.Unset("AWS_PROFILE")

		if input.Config.Region != "" {
			log.Printf("Setting subprocess env: AWS_DEFAULT_REGION=%s, AWS_REGION=%s", input.Config.Region, input.Config.Region)
			env.Set("AWS_DEFAULT_REGION", input.Config.Region)
			env.Set("AWS_REGION", input.Config.Region)
		}

		if setEnv {
			log.Println("Setting subprocess env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY")
			env.Set("AWS_ACCESS_KEY_ID", val.AccessKeyID)
			env.Set("AWS_SECRET_ACCESS_KEY", val.SecretAccessKey)

			if val.SessionToken != "" {
				log.Println("Setting subprocess env: AWS_SESSION_TOKEN, AWS_SECURITY_TOKEN")
				env.Set("AWS_SESSION_TOKEN", val.SessionToken)
				env.Set("AWS_SECURITY_TOKEN", val.SessionToken)
			}
		}

		err = exec(input.Command, input.Args, env)
		if err != nil {
			app.Fatalf("%v", err)
			return
		}
	}
}

// environ is a slice of strings representing the environment, in the form "key=value".
type environ []string

// Unset an environment variable by key
func (e *environ) Unset(key string) {
	for i := range *e {
		if strings.HasPrefix((*e)[i], key+"=") {
			(*e)[i] = (*e)[len(*e)-1]
			*e = (*e)[:len(*e)-1]
			break
		}
	}
}

// Set adds an environment variable, replacing any existing ones of the same key
func (e *environ) Set(key, val string) {
	e.Unset(key)
	*e = append(*e, key+"="+val)
}
<commit_msg>Remove unused variable<commit_after>package cli

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/99designs/aws-vault/server"
	"github.com/99designs/aws-vault/vault"
	"github.com/99designs/keyring"
	"gopkg.in/alecthomas/kingpin.v2"
)

type ExecCommandInput struct {
	ProfileName      string
	Command          string
	Args             []string
	Keyring          keyring.Keyring
	StartServer      bool
	CredentialHelper bool
	Config           vault.Config
}

// json metadata for AWS credential process. Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes
type AwsCredentialHelperData struct {
	Version         int    `json:"Version"`
	AccessKeyID     string `json:"AccessKeyId"`
	SecretAccessKey string `json:"SecretAccessKey"`
	SessionToken    string `json:"SessionToken"`
	Expiration      string `json:"Expiration,omitempty"`
}

func ConfigureExecCommand(app *kingpin.Application) {
	input := ExecCommandInput{}

	cmd := app.Command("exec", "Executes a command with AWS credentials in the environment")
	cmd.Flag("no-session", "Use root credentials, no session created").
		Short('n').
		BoolVar(&input.Config.NoSession)

	cmd.Flag("session-ttl", "Expiration time for aws session").
		Default("4h").
		Envar("AWS_SESSION_TTL").
		Short('t').
		DurationVar(&input.Config.SessionDuration)

	cmd.Flag("assume-role-ttl", "Expiration time for aws assumed role").
		Default("15m").
		Envar("AWS_ASSUME_ROLE_TTL").
		DurationVar(&input.Config.AssumeRoleDuration)

	cmd.Flag("mfa-token", "The mfa token to use").
		Short('m').
		StringVar(&input.Config.MfaToken)

	cmd.Flag("mfa-serial-override", "Deprecated, use --mfa-serial instead").
		Hidden().
		StringVar(&input.Config.MfaSerial)

	cmd.Flag("mfa-serial", "The identification number of the MFA device to use").
		StringVar(&input.Config.MfaSerial)

	cmd.Flag("json", "AWS credential helper. Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes").
		Short('j').
		BoolVar(&input.CredentialHelper)

	cmd.Flag("server", "Run the server in the background for credentials").
		Short('s').
		BoolVar(&input.StartServer)

	cmd.Arg("profile", "Name of the profile").
		Required().
		HintAction(awsConfigFile.ProfileNames).
		StringVar(&input.ProfileName)

	cmd.Arg("cmd", "Command to execute").
		Default(os.Getenv("SHELL")).
		StringVar(&input.Command)

	cmd.Arg("args", "Command arguments").
		StringsVar(&input.Args)

	cmd.Action(func(c *kingpin.ParseContext) error {
		input.Keyring = keyringImpl
		input.Config.MfaPromptMethod = GlobalFlags.PromptDriver
		ExecCommand(app, input)
		return nil
	})
}

func ExecCommand(app *kingpin.Application, input ExecCommandInput) {
	if os.Getenv("AWS_VAULT") != "" {
		app.Fatalf("aws-vault sessions should be nested with care, unset $AWS_VAULT to force")
		return
	}

	var setEnv = true

	if input.Config.NoSession && input.StartServer {
		app.Fatalf("Can't start a credential server without a session")
		return
	}

	err := configLoader.LoadFromProfile(input.ProfileName, &input.Config)
	if err != nil {
		app.Fatalf("%v", err)
		return
	}

	creds, err := vault.NewTempCredentials(input.Keyring, &input.Config)
	if err != nil {
		app.Fatalf("%v", err)
		return
	}

	val, err := creds.Get()
	if err != nil {
		app.Fatalf(FormatCredentialError(err, input.Config.CredentialsName))
		return
	}

	if input.StartServer {
		if err := server.StartCredentialsServer(creds); err != nil {
			app.Fatalf("Failed to start credential server: %v", err)
			return
		} else {
			setEnv = false
		}
	}

	if input.CredentialHelper {
		credentialData := AwsCredentialHelperData{
			Version:         1,
			AccessKeyID:     val.AccessKeyID,
			SecretAccessKey: val.SecretAccessKey,
			SessionToken:    val.SessionToken,
		}
		if !input.Config.NoSession {
			credsExprest, err := creds.ExpiresAt()
			if err != nil {
				app.Fatalf("Error getting credential expiration: %v", err)
				return
			}
			credentialData.Expiration = credsExprest.Format("2006-01-02T15:04:05Z")
		}
		json, err := json.Marshal(&credentialData)
		if err != nil {
			app.Fatalf("Error creating credential json")
			return
		}
		fmt.Printf(string(json))
	} else {

		env := environ(os.Environ())
		env.Set("AWS_VAULT", input.ProfileName)

		env.Unset("AWS_ACCESS_KEY_ID")
		env.Unset("AWS_SECRET_ACCESS_KEY")
		env.Unset("AWS_CREDENTIAL_FILE")
		env.Unset("AWS_DEFAULT_PROFILE")
		env.Unset("AWS_PROFILE")

		if input.Config.Region != "" {
			log.Printf("Setting subprocess env: AWS_DEFAULT_REGION=%s, AWS_REGION=%s", input.Config.Region, input.Config.Region)
			env.Set("AWS_DEFAULT_REGION", input.Config.Region)
			env.Set("AWS_REGION", input.Config.Region)
		}

		if setEnv {
			log.Println("Setting subprocess env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY")
			env.Set("AWS_ACCESS_KEY_ID", val.AccessKeyID)
			env.Set("AWS_SECRET_ACCESS_KEY", val.SecretAccessKey)

			if val.SessionToken != "" {
				log.Println("Setting subprocess env: AWS_SESSION_TOKEN, AWS_SECURITY_TOKEN")
				env.Set("AWS_SESSION_TOKEN", val.SessionToken)
				env.Set("AWS_SECURITY_TOKEN", val.SessionToken)
			}
		}

		err = exec(input.Command, input.Args, env)
		if err != nil {
			app.Fatalf("%v", err)
			return
		}
	}
}

// environ is a slice of strings representing the environment, in the form "key=value".
type environ []string

// Unset an environment variable by key
func (e *environ) Unset(key string) {
	for i := range *e {
		if strings.HasPrefix((*e)[i], key+"=") {
			(*e)[i] = (*e)[len(*e)-1]
			*e = (*e)[:len(*e)-1]
			break
		}
	}
}

// Set adds an environment variable, replacing any existing ones of the same key
func (e *environ) Set(key, val string) {
	e.Unset(key)
	*e = append(*e, key+"="+val)
}
<|endoftext|>


<commit_before>/*

cli is a simple package to allow a game to render to the screen and be
interacted with. It's intended primarily as a tool to diagnose and play around
with a game while its moves and logic are being defined.

*/
package cli

import (
	"fmt"
	"github.com/jkomoros/boardgame"
	"github.com/jroimartin/gocui"
)

type renderType int

const (
	renderJSON renderType = iota
	renderRender
)

//Controller is the primary type of the package.
type Controller struct {
	game     *boardgame.Game
	gui      *gocui.Gui
	renderer RendererFunc
	render   renderType
}

//RenderrerFunc takes a state and outputs a list of strings that should be
//printed to screen to depict it.
type RendererFunc func(boardgame.StatePayload) string

func NewController(game *boardgame.Game, renderer RendererFunc) *Controller {
	return &Controller{
		game:     game,
		renderer: renderer,
	}
}

//Implement the gocui.Manager interface
func (c *Controller) Layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("main", 0, 0, maxX-1, maxY-2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = "JSON"
		v.Frame = true
	}

	if v, err := g.SetView("status", 0, maxY-2, maxX-1, maxY); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.FgColor = gocui.ColorBlack
		v.BgColor = gocui.ColorWhite
		v.Frame = false
	}

	//Update the json field of view

	if view, err := g.View("main"); err == nil {
		view.Clear()
		switch c.render {
		case renderRender:
			//Print renderered view
			fmt.Fprint(view, c.renderer(c.game.State.Payload))
			view.Title = "Rendered"
		case renderJSON:
			//Print JSON view
			fmt.Fprint(view, string(boardgame.Serialize(c.game.State.JSON())))
			view.Title = "JSON"
		}

	}

	if view, err := g.View("status"); err == nil {
		view.Clear()
		fmt.Fprint(view, "Type 't' to toggle json or render output, Ctrl-C to quit")
	}

	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

func (c *Controller) ScrollUp() {
	var view *gocui.View
	var err error
	if view, err = c.gui.View("main"); err != nil {
		return
	}
	x, y := view.Origin()
	view.SetOrigin(x, y-1)
}

func (c *Controller) ScrollDown() {
	var view *gocui.View
	var err error
	if view, err = c.gui.View("main"); err != nil {
		return
	}
	x, y := view.Origin()
	view.SetOrigin(x, y+1)
}

//Once the controller is set up, call Start. It will block until it is time
//to exit.
func (c *Controller) Start() {

	g, err := gocui.NewGui(gocui.OutputNormal)

	if err != nil {
		panic("Couldn't create gui:" + err.Error())
	}

	defer g.Close()

	c.gui = g

	//manager has to be set before setting keybindings, because it clears all
	//keybindings when set.
	g.SetManager(c)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", 't', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ToggleRender()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollUp()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.MouseWheelUp, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollUp()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollDown()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.MouseWheelDown, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollDown()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		panic(err)
	}

}

func (c *Controller) ToggleRender() {
	c.render++
	if c.render > renderRender {
		c.render = 0
	}
}
<commit_msg>Reorganize controller methods for clarity<commit_after>/*

cli is a simple package to allow a game to render to the screen and be
interacted with. It's intended primarily as a tool to diagnose and play around
with a game while its moves and logic are being defined.

*/
package cli

import (
	"fmt"
	"github.com/jkomoros/boardgame"
	"github.com/jroimartin/gocui"
)

type renderType int

const (
	renderJSON renderType = iota
	renderRender
)

//Controller is the primary type of the package.
type Controller struct {
	game     *boardgame.Game
	gui      *gocui.Gui
	renderer RendererFunc
	render   renderType
}

//RenderrerFunc takes a state and outputs a list of strings that should be
//printed to screen to depict it.
type RendererFunc func(boardgame.StatePayload) string

func NewController(game *boardgame.Game, renderer RendererFunc) *Controller {
	return &Controller{
		game:     game,
		renderer: renderer,
	}
}

//Implement the gocui.Manager interface
func (c *Controller) Layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("main", 0, 0, maxX-1, maxY-2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = "JSON"
		v.Frame = true
	}

	if v, err := g.SetView("status", 0, maxY-2, maxX-1, maxY); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.FgColor = gocui.ColorBlack
		v.BgColor = gocui.ColorWhite
		v.Frame = false
	}

	//Update the json field of view

	if view, err := g.View("main"); err == nil {
		view.Clear()
		switch c.render {
		case renderRender:
			//Print renderered view
			fmt.Fprint(view, c.renderer(c.game.State.Payload))
			view.Title = "Rendered"
		case renderJSON:
			//Print JSON view
			fmt.Fprint(view, string(boardgame.Serialize(c.game.State.JSON())))
			view.Title = "JSON"
		}

	}

	if view, err := g.View("status"); err == nil {
		view.Clear()
		fmt.Fprint(view, "Type 't' to toggle json or render output, Ctrl-C to quit")
	}

	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

func (c *Controller) ScrollUp() {
	var view *gocui.View
	var err error
	if view, err = c.gui.View("main"); err != nil {
		return
	}
	x, y := view.Origin()
	view.SetOrigin(x, y-1)
}

func (c *Controller) ScrollDown() {
	var view *gocui.View
	var err error
	if view, err = c.gui.View("main"); err != nil {
		return
	}
	x, y := view.Origin()
	view.SetOrigin(x, y+1)
}

func (c *Controller) ToggleRender() {
	c.render++
	if c.render > renderRender {
		c.render = 0
	}
}

//Once the controller is set up, call Start. It will block until it is time
//to exit.
func (c *Controller) Start() {

	g, err := gocui.NewGui(gocui.OutputNormal)

	if err != nil {
		panic("Couldn't create gui:" + err.Error())
	}

	defer g.Close()

	c.gui = g

	//manager has to be set before setting keybindings, because it clears all
	//keybindings when set.
	g.SetManager(c)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", 't', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ToggleRender()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollUp()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.MouseWheelUp, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollUp()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollDown()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.SetKeybinding("", gocui.MouseWheelDown, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
		c.ScrollDown()
		return nil
	}); err != nil {
		panic(err)
	}

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		panic(err)
	}

}
<|endoftext|>


<commit_before>package dnsp

import (
	"log"
	"regexp"
	"strings"

	"github.com/miekg/dns"
)

type hosts map[string]struct{}

// isAllowed returns whether we are allowed to resolve this host.
//
// If the server is whitelisting, the result will be true if the host is on the whitelist.
// If the server is blacklisting, the result will be true if the host is NOT on the blacklist.
//
// NOTE: "host" must end with a dot.
func (s *Server) isAllowed(host string) bool {
	s.m.RLock()
	defer s.m.RUnlock()

	_, ok := s.hosts[host]

	if s.white { // whitelist mode
		if ok {
			return true
		}
		for _, rx := range s.hostsRX {
			if rx.MatchString(host) {
				return true
			}
		}
		return false
	}

	// blacklist mode
	if ok {
		return false
	}
	for _, rx := range s.hostsRX {
		if rx.MatchString(host) {
			return false
		}
	}
	return true
}

func (s *Server) filter(qs []dns.Question) []dns.Question {
	result := []dns.Question{}
	for _, q := range qs {
		if s.isAllowed(q.Name) {
			result = append(result, q)
		}
	}
	return result
}

// Load the host entries into separate structures and swap the existing entries.
func (s *Server) loadHostEntries(path string) error {
	hosts := hosts{}
	hostsRX := []*regexp.Regexp{}

	if err := readHosts(path, func(host string) {
		if host[len(host)-1] != '.' {
			host += "."
		}

		if !strings.ContainsRune(host, '*') {
			// Plain host string:
			hosts[host] = struct{}{}
		} else if pat := compilePattern(host); pat != nil {
			// Host pattern (regex):
			hostsRX = append(hostsRX, compilePattern(host))
		}
	}); err != nil {
		return err
	}

	s.m.Lock()
	s.hosts = hosts
	s.hostsRX = hostsRX
	s.m.Unlock()

	return nil
}

func (s *Server) addHostEntry(host string) {
	if host == "" {
		return
	}
	if host[len(host)-1] != '.' {
		host += "."
	}

	if !strings.ContainsRune(host, '*') {
		// Plain host string:
		s.m.Lock()
		s.hosts[host] = struct{}{}
		s.m.Unlock()
	} else if rx := compilePattern(host); rx != nil {
		// Host pattern (regex):
		s.m.Lock()
		s.hostsRX = append(s.hostsRX, rx)
		s.m.Unlock()
	}
}

func compilePattern(pat string) *regexp.Regexp {
	pat = strings.Replace(pat, ".", `\.`, -1)
	pat = strings.Replace(pat, "*", ".*", -1)
	pat = "^" + pat + `$`
	rx, err := regexp.Compile(pat)
	if err != nil {
		log.Printf("dnsp: could not compile %q: %s", pat, err)
		return nil
	}
	return rx
}
<commit_msg>add s.removeHostEntry<commit_after>package dnsp

import (
	"log"
	"regexp"
	"strings"

	"github.com/miekg/dns"
)

type hosts map[string]struct{}

// isAllowed returns whether we are allowed to resolve this host.
//
// If the server is whitelisting, the result will be true if the host is on the whitelist.
// If the server is blacklisting, the result will be true if the host is NOT on the blacklist.
//
// NOTE: "host" must end with a dot.
func (s *Server) isAllowed(host string) bool {
	s.m.RLock()
	defer s.m.RUnlock()

	_, ok := s.hosts[host]

	if s.white { // whitelist mode
		if ok {
			return true
		}
		for _, rx := range s.hostsRX {
			if rx.MatchString(host) {
				return true
			}
		}
		return false
	}

	// blacklist mode
	if ok {
		return false
	}
	for _, rx := range s.hostsRX {
		if rx.MatchString(host) {
			return false
		}
	}
	return true
}

func (s *Server) filter(qs []dns.Question) []dns.Question {
	result := []dns.Question{}
	for _, q := range qs {
		if s.isAllowed(q.Name) {
			result = append(result, q)
		}
	}
	return result
}

// Load the host entries into separate structures and swap the existing entries.
func (s *Server) loadHostEntries(path string) error {
	hosts := hosts{}
	hostsRX := []*regexp.Regexp{}

	if err := readHosts(path, func(host string) {
		if host[len(host)-1] != '.' {
			host += "."
		}

		if !strings.ContainsRune(host, '*') {
			// Plain host string:
			hosts[host] = struct{}{}
		} else if pat := compilePattern(host); pat != nil {
			// Host pattern (regex):
			hostsRX = append(hostsRX, compilePattern(host))
		}
	}); err != nil {
		return err
	}

	s.m.Lock()
	s.hosts = hosts
	s.hostsRX = hostsRX
	s.m.Unlock()

	return nil
}

func (s *Server) addHostEntry(host string) {
	if host == "" {
		return
	}
	if host[len(host)-1] != '.' {
		host += "."
	}

	if !strings.ContainsRune(host, '*') {
		// Plain host string:
		s.m.Lock()
		s.hosts[host] = struct{}{}
		s.m.Unlock()
	} else if rx := compilePattern(host); rx != nil {
		// Host pattern (regex):
		s.m.Lock()
		s.hostsRX = append(s.hostsRX, rx)
		s.m.Unlock()
	}
}

func (s *Server) removeHostEntry(host string) {
	if host == "" {
		return
	}
	if host[len(host)-1] != '.' {
		host += "."
	}

	if !strings.ContainsRune(host, '*') {
		// Plain host string:
		s.m.Lock()
		delete(s.hosts, host)
		s.m.Unlock()
	} else if rx := compilePattern(host); rx != nil {
		// Host pattern (regex):
		pat := rx.String()
		for i, rx := range s.hostsRX {
			if rx.String() == pat {
				tail := len(s.hostsRX) - 1
				// Swap the current element with the last one:
				s.hostsRX[i] = s.hostsRX[tail]
				// Re-slice to pop the last element:
				s.hostsRX = s.hostsRX[:tail]
				break
			}
		}
		s.m.Unlock()
	}
}

func compilePattern(pat string) *regexp.Regexp {
	pat = strings.Replace(pat, ".", `\.`, -1)
	pat = strings.Replace(pat, "*", ".*", -1)
	pat = "^" + pat + `$`
	rx, err := regexp.Compile(pat)
	if err != nil {
		log.Printf("dnsp: could not compile %q: %s", pat, err)
		return nil
	}
	return rx
}
<|endoftext|>


<commit_before>// Package clog implements a python-like, module-based logger with a variety of
// backends and formats.
//
// This logger is based on Python's fantastic logging package, though it intends
// to be far simpler. Every part of the system should have its own individual
// logger, specific by a module name, so that its messages can be easily
// distinguished from other parts. In golang's log package, people have
// typically resorted to prefixing messages with things like "[INFO module]",
// but that is tedious, error prone, rather un-enforceable for external
// pacakges, and impossible to serialize for all logging services.
//
// Clog takes the approach that data should be represented as data, not strings
// (there are methods such as Infod, Warnd, etc), and this data is properly
// serialized for all output formats. Each message includes a timestamp, the
// module that generated the message, the level, and the source file and line.
//
// Like python's logging, clog modules are heirachical, in that rules for
// something like "server.http" will be applied to "server.http.requests" and
// "server.http.responses" as the messages propogate. Each module may have
// multiple outputs, so you may log to both a file and logstash for the same
// module, if you wish.
//
// Configuration
//
// Configuring logging packages has always been a rather daunting affair, but
// clog takes great pains to be as simple as possible.
//
// First, there are 2 concepts in logging: Outputs and Modules. Outputs are
// where log messages are written to, ie. a file, an external service, syslog,
// etc. Modules are where messages come from, ie. "http" for the http interface,
// "library.name" for some library named "name". You may choose your own values
// for these, just know that they're arranged in a tree, such that
// "http.request" is a child of "http" and messages from it propagate to "http".
//
// There are a variety of formats and output types. Each of them, along with
// their arguments, is documented below.
//
// The outputs list their "Which" for selecting the output; this is the value
// that you pass to ConfigOutput.Which.
//
// Since examples are worth more than descriptions, let's take a look at a
// pretty complex configuration, with comments explaining how it all works
// together.
//
//     Config{
//         // If set, this creates a new root module (the module named "" (the empty
//         // string)), and it records any message level >= Info to the named file in
//         // JSON format.
//         File: "/var/log/app.log",
//
//         Outputs: map[string]*ConfigOutput{
//             // Only errors with level >= Error will be logged here
//             "errors": {
//                 Which:   "jsonfile",
//                 Level:   Error,
//                 Filters: []string{"exampleFilter"},
//                 Args: ConfigOutputArgs{
//                     "path": "/var/log/app.jlog",
//                 },
//             },
//
//             // All messages will be accepted here
//             "debug": {
//                 Which: "file",
//                 Level: Debug,
//                 Args: ConfigOutputArgs{
//                     "path":   "/var/log/app.jlog",
//                     "format": "json",
//                 },
//             },
//
//             // Only errors level >= Warn will be accepted here
//             "heroku": {
//                 Which: "file",
//                 Level: Warn,
//                 Args: ConfigOutputArgs{
//                     "path":   "/var/log/app.lfmt",
//                     "format": "logfmt",
//                 },
//             },
//         },
//
//         Modules: map[string]*ConfigModule{
//             // All messages eventually reach here, unless DontPropagate==true in a
//             // module
//             "": {
//                 Outputs: []string{"errors"},
//             },
//
//             // This logs all messages level >= Info, where the filter allows the
//             // message through, to the debug log. These messages do not propagate to
//             // the root.
//             "http": {
//                 Outputs:       []string{"debug"},
//                 Level:         Info,
//                 Filters:       []string{"exampleFilter"},
//                 DontPropagate: true,
//             },
//
//             // This logs all messages level >= Warn, to both the heroku and errors
//             // outputs. These messages do not propagate to the root.
//             "templates": {
//                 Outputs:       []string{"heroku", "errors"},
//                 Level:         Warn,
//                 DontPropagate: true,
//             },
//
//             // This logs all messages from the external library to the debug log.
//             // These messages also propagate to the root, which will log any error
//             // messages. So, effectively, errors from this module will be logged
//             // twice.
//             "external.library": {
//                 Outputs: []string{"debug"},
//                 Level:   Debug,
//             },
//         },
//     }
//
// File Output
//
// Arguments:
//     "Format": which format to use. Valid formats are:
//         - logfmt: output in Heroku's logfmt
//         - json: output json data
//         - human: output human-readable data
//     "Path": path of the log file to write to
//
// If you're using the "human" log formatter, you may also include its arguments
// in the file's arguments.
//
// Which:
//     - To select file, use the value "file"
//     - As a shortcut to select the json formatter, the value "JSONFile" also exists
//
// Terminal Output
//
// You may also write to the terminal. By default, this uses the human
// formatter.
//
// Arguments:
//     "Stdout": if output should go to stdout instead of stderr
//
// Which:
//     term
//     terminal
//
// Testlog Output
//
// This output is for capturing the output of your application to the test log,
// so that if a test fails, you have the entire application log handy, otherwise
// it's all hidden.
//
// This is a special output in that it must be configured programmatically.
// Instead, you would configure it directly in Config itself, as follows:
//
//     Config{
//         Output: map[string]*ConfigOutput{
//             "testlog": {
//                 Which: "testlog",
//                 Args: ConfigOutputArgs{
//                     "log": t, // a *testing.T
//                 }
//             }
//         }
//     }
//
// In the above example, you pass a *testing.T as the argument; really, it will
// accept anything with a `Log(...interface{})` method. All log output will be
// directed to this function as a single string.
//
// Which:
//     TestLog
//
// Human-readable Format
//
// Arguments:
//     "ShortTime": if true, timestamps in entries are printed as time since start
package clog
<commit_msg>Fix commas in clog docs<commit_after>// Package clog implements a python-like, module-based logger with a variety of
// backends and formats.
//
// This logger is based on Python's fantastic logging package, though it intends
// to be far simpler. Every part of the system should have its own individual
// logger, specific by a module name, so that its messages can be easily
// distinguished from other parts. In golang's log package, people have
// typically resorted to prefixing messages with things like "[INFO module]",
// but that is tedious, error prone, rather un-enforceable for external
// pacakges, and impossible to serialize for all logging services.
//
// Clog takes the approach that data should be represented as data, not strings
// (there are methods such as Infod, Warnd, etc), and this data is properly
// serialized for all output formats. Each message includes a timestamp, the
// module that generated the message, the level, and the source file and line.
//
// Like python's logging, clog modules are heirachical, in that rules for
// something like "server.http" will be applied to "server.http.requests" and
// "server.http.responses" as the messages propogate. Each module may have
// multiple outputs, so you may log to both a file and logstash for the same
// module, if you wish.
//
// Configuration
//
// Configuring logging packages has always been a rather daunting affair, but
// clog takes great pains to be as simple as possible.
//
// First, there are 2 concepts in logging: Outputs and Modules. Outputs are
// where log messages are written to, ie. a file, an external service, syslog,
// etc. Modules are where messages come from, ie. "http" for the http interface,
// "library.name" for some library named "name". You may choose your own values
// for these, just know that they're arranged in a tree, such that
// "http.request" is a child of "http" and messages from it propagate to "http".
//
// There are a variety of formats and output types. Each of them, along with
// their arguments, is documented below.
//
// The outputs list their "Which" for selecting the output; this is the value
// that you pass to ConfigOutput.Which.
//
// Since examples are worth more than descriptions, let's take a look at a
// pretty complex configuration, with comments explaining how it all works
// together.
//
//     Config{
//         // If set, this creates a new root module (the module named "" (the empty
//         // string)), and it records any message level >= Info to the named file in
//         // JSON format.
//         File: "/var/log/app.log",
//
//         Outputs: map[string]*ConfigOutput{
//             // Only errors with level >= Error will be logged here
//             "errors": {
//                 Which:   "jsonfile",
//                 Level:   Error,
//                 Filters: []string{"exampleFilter"},
//                 Args: ConfigOutputArgs{
//                     "path": "/var/log/app.jlog",
//                 },
//             },
//
//             // All messages will be accepted here
//             "debug": {
//                 Which: "file",
//                 Level: Debug,
//                 Args: ConfigOutputArgs{
//                     "path":   "/var/log/app.jlog",
//                     "format": "json",
//                 },
//             },
//
//             // Only errors level >= Warn will be accepted here
//             "heroku": {
//                 Which: "file",
//                 Level: Warn,
//                 Args: ConfigOutputArgs{
//                     "path":   "/var/log/app.lfmt",
//                     "format": "logfmt",
//                 },
//             },
//         },
//
//         Modules: map[string]*ConfigModule{
//             // All messages eventually reach here, unless DontPropagate==true in a
//             // module
//             "": {
//                 Outputs: []string{"errors"},
//             },
//
//             // This logs all messages level >= Info, where the filter allows the
//             // message through, to the debug log. These messages do not propagate to
//             // the root.
//             "http": {
//                 Outputs:       []string{"debug"},
//                 Level:         Info,
//                 Filters:       []string{"exampleFilter"},
//                 DontPropagate: true,
//             },
//
//             // This logs all messages level >= Warn, to both the heroku and errors
//             // outputs. These messages do not propagate to the root.
//             "templates": {
//                 Outputs:       []string{"heroku", "errors"},
//                 Level:         Warn,
//                 DontPropagate: true,
//             },
//
//             // This logs all messages from the external library to the debug log.
//             // These messages also propagate to the root, which will log any error
//             // messages. So, effectively, errors from this module will be logged
//             // twice.
//             "external.library": {
//                 Outputs: []string{"debug"},
//                 Level:   Debug,
//             },
//         },
//     }
//
// File Output
//
// Arguments:
//     "Format": which format to use. Valid formats are:
//         - logfmt: output in Heroku's logfmt
//         - json: output json data
//         - human: output human-readable data
//     "Path": path of the log file to write to
//
// If you're using the "human" log formatter, you may also include its arguments
// in the file's arguments.
//
// Which:
//     - To select file, use the value "file"
//     - As a shortcut to select the json formatter, the value "JSONFile" also exists
//
// Terminal Output
//
// You may also write to the terminal. By default, this uses the human
// formatter.
//
// Arguments:
//     "Stdout": if output should go to stdout instead of stderr
//
// Which:
//     term
//     terminal
//
// Testlog Output
//
// This output is for capturing the output of your application to the test log,
// so that if a test fails, you have the entire application log handy, otherwise
// it's all hidden.
//
// This is a special output in that it must be configured programmatically.
// Instead, you would configure it directly in Config itself, as follows:
//
//     Config{
//         Outputs: map[string]*ConfigOutput{
//             "testlog": {
//                 Which: "testlog",
//                 Args: ConfigOutputArgs{
//                     "log": t, // a *testing.T
//                 },
//             },
//         },
//     }
//
// In the above example, you pass a *testing.T as the argument; really, it will
// accept anything with a `Log(...interface{})` method. All log output will be
// directed to this function as a single string.
//
// Which:
//     TestLog
//
// Human-readable Format
//
// Arguments:
//     "ShortTime": if true, timestamps in entries are printed as time since start
package clog
<|endoftext|>


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

package cmd

import (
	"fmt"
	"log"
	"os"
	"path"
	"time"

	"github.com/Unknwon/cae/zip"
	"github.com/codegangsta/cli"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/setting"
)

var CmdDump = cli.Command{
	Name:  "dump",
	Usage: "Dump Gogs files and database",
	Description: `Dump compresses all related files and database into zip file.
It can be used for backup and capture Gogs server image to send to maintainer`,
	Action: runDump,
	Flags: []cli.Flag{
		stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
		boolFlag("verbose, v", "show process details"),
	},
}

func runDump(ctx *cli.Context) {
	if ctx.IsSet("config") {
		setting.CustomConf = ctx.String("config")
	}
	setting.NewContext()
	models.LoadConfigs()
	models.SetEngine()

	log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
	zip.Verbose = ctx.Bool("verbose")
	defer os.Remove("gogs-repo.zip")
	if err := zip.PackTo(setting.RepoRootPath, "gogs-repo.zip", true); err != nil {
		log.Fatalf("Fail to dump local repositories: %v", err)
	}

	log.Printf("Dumping database...")
	defer os.Remove("gogs-db.sql")
	if err := models.DumpDatabase("gogs-db.sql"); err != nil {
		log.Fatalf("Fail to dump database: %v", err)
	}

	fileName := fmt.Sprintf("gogs-dump-%d.zip", time.Now().Unix())
	log.Printf("Packing dump files...")
	z, err := zip.Create(fileName)
	if err != nil {
		os.Remove(fileName)
		log.Fatalf("Fail to create %s: %v", fileName, err)
	}

	workDir, _ := setting.WorkDir()
	z.AddFile("gogs-repo.zip", path.Join(workDir, "gogs-repo.zip"))
	z.AddFile("gogs-db.sql", path.Join(workDir, "gogs-db.sql"))
	z.AddDir("custom", path.Join(workDir, "custom"))
	z.AddDir("log", path.Join(workDir, "log"))
	// FIXME: SSH key file.
	if err = z.Close(); err != nil {
		os.Remove(fileName)
		log.Fatalf("Fail to save %s: %v", fileName, err)
	}

	log.Println("Finish dumping!")
}
<commit_msg>Adding more error handling in dump cmd<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package cmd

import (
	"fmt"
	"log"
	"os"
	"path"
	"time"

	"github.com/Unknwon/cae/zip"
	"github.com/codegangsta/cli"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/setting"
)

var CmdDump = cli.Command{
	Name:  "dump",
	Usage: "Dump Gogs files and database",
	Description: `Dump compresses all related files and database into zip file.
It can be used for backup and capture Gogs server image to send to maintainer`,
	Action: runDump,
	Flags: []cli.Flag{
		stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
		boolFlag("verbose, v", "show process details"),
	},
}

func runDump(ctx *cli.Context) {
	if ctx.IsSet("config") {
		setting.CustomConf = ctx.String("config")
	}
	setting.NewContext()
	models.LoadConfigs()
	models.SetEngine()

	log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
	zip.Verbose = ctx.Bool("verbose")
	defer os.Remove("gogs-repo.zip")
	if err := zip.PackTo(setting.RepoRootPath, "gogs-repo.zip", true); err != nil {
		log.Fatalf("Fail to dump local repositories: %v", err)
	}

	log.Printf("Dumping database...")
	defer os.Remove("gogs-db.sql")
	if err := models.DumpDatabase("gogs-db.sql"); err != nil {
		log.Fatalf("Fail to dump database: %v", err)
	}

	fileName := fmt.Sprintf("gogs-dump-%d.zip", time.Now().Unix())
	log.Printf("Packing dump files...")
	z, err := zip.Create(fileName)
	if err != nil {
		os.Remove(fileName)
		log.Fatalf("Fail to create %s: %v", fileName, err)
	}

	workDir, _ := setting.WorkDir()
	if err := z.AddFile("gogs-repo.zip", path.Join(workDir, "gogs-repo.zip")); err !=nil {
		log.Fatalf("Fail to include gogs-repo.zip: %v", err)
	}
	if err := z.AddFile("gogs-db.sql", path.Join(workDir, "gogs-db.sql")); err !=nil {
		log.Fatalf("Fail to include gogs-db.sql: %v", err)
	}
	if err := z.AddDir("custom", path.Join(workDir, "custom")); err !=nil {
		log.Fatalf("Fail to include custom: %v", err)
	}
	if err := z.AddDir("log", path.Join(workDir, "log")); err !=nil {
		log.Fatalf("Fail to include log: %v", err)
	}
	// FIXME: SSH key file.
	if err = z.Close(); err != nil {
		os.Remove(fileName)
		log.Fatalf("Fail to save %s: %v", fileName, err)
	}

	log.Println("Finish dumping!")
}
<|endoftext|>


<commit_before>package streams

import (
	"fmt"
	"sync"
	"time"

	"github.com/FederationOfFathers/dashboard/db"
	"github.com/uber-go/zap"
)

var Streams = []*db.Stream{}
var lock sync.Mutex
var logger = zap.New(zap.NewJSONEncoder()).With(zap.String("module", "streams"))
var channel string

var DB *db.DB

func Init(notifySlackChannel string) error {
	channel = notifySlackChannel
	updated()
	return nil
}

func updated() {
	if s, err := DB.Streams(); err != nil {
		logger.Error("Error updating streams", zap.Error(err))
	} else {
		Streams = s
	}
}

func Mind() {
	go mind()
}

func mind() {
	mindYoutube()
	mindTwitch()
	uptimer := time.Tick(5 * time.Minute)
	twtimer := time.Tick(5 * time.Minute)
	yttimer := time.Tick(5 * time.Minute)
	for {
		select {
		case <-uptimer:
			updated()
		case <-twtimer:
			mindTwitch()
		case <-yttimer:
			mindYoutube()
		}
	}
}

func Owner(s *db.Stream) (*db.Member, error) {
	return DB.MemberByID(s.MemberID)
}

func Add(kind, identifier, userID string) error {
	member, err := DB.MemberBySlackID(userID)
	if err != nil {
		return err
	}
	switch kind {
	case "twitch":
		err := DB.Exec(
			"INSERT INTO `streams` (`member_id`,`twitch`) VALUES (?,?) ON DUPLICATE KEY UPDATE `twitch`=?",
			member.ID,
			identifier,
			identifier,
		).Error
		updated()
		return err
	case "youtube":
		err := DB.Exec(
			"INSERT INTO `streams` (`member_id`,`youtube`) VALUES (?,?) ON DUPLICATE KEY UPDATE `youtube`=?",
			member.ID,
			identifier,
			identifier,
		).Error
		updated()
		return err
	}
	return fmt.Errorf("unknown kind!")
}

func Remove(memberID int, kind string) error {
	switch kind {
	case "twitch":
		err := DB.Exec("UPDATE `streams` SET `twitch` = '' WHERE `id` = ?", memberID).Error
		updated()
		return err
	case "youtube":
		err := DB.Exec("UPDATE `streams` SET `youtube` = '' WHERE `id` = ?", memberID).Error
		updated()
		return err
	}
	return fmt.Errorf("unknown kind!")
}
<commit_msg>1 minute timers<commit_after>package streams

import (
	"fmt"
	"sync"
	"time"

	"github.com/FederationOfFathers/dashboard/db"
	"github.com/uber-go/zap"
)

var Streams = []*db.Stream{}
var lock sync.Mutex
var logger = zap.New(zap.NewJSONEncoder()).With(zap.String("module", "streams"))
var channel string

var DB *db.DB

func Init(notifySlackChannel string) error {
	channel = notifySlackChannel
	updated()
	return nil
}

func updated() {
	if s, err := DB.Streams(); err != nil {
		logger.Error("Error updating streams", zap.Error(err))
	} else {
		Streams = s
	}
}

func Mind() {
	go mind()
}

func mind() {
	mindYoutube()
	mindTwitch()
	uptimer := time.Tick(1 * time.Minute)
	twtimer := time.Tick(1 * time.Minute)
	yttimer := time.Tick(1 * time.Minute)
	for {
		select {
		case <-uptimer:
			updated()
		case <-twtimer:
			mindTwitch()
		case <-yttimer:
			mindYoutube()
		}
	}
}

func Owner(s *db.Stream) (*db.Member, error) {
	return DB.MemberByID(s.MemberID)
}

func Add(kind, identifier, userID string) error {
	member, err := DB.MemberBySlackID(userID)
	if err != nil {
		return err
	}
	switch kind {
	case "twitch":
		err := DB.Exec(
			"INSERT INTO `streams` (`member_id`,`twitch`) VALUES (?,?) ON DUPLICATE KEY UPDATE `twitch`=?",
			member.ID,
			identifier,
			identifier,
		).Error
		updated()
		return err
	case "youtube":
		err := DB.Exec(
			"INSERT INTO `streams` (`member_id`,`youtube`) VALUES (?,?) ON DUPLICATE KEY UPDATE `youtube`=?",
			member.ID,
			identifier,
			identifier,
		).Error
		updated()
		return err
	}
	return fmt.Errorf("unknown kind!")
}

func Remove(memberID int, kind string) error {
	switch kind {
	case "twitch":
		err := DB.Exec("UPDATE `streams` SET `twitch` = '' WHERE `id` = ?", memberID).Error
		updated()
		return err
	case "youtube":
		err := DB.Exec("UPDATE `streams` SET `youtube` = '' WHERE `id` = ?", memberID).Error
		updated()
		return err
	}
	return fmt.Errorf("unknown kind!")
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"time"

	"github.com/rebuy-de/aws-nuke/pkg/awsutil"
	"github.com/rebuy-de/aws-nuke/pkg/config"
	"github.com/rebuy-de/aws-nuke/pkg/types"
	"github.com/rebuy-de/aws-nuke/resources"
	"github.com/sirupsen/logrus"
)

type Nuke struct {
	Parameters NukeParameters
	Account    awsutil.Account
	Config     *config.Nuke

	ResourceTypes types.Collection

	items Queue
}

func NewNuke(params NukeParameters, account awsutil.Account) *Nuke {
	n := Nuke{
		Parameters: params,
		Account:    account,
	}

	return &n
}

func (n *Nuke) Run() error {
	var err error

	if n.Parameters.ForceSleep < 3 {
		return fmt.Errorf("Value for --force-sleep cannot be less than 3 seconds. This is for your own protection.")
	}
	forceSleep := time.Duration(n.Parameters.ForceSleep) * time.Second

	fmt.Printf("aws-nuke version %s - %s - %s\n\n", BuildVersion, BuildDate, BuildHash)

	err = n.Config.ValidateAccount(n.Account.ID(), n.Account.Aliases())
	if err != nil {
		return err
	}

	fmt.Printf("Do you really want to nuke the account with "+
		"the ID %s and the alias '%s'?\n", n.Account.ID(), n.Account.Alias())
	if n.Parameters.Force {
		fmt.Printf("Waiting %v before continuing.\n", forceSleep)
		time.Sleep(forceSleep)
	} else {
		fmt.Printf("Do you want to continue? Enter account alias to continue.\n")
		err = Prompt(n.Account.Alias())
		if err != nil {
			return err
		}
	}

	err = n.Scan()
	if err != nil {
		return err
	}

	if n.items.Count(ItemStateNew) == 0 {
		fmt.Println("No resource to delete.")
		return nil
	}

	if !n.Parameters.NoDryRun {
		fmt.Println("The above resources would be deleted with the supplied configuration. Provide --no-dry-run to actually destroy resources.")
		return nil
	}

	fmt.Printf("Do you really want to nuke these resources on the account with "+
		"the ID %s and the alias '%s'?\n", n.Account.ID(), n.Account.Alias())
	if n.Parameters.Force {
		fmt.Printf("Waiting %v before continuing.\n", forceSleep)
		time.Sleep(forceSleep)
	} else {
		fmt.Printf("Do you want to continue? Enter account alias to continue.\n")
		err = Prompt(n.Account.Alias())
		if err != nil {
			return err
		}
	}

	failCount := 0
	waitingCount := 0

	for {
		n.HandleQueue()

		if n.items.Count(ItemStatePending, ItemStateWaiting, ItemStateNew) == 0 && n.items.Count(ItemStateFailed) > 0 {
			if failCount >= 2 {
				logrus.Errorf("There are resources in failed state, but none are ready for deletion, anymore.")
				fmt.Println()

				for _, item := range n.items {
					if item.State != ItemStateFailed {
						continue
					}

					item.Print()
					logrus.Error(item.Reason)
				}

				return fmt.Errorf("failed")
			}

			failCount = failCount + 1
		} else {
			failCount = 0
		}
		if n.Parameters.MaxWaitRetries != 0 && n.items.Count(ItemStateWaiting, ItemStatePending) > 0 && n.items.Count(ItemStateNew) == 0 {
			if waitingCount >= n.Parameters.MaxWaitRetries {
				fmt.Printf("Max wait retries of %d exceeded.\n\n", n.Parameters.MaxWaitRetries)

				break
			}
			waitingCount = waitingCount + 1
		} else {
			waitingCount = 0
		}
		if n.items.Count(ItemStateNew, ItemStatePending, ItemStateFailed, ItemStateWaiting) == 0 {
			break
		}

		time.Sleep(5 * time.Second)
	}

	fmt.Printf("Nuke complete: %d failed, %d skipped, %d finished.\n\n",
		n.items.Count(ItemStateFailed), n.items.Count(ItemStateFiltered), n.items.Count(ItemStateFinished))

	return nil
}

func (n *Nuke) Scan() error {
	accountConfig := n.Config.Accounts[n.Account.ID()]

	resourceTypes := ResolveResourceTypes(
		resources.GetListerNames(),
		[]types.Collection{
			n.Parameters.Targets,
			n.Config.ResourceTypes.Targets,
			accountConfig.ResourceTypes.Targets,
		},
		[]types.Collection{
			n.Parameters.Excludes,
			n.Config.ResourceTypes.Excludes,
			accountConfig.ResourceTypes.Excludes,
		},
	)

	queue := make(Queue, 0)

	for _, regionName := range n.Config.Regions {
		sess, err := n.Account.NewSession(regionName)
		if err != nil {
			return err
		}

		region := Region{
			Name:    regionName,
			Session: sess,
		}

		items := Scan(region, resourceTypes)
		for item := range items {
			queue = append(queue, item)
			err := n.Filter(item)
			if err != nil {
				return err
			}

			item.Print()
		}
	}

	fmt.Printf("Scan complete: %d total, %d nukeable, %d filtered.\n\n",
		queue.CountTotal(), queue.Count(ItemStateNew), queue.Count(ItemStateFiltered))

	n.items = queue

	return nil
}

func (n *Nuke) Filter(item *Item) error {

	checker, ok := item.Resource.(resources.Filter)
	if ok {
		err := checker.Filter()
		if err != nil {
			item.State = ItemStateFiltered
			item.Reason = err.Error()

			// Not returning the error, since it could be because of a failed
			// request to the API. We do not want to block the whole nuking,
			// because of an issue on AWS side.
			return nil
		}
	}

	accountFilters, err := n.Config.Filters(n.Account.ID())
	if err != nil {
		return err
	}

	itemFilters, ok := accountFilters[item.Type]
	if !ok {
		return nil
	}

	for _, filter := range itemFilters {
		prop, err := item.GetProperty(filter.Property)

		match, err := filter.Match(prop)
		if err != nil {
			return err
		}

		if IsTrue(filter.Invert) {
			match = !match
		}

		if match {
			item.State = ItemStateFiltered
			item.Reason = "filtered by config"
			return nil
		}
	}

	return nil
}

func (n *Nuke) HandleQueue() {
	listCache := make(map[string][]resources.Resource)

	for _, item := range n.items {
		switch item.State {
		case ItemStateNew:
			n.HandleRemove(item)
			item.Print()
		case ItemStateFailed:
			n.HandleRemove(item)
			n.HandleWait(item, listCache)
			item.Print()
		case ItemStatePending:
			n.HandleWait(item, listCache)
			item.State = ItemStateWaiting
			item.Print()
		case ItemStateWaiting:
			n.HandleWait(item, listCache)
			item.Print()
		}

	}

	fmt.Println()
	fmt.Printf("Removal requested: %d waiting, %d failed, %d skipped, %d finished\n\n",
		n.items.Count(ItemStateWaiting, ItemStatePending), n.items.Count(ItemStateFailed),
		n.items.Count(ItemStateFiltered), n.items.Count(ItemStateFinished))
}

func (n *Nuke) HandleRemove(item *Item) {
	err := item.Resource.Remove()
	if err != nil {
		item.State = ItemStateFailed
		item.Reason = err.Error()
		return
	}

	item.State = ItemStatePending
	item.Reason = ""
}

func (n *Nuke) HandleWait(item *Item, cache map[string][]resources.Resource) {
	var err error

	left, ok := cache[item.Type]
	if !ok {
		left, err = item.List()
		if err != nil {
			item.State = ItemStateFailed
			item.Reason = err.Error()
			return
		}
		cache[item.Type] = left
	}

	for _, r := range left {
		if item.Equals(r) {
			checker, ok := r.(resources.Filter)
			if ok {
				err := checker.Filter()
				if err != nil {
					break
				}
			}

			return
		}
	}

	item.State = ItemStateFinished
	item.Reason = ""
}
<commit_msg>return error when max wait threshold is reached<commit_after>package cmd

import (
	"fmt"
	"time"

	"github.com/rebuy-de/aws-nuke/pkg/awsutil"
	"github.com/rebuy-de/aws-nuke/pkg/config"
	"github.com/rebuy-de/aws-nuke/pkg/types"
	"github.com/rebuy-de/aws-nuke/resources"
	"github.com/sirupsen/logrus"
)

type Nuke struct {
	Parameters NukeParameters
	Account    awsutil.Account
	Config     *config.Nuke

	ResourceTypes types.Collection

	items Queue
}

func NewNuke(params NukeParameters, account awsutil.Account) *Nuke {
	n := Nuke{
		Parameters: params,
		Account:    account,
	}

	return &n
}

func (n *Nuke) Run() error {
	var err error

	if n.Parameters.ForceSleep < 3 {
		return fmt.Errorf("Value for --force-sleep cannot be less than 3 seconds. This is for your own protection.")
	}
	forceSleep := time.Duration(n.Parameters.ForceSleep) * time.Second

	fmt.Printf("aws-nuke version %s - %s - %s\n\n", BuildVersion, BuildDate, BuildHash)

	err = n.Config.ValidateAccount(n.Account.ID(), n.Account.Aliases())
	if err != nil {
		return err
	}

	fmt.Printf("Do you really want to nuke the account with "+
		"the ID %s and the alias '%s'?\n", n.Account.ID(), n.Account.Alias())
	if n.Parameters.Force {
		fmt.Printf("Waiting %v before continuing.\n", forceSleep)
		time.Sleep(forceSleep)
	} else {
		fmt.Printf("Do you want to continue? Enter account alias to continue.\n")
		err = Prompt(n.Account.Alias())
		if err != nil {
			return err
		}
	}

	err = n.Scan()
	if err != nil {
		return err
	}

	if n.items.Count(ItemStateNew) == 0 {
		fmt.Println("No resource to delete.")
		return nil
	}

	if !n.Parameters.NoDryRun {
		fmt.Println("The above resources would be deleted with the supplied configuration. Provide --no-dry-run to actually destroy resources.")
		return nil
	}

	fmt.Printf("Do you really want to nuke these resources on the account with "+
		"the ID %s and the alias '%s'?\n", n.Account.ID(), n.Account.Alias())
	if n.Parameters.Force {
		fmt.Printf("Waiting %v before continuing.\n", forceSleep)
		time.Sleep(forceSleep)
	} else {
		fmt.Printf("Do you want to continue? Enter account alias to continue.\n")
		err = Prompt(n.Account.Alias())
		if err != nil {
			return err
		}
	}

	failCount := 0
	waitingCount := 0

	for {
		n.HandleQueue()

		if n.items.Count(ItemStatePending, ItemStateWaiting, ItemStateNew) == 0 && n.items.Count(ItemStateFailed) > 0 {
			if failCount >= 2 {
				logrus.Errorf("There are resources in failed state, but none are ready for deletion, anymore.")
				fmt.Println()

				for _, item := range n.items {
					if item.State != ItemStateFailed {
						continue
					}

					item.Print()
					logrus.Error(item.Reason)
				}

				return fmt.Errorf("failed")
			}

			failCount = failCount + 1
		} else {
			failCount = 0
		}
		if n.Parameters.MaxWaitRetries != 0 && n.items.Count(ItemStateWaiting, ItemStatePending) > 0 && n.items.Count(ItemStateNew) == 0 {
			if waitingCount >= n.Parameters.MaxWaitRetries {
				return fmt.Errorf("Max wait retries of %d exceeded.\n\n", n.Parameters.MaxWaitRetries)
			}
			waitingCount = waitingCount + 1
		} else {
			waitingCount = 0
		}
		if n.items.Count(ItemStateNew, ItemStatePending, ItemStateFailed, ItemStateWaiting) == 0 {
			break
		}

		time.Sleep(5 * time.Second)
	}

	fmt.Printf("Nuke complete: %d failed, %d skipped, %d finished.\n\n",
		n.items.Count(ItemStateFailed), n.items.Count(ItemStateFiltered), n.items.Count(ItemStateFinished))

	return nil
}

func (n *Nuke) Scan() error {
	accountConfig := n.Config.Accounts[n.Account.ID()]

	resourceTypes := ResolveResourceTypes(
		resources.GetListerNames(),
		[]types.Collection{
			n.Parameters.Targets,
			n.Config.ResourceTypes.Targets,
			accountConfig.ResourceTypes.Targets,
		},
		[]types.Collection{
			n.Parameters.Excludes,
			n.Config.ResourceTypes.Excludes,
			accountConfig.ResourceTypes.Excludes,
		},
	)

	queue := make(Queue, 0)

	for _, regionName := range n.Config.Regions {
		sess, err := n.Account.NewSession(regionName)
		if err != nil {
			return err
		}

		region := Region{
			Name:    regionName,
			Session: sess,
		}

		items := Scan(region, resourceTypes)
		for item := range items {
			queue = append(queue, item)
			err := n.Filter(item)
			if err != nil {
				return err
			}

			item.Print()
		}
	}

	fmt.Printf("Scan complete: %d total, %d nukeable, %d filtered.\n\n",
		queue.CountTotal(), queue.Count(ItemStateNew), queue.Count(ItemStateFiltered))

	n.items = queue

	return nil
}

func (n *Nuke) Filter(item *Item) error {

	checker, ok := item.Resource.(resources.Filter)
	if ok {
		err := checker.Filter()
		if err != nil {
			item.State = ItemStateFiltered
			item.Reason = err.Error()

			// Not returning the error, since it could be because of a failed
			// request to the API. We do not want to block the whole nuking,
			// because of an issue on AWS side.
			return nil
		}
	}

	accountFilters, err := n.Config.Filters(n.Account.ID())
	if err != nil {
		return err
	}

	itemFilters, ok := accountFilters[item.Type]
	if !ok {
		return nil
	}

	for _, filter := range itemFilters {
		prop, err := item.GetProperty(filter.Property)

		match, err := filter.Match(prop)
		if err != nil {
			return err
		}

		if IsTrue(filter.Invert) {
			match = !match
		}

		if match {
			item.State = ItemStateFiltered
			item.Reason = "filtered by config"
			return nil
		}
	}

	return nil
}

func (n *Nuke) HandleQueue() {
	listCache := make(map[string][]resources.Resource)

	for _, item := range n.items {
		switch item.State {
		case ItemStateNew:
			n.HandleRemove(item)
			item.Print()
		case ItemStateFailed:
			n.HandleRemove(item)
			n.HandleWait(item, listCache)
			item.Print()
		case ItemStatePending:
			n.HandleWait(item, listCache)
			item.State = ItemStateWaiting
			item.Print()
		case ItemStateWaiting:
			n.HandleWait(item, listCache)
			item.Print()
		}

	}

	fmt.Println()
	fmt.Printf("Removal requested: %d waiting, %d failed, %d skipped, %d finished\n\n",
		n.items.Count(ItemStateWaiting, ItemStatePending), n.items.Count(ItemStateFailed),
		n.items.Count(ItemStateFiltered), n.items.Count(ItemStateFinished))
}

func (n *Nuke) HandleRemove(item *Item) {
	err := item.Resource.Remove()
	if err != nil {
		item.State = ItemStateFailed
		item.Reason = err.Error()
		return
	}

	item.State = ItemStatePending
	item.Reason = ""
}

func (n *Nuke) HandleWait(item *Item, cache map[string][]resources.Resource) {
	var err error

	left, ok := cache[item.Type]
	if !ok {
		left, err = item.List()
		if err != nil {
			item.State = ItemStateFailed
			item.Reason = err.Error()
			return
		}
		cache[item.Type] = left
	}

	for _, r := range left {
		if item.Equals(r) {
			checker, ok := r.(resources.Filter)
			if ok {
				err := checker.Filter()
				if err != nil {
					break
				}
			}

			return
		}
	}

	item.State = ItemStateFinished
	item.Reason = ""
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "cozy",
	Short: "cozy is the main command",
	Long: `Cozy is a platform that brings all your web services in the same private space.
With it, your web apps and your devices can share data easily, providing you
with a new experience. You can install Cozy on your own hardware where no one
profiles you.`,
}

func init() {
	cobra.OnInitialize(initConfig)
	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cozy.yaml)")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".cozy") // name of config file (without extension)
	viper.AddConfigPath("$HOME") // adding home directory as first search path
	viper.AutomaticEnv()         // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	}
}
<commit_msg>Plug Cobra with Viper<commit_after>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "cozy",
	Short: "cozy is the main command",
	Long: `Cozy is a platform that brings all your web services in the same private space.
With it, your web apps and your devices can share data easily, providing you
with a new experience. You can install Cozy on your own hardware where no one
profiles you.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		return configureViper()
	},
}

var cfgFile string

// Default config values
const (
	defaultMode = "development"
)

func init() {
	RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.cozy.yaml)")

	RootCmd.PersistentFlags().StringP("mode", "m", defaultMode, "server mode: development or production")
	viper.BindPFlag("mode", RootCmd.PersistentFlags().Lookup("mode"))
	viper.SetDefault("mode", defaultMode)
}

func configureViper() error {
	viper.SetEnvPrefix("cozy")
	viper.AutomaticEnv()

	if cfgFile != "" {
		// Read given config file and skip other paths
		viper.SetConfigFile(cfgFile)
	} else {
		viper.SetConfigName(".cozy")
		viper.AddConfigPath("/etc/cozy")
		viper.AddConfigPath("$HOME")
		viper.AddConfigPath(".")
	}

	err := viper.ReadInConfig()

	if err != nil {
		if _, ok := err.(viper.ConfigParseError); ok {
			return err
		}

		if cfgFile != "" {
			return fmt.Errorf("Unable to locate config file: %s\n", cfgFile)
		}
	}

	if viper.ConfigFileUsed() != "" {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google, Inc. All rights reserved.

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 cmd

import (
	"context"
	"errors"
	goflag "flag"
	"fmt"
	"sort"
	"strings"

	"github.com/GoogleCloudPlatform/container-diff/differs"
	pkgutil "github.com/GoogleCloudPlatform/container-diff/pkg/util"
	"github.com/GoogleCloudPlatform/container-diff/util"
	"github.com/docker/docker/client"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var json bool
var save bool
var types string

type validatefxn func(args []string) error

const (
	DaemonPrefix = "daemon://"
	RemotePrefix = "remote://"
)

var RootCmd = &cobra.Command{
	Use:   "container-diff",
	Short: "container-diff is a tool for analyzing and comparing container images",
	Long:  `container-diff is a CLI tool for analyzing and comparing container images.`,
}

func NewClient() (*client.Client, error) {
	cli, err := client.NewEnvClient()
	if err != nil {
		return nil, fmt.Errorf("Error getting docker client: %s", err)
	}
	cli.NegotiateAPIVersion(context.Background())

	return cli, nil
}

func outputResults(resultMap map[string]util.Result) {
	// Outputs diff/analysis results in alphabetical order by analyzer name
	sortedTypes := []string{}
	for analyzerType := range resultMap {
		sortedTypes = append(sortedTypes, analyzerType)
	}
	sort.Strings(sortedTypes)

	results := make([]interface{}, len(resultMap))
	for i, analyzerType := range sortedTypes {
		result := resultMap[analyzerType]
		if json {
			results[i] = result.OutputStruct()
		} else {
			err := result.OutputText(analyzerType)
			if err != nil {
				glog.Error(err)
			}
		}
	}
	if json {
		err := util.JSONify(results)
		if err != nil {
			glog.Error(err)
		}
	}
}

func validateArgs(args []string, validatefxns ...validatefxn) error {
	for _, validatefxn := range validatefxns {
		if err := validatefxn(args); err != nil {
			return err
		}
	}
	return nil
}

func checkIfValidAnalyzer(flagtypes string) error {
	if flagtypes == "" {
		return errors.New("Please provide at least one analyzer to run")
	}
	analyzers := strings.Split(flagtypes, ",")
	for _, name := range analyzers {
		if _, exists := differs.Analyzers[name]; !exists {
			return fmt.Errorf("Argument %s is not a valid analyzer", name)
		}
	}
	return nil
}

func getPrepperForImage(image string) (pkgutil.Prepper, error) {
	cli, err := client.NewEnvClient()
	if err != nil {
		return nil, err
	}
	if pkgutil.IsTar(image) {
		return pkgutil.TarPrepper{
			Source: image,
			Client: cli,
		}, nil

	} else if strings.HasPrefix(image, DaemonPrefix) {
		return pkgutil.DaemonPrepper{
			Source: strings.Replace(image, DaemonPrefix, "", -1),
			Client: cli,
		}, nil
	}
	// either has remote prefix or has no prefix, in which case we force remote
	return pkgutil.CloudPrepper{
		Source: strings.Replace(image, RemotePrefix, "", -1),
		Client: cli,
	}, nil
}

func init() {
	pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
}

func addSharedFlags(cmd *cobra.Command) {
	cmd.Flags().BoolVarP(&json, "json", "j", false, "JSON Output defines if the diff should be returned in a human readable format (false) or a JSON (true).")
	cmd.Flags().StringVarP(&types, "types", "t", "apt", "This flag sets the list of analyzer types to use.  It expects a comma separated list of supported analyzers.")
	cmd.Flags().BoolVarP(&save, "save", "s", false, "Set this flag to save rather than remove the final image filesystems on exit.")
	cmd.Flags().BoolVarP(&util.SortSize, "order", "o", false, "Set this flag to sort any file/package results by descending size. Otherwise, they will be sorted by name.")
}
<commit_msg>update help string with prefix info<commit_after>/*
Copyright 2017 Google, Inc. All rights reserved.

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 cmd

import (
	"context"
	"errors"
	goflag "flag"
	"fmt"
	"sort"
	"strings"

	"github.com/GoogleCloudPlatform/container-diff/differs"
	pkgutil "github.com/GoogleCloudPlatform/container-diff/pkg/util"
	"github.com/GoogleCloudPlatform/container-diff/util"
	"github.com/docker/docker/client"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var json bool
var save bool
var types string

type validatefxn func(args []string) error

const (
	DaemonPrefix = "daemon://"
	RemotePrefix = "remote://"
)

var RootCmd = &cobra.Command{
	Use:   "container-diff",
	Short: "container-diff is a tool for analyzing and comparing container images",
	Long: `container-diff is a CLI tool for analyzing and comparing container images.

Images can be specified from either a local Docker daemon, or from a remote registry.
To specify a local image, prefix the image ID with 'daemon://', e.g. 'daemon://gcr.io/foo/bar'.
To specify a remote image, prefix the image ID with 'remote://', e.g. 'remote://gcr.io/foo/bar'.
If no prefix is specified, the local daemon will be checked first.

Tarballs can also be specified by simply providing the path to the .tar, .tar.gz, or .tgz file.`,
}

func NewClient() (*client.Client, error) {
	cli, err := client.NewEnvClient()
	if err != nil {
		return nil, fmt.Errorf("Error getting docker client: %s", err)
	}
	cli.NegotiateAPIVersion(context.Background())

	return cli, nil
}

func outputResults(resultMap map[string]util.Result) {
	// Outputs diff/analysis results in alphabetical order by analyzer name
	sortedTypes := []string{}
	for analyzerType := range resultMap {
		sortedTypes = append(sortedTypes, analyzerType)
	}
	sort.Strings(sortedTypes)

	results := make([]interface{}, len(resultMap))
	for i, analyzerType := range sortedTypes {
		result := resultMap[analyzerType]
		if json {
			results[i] = result.OutputStruct()
		} else {
			err := result.OutputText(analyzerType)
			if err != nil {
				glog.Error(err)
			}
		}
	}
	if json {
		err := util.JSONify(results)
		if err != nil {
			glog.Error(err)
		}
	}
}

func validateArgs(args []string, validatefxns ...validatefxn) error {
	for _, validatefxn := range validatefxns {
		if err := validatefxn(args); err != nil {
			return err
		}
	}
	return nil
}

func checkIfValidAnalyzer(flagtypes string) error {
	if flagtypes == "" {
		return errors.New("Please provide at least one analyzer to run")
	}
	analyzers := strings.Split(flagtypes, ",")
	for _, name := range analyzers {
		if _, exists := differs.Analyzers[name]; !exists {
			return fmt.Errorf("Argument %s is not a valid analyzer", name)
		}
	}
	return nil
}

func getPrepperForImage(image string) (pkgutil.Prepper, error) {
	cli, err := client.NewEnvClient()
	if err != nil {
		return nil, err
	}
	if pkgutil.IsTar(image) {
		return pkgutil.TarPrepper{
			Source: image,
			Client: cli,
		}, nil

	} else if strings.HasPrefix(image, DaemonPrefix) {
		return pkgutil.DaemonPrepper{
			Source: strings.Replace(image, DaemonPrefix, "", -1),
			Client: cli,
		}, nil
	}
	// either has remote prefix or has no prefix, in which case we force remote
	return pkgutil.CloudPrepper{
		Source: strings.Replace(image, RemotePrefix, "", -1),
		Client: cli,
	}, nil
}

func init() {
	pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
}

func addSharedFlags(cmd *cobra.Command) {
	cmd.Flags().BoolVarP(&json, "json", "j", false, "JSON Output defines if the diff should be returned in a human readable format (false) or a JSON (true).")
	cmd.Flags().StringVarP(&types, "types", "t", "apt", "This flag sets the list of analyzer types to use.  It expects a comma separated list of supported analyzers.")
	cmd.Flags().BoolVarP(&save, "save", "s", false, "Set this flag to save rather than remove the final image filesystems on exit.")
	cmd.Flags().BoolVarP(&util.SortSize, "order", "o", false, "Set this flag to sort any file/package results by descending size. Otherwise, they will be sorted by name.")
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/onrik/logrus/filename"
	"github.com/sirupsen/logrus"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var rootCmd = &cobra.Command{
	Use:   "smallblog",
	Short: "Smallblog is a simple self-hosted no-db blog",
	Long:  "A simple blog engine which parses markdown files with front-matter in yaml.",
}

// Execute executes the commands
func Execute() {
	rootCmd.AddCommand(serve, validate, newCmd)
	if err := rootCmd.Execute(); err != nil {
		logrus.WithError(err).Fatal()
	}
}

func init() {
	cobra.OnInitialize(setupLogger)

	// Environment variables
	viper.SetEnvPrefix("smallblog")
	viper.AutomaticEnv()

	// Configuration file
	viper.SetConfigName("conf")
	viper.AddConfigPath(".")
	viper.AddConfigPath("/config/")
	if err := viper.ReadInConfig(); err != nil {
		logrus.Warn("No configuration file found")
	}

	// Global flags
	rootCmd.PersistentFlags().String("log.level", "info", "one of debug, info, warn, error or fatal")
	rootCmd.PersistentFlags().String("log.format", "text", "one of text or json")
	rootCmd.PersistentFlags().Bool("log.line", false, "enable filename and line in logs")

	// Blog
	rootCmd.PersistentFlags().String("blog.title", "", "your blog's title")
	rootCmd.PersistentFlags().String("blog.description", "", "your blog's description")
	rootCmd.PersistentFlags().String("blog.pages", "pages/", "directory in which articles are stored")
	rootCmd.PersistentFlags().String("blog.code.style", "monokai", "style of the code sections")

	// Flag binding
	viper.BindPFlags(rootCmd.PersistentFlags())
}

func setupLogger() {
	lvl := viper.GetString("log.level")
	l, err := logrus.ParseLevel(lvl)
	if err != nil {
		logrus.WithField("level", lvl).Warn("Invalid log level, fallback to 'info'")
	} else {
		logrus.SetLevel(l)
	}
	switch viper.GetString("log.format") {
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	default:
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	}
	if viper.GetBool("log.line") {
		logrus.AddHook(filename.NewHook())
	}
}
<commit_msg>Initialize<commit_after>package cmd

import (
	"github.com/onrik/logrus/filename"
	"github.com/sirupsen/logrus"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var rootCmd = &cobra.Command{
	Use:   "smallblog",
	Short: "Smallblog is a simple self-hosted no-db blog",
	Long:  "A simple blog engine which parses markdown files with front-matter in yaml.",
}

// Execute executes the commands
func Execute() {
	rootCmd.AddCommand(serve, validate, newCmd)
	if err := rootCmd.Execute(); err != nil {
		logrus.WithError(err).Fatal()
	}
}

func init() {
	cobra.OnInitialize(initialize)

	// Global flags
	rootCmd.PersistentFlags().String("log.level", "info", "one of debug, info, warn, error or fatal")
	rootCmd.PersistentFlags().String("log.format", "text", "one of text or json")
	rootCmd.PersistentFlags().Bool("log.line", false, "enable filename and line in logs")

	// Blog
	rootCmd.PersistentFlags().String("blog.title", "", "your blog's title")
	rootCmd.PersistentFlags().String("blog.description", "", "your blog's description")
	rootCmd.PersistentFlags().String("blog.pages", "pages/", "directory in which articles are stored")
	rootCmd.PersistentFlags().String("blog.code.style", "monokai", "style of the code sections")

	// Flag binding
	viper.BindPFlags(rootCmd.PersistentFlags())
}

func initialize() {
	// Environment variables
	viper.SetEnvPrefix("smallblog")
	viper.AutomaticEnv()

	// Configuration file
	viper.SetConfigName("conf")
	viper.AddConfigPath(".")
	viper.AddConfigPath("/config/")
	if err := viper.ReadInConfig(); err != nil {
		logrus.Warn("No configuration file found")
	}
	lvl := viper.GetString("log.level")
	l, err := logrus.ParseLevel(lvl)
	if err != nil {
		logrus.WithField("level", lvl).Warn("Invalid log level, fallback to 'info'")
	} else {
		logrus.SetLevel(l)
	}
	switch viper.GetString("log.format") {
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	default:
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	}
	if viper.GetBool("log.line") {
		logrus.AddHook(filename.NewHook())
	}
}
<|endoftext|>


<commit_before>// Copyright © 2017 Kevin Kirsche <kev.kirsche[at]gmail.com>
//
// 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 cmd

import (
	"os/user"

	"github.com/Sirupsen/logrus"
	"github.com/kkirsche/go-scp/libscp"
	"github.com/spf13/cobra"
)

var (
	addr,
	port,
	username,
	password,
	fp string
	verbose bool
)

// sendCmd represents the send command
var sendCmd = &cobra.Command{
	Use:   "send",
	Short: "Send a file from the local machine to a remote machine",
	Long:  `Use to send a file from the local host to a remote host`,
	Run: func(cmd *cobra.Command, args []string) {
		logrus.SetLevel(logrus.InfoLevel)
		if verbose {
			logrus.SetLevel(logrus.DebugLevel)
		}

		for _, arg := range args {
			libscp.SendFileWithAgent(username, arg, port)
		}
	},
}

func init() {
	RootCmd.AddCommand(sendCmd)

	u, err := user.Current()
	if err != nil {
		logrus.WithError(err).Errorln("Failed to get current user")
	}

	sendCmd.PersistentFlags().StringVarP(&port, "port", "p", "22", "The port to connect to the remote host on")
	sendCmd.PersistentFlags().StringVarP(&username, "username", "u", u.Username, "The username to connect to the remote host with")
	sendCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose mode")
}
<commit_msg>Add error check correctly<commit_after>// Copyright © 2017 Kevin Kirsche <kev.kirsche[at]gmail.com>
//
// 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 cmd

import (
	"os/user"

	"github.com/Sirupsen/logrus"
	"github.com/kkirsche/go-scp/libscp"
	"github.com/spf13/cobra"
)

var (
	addr,
	port,
	username,
	password,
	fp string
	verbose bool
)

// sendCmd represents the send command
var sendCmd = &cobra.Command{
	Use:   "send",
	Short: "Send a file from the local machine to a remote machine",
	Long:  `Use to send a file from the local host to a remote host`,
	Run: func(cmd *cobra.Command, args []string) {
		logrus.SetLevel(logrus.InfoLevel)
		if verbose {
			logrus.SetLevel(logrus.DebugLevel)
		}

		for _, arg := range args {
			fields, err := libscp.SendFileWithAgent(username, arg, port)
			if err != nil {
				logrus.WithFields(fields).WithError(err).Errorln("Failed to transfer file to the remote host")
			}
		}
	},
}

func init() {
	RootCmd.AddCommand(sendCmd)

	u, err := user.Current()
	if err != nil {
		logrus.WithError(err).Errorln("Failed to get current user")
	}

	sendCmd.PersistentFlags().StringVarP(&port, "port", "p", "22", "The port to connect to the remote host on")
	sendCmd.PersistentFlags().StringVarP(&username, "username", "u", u.Username, "The username to connect to the remote host with")
	sendCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose mode")
}
<|endoftext|>