<commit_before>// Package cmd implemnts the rclone command
//
// It is in a sub package so it's internals can be re-used elsewhere
package cmd

// FIXME only attach the remote flags when using a remote???
// would probably mean bringing all the flags in to here? Or define some flagsets in fs...

import (
	"fmt"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"time"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"github.com/ncw/rclone/fs"
)

// Globals
var (
	// Flags
	cpuProfile    = pflag.StringP("cpuprofile", "", "", "Write cpu profile to file")
	memProfile    = pflag.String("memprofile", "", "Write memory profile to file")
	statsInterval = pflag.DurationP("stats", "", time.Minute*1, "Interval to print stats (0 to disable)")
	version       bool
	logFile       = pflag.StringP("log-file", "", "", "Log everything to this file")
	retries       = pflag.IntP("retries", "", 3, "Retry operations this many times if they fail")
)

// Root is the main rclone command
var Root = &cobra.Command{
	Use:   "rclone",
	Short: "Sync files and directories to and from local and remote object stores - " + fs.Version,
	Long: `
Rclone is a command line program to sync files and directories to and
from various cloud storage systems, such as:

  * Google Drive
  * Amazon S3
  * Openstack Swift / Rackspace cloud files / Memset Memstore
  * Dropbox
  * Google Cloud Storage
  * Amazon Drive
  * Microsoft One Drive
  * Hubic
  * Backblaze B2
  * Yandex Disk
  * The local filesystem

Features

  * MD5/SHA1 hashes checked at all times for file integrity
  * Timestamps preserved on files
  * Partial syncs supported on a whole file basis
  * Copy mode to just copy new/changed files
  * Sync (one way) mode to make a directory identical
  * Check mode to check for file hash equality
  * Can sync to and from network, eg two different cloud accounts

See the home page for installation, usage, documentation, changelog
and configuration walkthroughs.

  * http://rclone.org/
`,
}

// runRoot implements the main rclone command with no subcommands
func runRoot(cmd *cobra.Command, args []string) {
	if version {
		ShowVersion()
		os.Exit(0)
	} else {
		_ = Root.Usage()
		fmt.Fprintf(os.Stderr, "Command not found.\n")
		os.Exit(1)
	}
}

func init() {
	Root.Run = runRoot
	Root.Flags().BoolVarP(&version, "version", "V", false, "Print the version number")
	cobra.OnInitialize(initConfig)
}

// ShowVersion prints the version to stdout
func ShowVersion() {
	fmt.Printf("rclone %s\n", fs.Version)
}

// newFsSrc creates a src Fs from a name
//
// This can point to a file
func newFsSrc(remote string) fs.Fs {
	fsInfo, configName, fsPath, err := fs.ParseRemote(remote)
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	f, err := fsInfo.NewFs(configName, fsPath)
	if err == fs.ErrorIsFile {
		if !fs.Config.Filter.InActive() {
			fs.Stats.Error()
			log.Fatalf("Can't limit to single files when using filters: %v", remote)
		}
		// Limit transfers to this file
		err = fs.Config.Filter.AddFile(path.Base(fsPath))
		// Set --no-traverse as only one file
		fs.Config.NoTraverse = true
	}
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	return f
}

// newFsDst creates a dst Fs from a name
//
// This must point to a directory
func newFsDst(remote string) fs.Fs {
	f, err := fs.NewFs(remote)
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	return f
}

// NewFsSrcDst creates a new src and dst fs from the arguments
func NewFsSrcDst(args []string) (fs.Fs, fs.Fs) {
	fsrc, fdst := newFsSrc(args[0]), newFsDst(args[1])
	fs.CalculateModifyWindow(fdst, fsrc)
	return fdst, fsrc
}

// NewFsSrc creates a new src fs from the arguments
func NewFsSrc(args []string) fs.Fs {
	fsrc := newFsSrc(args[0])
	fs.CalculateModifyWindow(fsrc)
	return fsrc
}

// NewFsDst creates a new dst fs from the arguments
//
// Dst fs-es can't point to single files
func NewFsDst(args []string) fs.Fs {
	fdst := newFsDst(args[0])
	fs.CalculateModifyWindow(fdst)
	return fdst
}

// Run the function with stats and retries if required
func Run(Retry bool, cmd *cobra.Command, f func() error) {
	var err error
	stopStats := startStats()
	for try := 1; try <= *retries; try++ {
		err = f()
		if !Retry || (err == nil && !fs.Stats.Errored()) {
			break
		}
		if fs.IsFatalError(err) {
			fs.Log(nil, "Fatal error received - not attempting retries")
			break
		}
		if fs.IsNoRetryError(err) {
			fs.Log(nil, "Can't retry this error - not attempting retries")
			break
		}
		if err != nil {
			fs.Log(nil, "Attempt %d/%d failed with %d errors and: %v", try, *retries, fs.Stats.GetErrors(), err)
		} else {
			fs.Log(nil, "Attempt %d/%d failed with %d errors", try, *retries, fs.Stats.GetErrors())
		}
		if try < *retries {
			fs.Stats.ResetErrors()
		}
	}
	close(stopStats)
	if err != nil {
		log.Fatalf("Failed to %s: %v", cmd.Name(), err)
	}
	if !fs.Config.Quiet || fs.Stats.Errored() || *statsInterval > 0 {
		fs.Log(nil, "%s", fs.Stats)
	}
	if fs.Config.Verbose {
		fs.Debug(nil, "Go routines at exit %d\n", runtime.NumGoroutine())
	}
	if fs.Stats.Errored() {
		os.Exit(1)
	}
}

// CheckArgs checks there are enough arguments and prints a message if not
func CheckArgs(MinArgs, MaxArgs int, cmd *cobra.Command, args []string) {
	if len(args) < MinArgs {
		_ = cmd.Usage()
		fmt.Fprintf(os.Stderr, "Command %s needs %d arguments mininum\n", cmd.Name(), MinArgs)
		os.Exit(1)
	} else if len(args) > MaxArgs {
		_ = cmd.Usage()
		fmt.Fprintf(os.Stderr, "Command %s needs %d arguments maximum\n", cmd.Name(), MaxArgs)
		os.Exit(1)
	}
}

// startStats prints the stats every statsInterval
//
// It returns a channel which should be closed to stop the stats.
func startStats() chan struct{} {
	stopStats := make(chan struct{})
	if *statsInterval > 0 {
		go func() {
			ticker := time.NewTicker(*statsInterval)
			for {
				select {
				case <-ticker.C:
					fs.Stats.Log()
				case <-stopStats:
					ticker.Stop()
					return
				}
			}
		}()
	}
	return stopStats
}

// initConfig is run by cobra after initialising the flags
func initConfig() {
	// Log file output
	if *logFile != "" {
		f, err := os.OpenFile(*logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
		if err != nil {
			log.Fatalf("Failed to open log file: %v", err)
		}
		_, err = f.Seek(0, os.SEEK_END)
		if err != nil {
			fs.ErrorLog(nil, "Failed to seek log file to end: %v", err)
		}
		log.SetOutput(f)
		fs.DebugLogger.SetOutput(f)
		redirectStderr(f)
	}

	// Load the rest of the config now we have started the logger
	fs.LoadConfig()

	// Write the args for debug purposes
	fs.Debug("rclone", "Version %q starting with parameters %q", fs.Version, os.Args)

	// Setup CPU profiling if desired
	if *cpuProfile != "" {
		fs.Log(nil, "Creating CPU profile %q\n", *cpuProfile)
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fs.Stats.Error()
			log.Fatal(err)
		}
		err = pprof.StartCPUProfile(f)
		if err != nil {
			fs.Stats.Error()
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}

	// Setup memory profiling if desired
	if *memProfile != "" {
		defer func() {
			fs.Log(nil, "Saving Memory profile %q\n", *memProfile)
			f, err := os.Create(*memProfile)
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
			err = pprof.WriteHeapProfile(f)
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
			err = f.Close()
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
		}()
	}
}
<commit_msg>Correct parameter order for copy/sync etc<commit_after>// Package cmd implemnts the rclone command
//
// It is in a sub package so it's internals can be re-used elsewhere
package cmd

// FIXME only attach the remote flags when using a remote???
// would probably mean bringing all the flags in to here? Or define some flagsets in fs...

import (
	"fmt"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"time"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"github.com/ncw/rclone/fs"
)

// Globals
var (
	// Flags
	cpuProfile    = pflag.StringP("cpuprofile", "", "", "Write cpu profile to file")
	memProfile    = pflag.String("memprofile", "", "Write memory profile to file")
	statsInterval = pflag.DurationP("stats", "", time.Minute*1, "Interval to print stats (0 to disable)")
	version       bool
	logFile       = pflag.StringP("log-file", "", "", "Log everything to this file")
	retries       = pflag.IntP("retries", "", 3, "Retry operations this many times if they fail")
)

// Root is the main rclone command
var Root = &cobra.Command{
	Use:   "rclone",
	Short: "Sync files and directories to and from local and remote object stores - " + fs.Version,
	Long: `
Rclone is a command line program to sync files and directories to and
from various cloud storage systems, such as:

  * Google Drive
  * Amazon S3
  * Openstack Swift / Rackspace cloud files / Memset Memstore
  * Dropbox
  * Google Cloud Storage
  * Amazon Drive
  * Microsoft One Drive
  * Hubic
  * Backblaze B2
  * Yandex Disk
  * The local filesystem

Features

  * MD5/SHA1 hashes checked at all times for file integrity
  * Timestamps preserved on files
  * Partial syncs supported on a whole file basis
  * Copy mode to just copy new/changed files
  * Sync (one way) mode to make a directory identical
  * Check mode to check for file hash equality
  * Can sync to and from network, eg two different cloud accounts

See the home page for installation, usage, documentation, changelog
and configuration walkthroughs.

  * http://rclone.org/
`,
}

// runRoot implements the main rclone command with no subcommands
func runRoot(cmd *cobra.Command, args []string) {
	if version {
		ShowVersion()
		os.Exit(0)
	} else {
		_ = Root.Usage()
		fmt.Fprintf(os.Stderr, "Command not found.\n")
		os.Exit(1)
	}
}

func init() {
	Root.Run = runRoot
	Root.Flags().BoolVarP(&version, "version", "V", false, "Print the version number")
	cobra.OnInitialize(initConfig)
}

// ShowVersion prints the version to stdout
func ShowVersion() {
	fmt.Printf("rclone %s\n", fs.Version)
}

// newFsSrc creates a src Fs from a name
//
// This can point to a file
func newFsSrc(remote string) fs.Fs {
	fsInfo, configName, fsPath, err := fs.ParseRemote(remote)
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	f, err := fsInfo.NewFs(configName, fsPath)
	if err == fs.ErrorIsFile {
		if !fs.Config.Filter.InActive() {
			fs.Stats.Error()
			log.Fatalf("Can't limit to single files when using filters: %v", remote)
		}
		// Limit transfers to this file
		err = fs.Config.Filter.AddFile(path.Base(fsPath))
		// Set --no-traverse as only one file
		fs.Config.NoTraverse = true
	}
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	return f
}

// newFsDst creates a dst Fs from a name
//
// This must point to a directory
func newFsDst(remote string) fs.Fs {
	f, err := fs.NewFs(remote)
	if err != nil {
		fs.Stats.Error()
		log.Fatalf("Failed to create file system for %q: %v", remote, err)
	}
	return f
}

// NewFsSrcDst creates a new src and dst fs from the arguments
func NewFsSrcDst(args []string) (fs.Fs, fs.Fs) {
	fsrc, fdst := newFsSrc(args[0]), newFsDst(args[1])
	fs.CalculateModifyWindow(fdst, fsrc)
	return fsrc, fdst
}

// NewFsSrc creates a new src fs from the arguments
func NewFsSrc(args []string) fs.Fs {
	fsrc := newFsSrc(args[0])
	fs.CalculateModifyWindow(fsrc)
	return fsrc
}

// NewFsDst creates a new dst fs from the arguments
//
// Dst fs-es can't point to single files
func NewFsDst(args []string) fs.Fs {
	fdst := newFsDst(args[0])
	fs.CalculateModifyWindow(fdst)
	return fdst
}

// Run the function with stats and retries if required
func Run(Retry bool, cmd *cobra.Command, f func() error) {
	var err error
	stopStats := startStats()
	for try := 1; try <= *retries; try++ {
		err = f()
		if !Retry || (err == nil && !fs.Stats.Errored()) {
			break
		}
		if fs.IsFatalError(err) {
			fs.Log(nil, "Fatal error received - not attempting retries")
			break
		}
		if fs.IsNoRetryError(err) {
			fs.Log(nil, "Can't retry this error - not attempting retries")
			break
		}
		if err != nil {
			fs.Log(nil, "Attempt %d/%d failed with %d errors and: %v", try, *retries, fs.Stats.GetErrors(), err)
		} else {
			fs.Log(nil, "Attempt %d/%d failed with %d errors", try, *retries, fs.Stats.GetErrors())
		}
		if try < *retries {
			fs.Stats.ResetErrors()
		}
	}
	close(stopStats)
	if err != nil {
		log.Fatalf("Failed to %s: %v", cmd.Name(), err)
	}
	if !fs.Config.Quiet || fs.Stats.Errored() || *statsInterval > 0 {
		fs.Log(nil, "%s", fs.Stats)
	}
	if fs.Config.Verbose {
		fs.Debug(nil, "Go routines at exit %d\n", runtime.NumGoroutine())
	}
	if fs.Stats.Errored() {
		os.Exit(1)
	}
}

// CheckArgs checks there are enough arguments and prints a message if not
func CheckArgs(MinArgs, MaxArgs int, cmd *cobra.Command, args []string) {
	if len(args) < MinArgs {
		_ = cmd.Usage()
		fmt.Fprintf(os.Stderr, "Command %s needs %d arguments mininum\n", cmd.Name(), MinArgs)
		os.Exit(1)
	} else if len(args) > MaxArgs {
		_ = cmd.Usage()
		fmt.Fprintf(os.Stderr, "Command %s needs %d arguments maximum\n", cmd.Name(), MaxArgs)
		os.Exit(1)
	}
}

// startStats prints the stats every statsInterval
//
// It returns a channel which should be closed to stop the stats.
func startStats() chan struct{} {
	stopStats := make(chan struct{})
	if *statsInterval > 0 {
		go func() {
			ticker := time.NewTicker(*statsInterval)
			for {
				select {
				case <-ticker.C:
					fs.Stats.Log()
				case <-stopStats:
					ticker.Stop()
					return
				}
			}
		}()
	}
	return stopStats
}

// initConfig is run by cobra after initialising the flags
func initConfig() {
	// Log file output
	if *logFile != "" {
		f, err := os.OpenFile(*logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
		if err != nil {
			log.Fatalf("Failed to open log file: %v", err)
		}
		_, err = f.Seek(0, os.SEEK_END)
		if err != nil {
			fs.ErrorLog(nil, "Failed to seek log file to end: %v", err)
		}
		log.SetOutput(f)
		fs.DebugLogger.SetOutput(f)
		redirectStderr(f)
	}

	// Load the rest of the config now we have started the logger
	fs.LoadConfig()

	// Write the args for debug purposes
	fs.Debug("rclone", "Version %q starting with parameters %q", fs.Version, os.Args)

	// Setup CPU profiling if desired
	if *cpuProfile != "" {
		fs.Log(nil, "Creating CPU profile %q\n", *cpuProfile)
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fs.Stats.Error()
			log.Fatal(err)
		}
		err = pprof.StartCPUProfile(f)
		if err != nil {
			fs.Stats.Error()
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}

	// Setup memory profiling if desired
	if *memProfile != "" {
		defer func() {
			fs.Log(nil, "Saving Memory profile %q\n", *memProfile)
			f, err := os.Create(*memProfile)
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
			err = pprof.WriteHeapProfile(f)
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
			err = f.Close()
			if err != nil {
				fs.Stats.Error()
				log.Fatal(err)
			}
		}()
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package cmd

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/open-policy-agent/opa/format"

	"github.com/spf13/cobra"
)

var fmtParams = struct {
	overwrite bool
	list      bool
	diff      bool
}{}

var formatCommand = &cobra.Command{
	Use:   "fmt <path> [path [...]]",
	Short: "Format Rego source files",
	Long: `Format Rego source files.

The 'fmt' command takes a Rego source file and outputs a reformatted version.
The format of the output is not defined specifically; whatever this tool outputs
is considered correct format (with the exception of bugs).

If the '-w' option is supplied, the 'fmt' command with overwrite the source file
instead of printing to stdout.

If the '-d' option is supplied, the 'fmt' command will output a diff between the
original and formatted source.

If the '-l' option is suppled, the 'fmt' command will output the names of files
that would change if formatted. The '-l' option will suppress any other output
to stdout from the 'fmt' command.`,
	Run: func(cmd *cobra.Command, args []string) {
		os.Exit(opaFmt(args))
	},
}

func opaFmt(args []string) int {

	if len(args) == 0 {
		if err := formatStdin(os.Stdin, os.Stdout); err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
		return 0
	}

	for _, filename := range args {
		if err := filepath.Walk(filename, formatFile); err != nil {
			switch err := err.(type) {
			case fmtError:
				fmt.Fprintln(os.Stderr, err.msg)
				return err.code
			default:
				fmt.Fprintln(os.Stderr, err.Error())
				return 1
			}
		}
	}

	return 0
}

func formatFile(filename string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if info.IsDir() {
		return nil
	}

	if filepath.Ext(filename) != ".rego" {
		return nil
	}

	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return newError("failed to open file: %v", err)
	}

	formatted, err := format.Source(filename, contents)
	if err != nil {
		return newError("failed to parse Rego source file: %v", err)
	}

	if bytes.Equal(formatted, contents) {
		return nil
	}

	var out io.Writer = os.Stdout
	if fmtParams.list {
		fmt.Fprintln(out, filename)
		out = ioutil.Discard
	}

	if fmtParams.diff {
		stdout, stderr, err := doDiff(contents, formatted)
		if err != nil && stdout.Len() == 0 {
			fmt.Fprintln(os.Stderr, stderr.String())
			return newError("failed to diff formatting: %v", err)
		}

		fmt.Fprintln(out, stdout.String())

		// If we called diff, we shouldn't output to stdout.
		out = ioutil.Discard
	}

	if fmtParams.overwrite {
		outfile, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open file for writing: %v", err)
		}
		defer outfile.Close()
		out = outfile
	}

	_, err = out.Write(formatted)
	if err != nil {
		return newError("failed writing formatted contents: %v", err)
	}

	return nil
}

func formatStdin(r io.Reader, w io.Writer) error {

	contents, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	formatted, err := format.Source("stdin", contents)
	if err != nil {
		return err
	}

	if !bytes.Equal(formatted, contents) {
		_, err := w.Write(formatted)
		return err
	}

	return nil
}

func doDiff(old, new []byte) (stdout, stderr bytes.Buffer, err error) {
	o, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	defer os.Remove(o.Name())
	defer o.Close()

	n, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	defer os.Remove(n.Name())
	defer n.Close()

	o.Write(old)
	n.Write(new)

	cmd := exec.Command("diff", "-u", o.Name(), n.Name())
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	return stdout, stderr, cmd.Run()
}

type fmtError struct {
	msg  string
	code int
}

func (e fmtError) Error() string {
	return fmt.Sprintf("%s (%d)", e.msg, e.code)
}

func newError(msg string, a ...interface{}) fmtError {
	return fmtError{
		msg:  fmt.Sprintf(msg, a...),
		code: 2,
	}
}

func init() {
	formatCommand.Flags().BoolVarP(&fmtParams.overwrite, "write", "w", false, "overwrite the original source file")
	formatCommand.Flags().BoolVarP(&fmtParams.list, "list", "l", false, "list all files who would change when formatted")
	formatCommand.Flags().BoolVarP(&fmtParams.diff, "diff", "d", false, "only display a diff of the changes")
	RootCommand.AddCommand(formatCommand)
}
<commit_msg>make path optional<commit_after>// Copyright 2017 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package cmd

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/open-policy-agent/opa/format"

	"github.com/spf13/cobra"
)

var fmtParams = struct {
	overwrite bool
	list      bool
	diff      bool
}{}

var formatCommand = &cobra.Command{
	Use:   "fmt [path [...]]",
	Short: "Format Rego source files",
	Long: `Format Rego source files.

The 'fmt' command takes a Rego source file and outputs a reformatted version. If no file path
is provided - this tool will use stdin.
The format of the output is not defined specifically; whatever this tool outputs
is considered correct format (with the exception of bugs).

If the '-w' option is supplied, the 'fmt' command with overwrite the source file
instead of printing to stdout.

If the '-d' option is supplied, the 'fmt' command will output a diff between the
original and formatted source.

If the '-l' option is suppled, the 'fmt' command will output the names of files
that would change if formatted. The '-l' option will suppress any other output
to stdout from the 'fmt' command.`,
	Run: func(cmd *cobra.Command, args []string) {
		os.Exit(opaFmt(args))
	},
}

func opaFmt(args []string) int {

	if len(args) == 0 {
		if err := formatStdin(os.Stdin, os.Stdout); err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
		return 0
	}

	for _, filename := range args {
		if err := filepath.Walk(filename, formatFile); err != nil {
			switch err := err.(type) {
			case fmtError:
				fmt.Fprintln(os.Stderr, err.msg)
				return err.code
			default:
				fmt.Fprintln(os.Stderr, err.Error())
				return 1
			}
		}
	}

	return 0
}

func formatFile(filename string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if info.IsDir() {
		return nil
	}

	if filepath.Ext(filename) != ".rego" {
		return nil
	}

	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return newError("failed to open file: %v", err)
	}

	formatted, err := format.Source(filename, contents)
	if err != nil {
		return newError("failed to parse Rego source file: %v", err)
	}

	if bytes.Equal(formatted, contents) {
		return nil
	}

	var out io.Writer = os.Stdout
	if fmtParams.list {
		fmt.Fprintln(out, filename)
		out = ioutil.Discard
	}

	if fmtParams.diff {
		stdout, stderr, err := doDiff(contents, formatted)
		if err != nil && stdout.Len() == 0 {
			fmt.Fprintln(os.Stderr, stderr.String())
			return newError("failed to diff formatting: %v", err)
		}

		fmt.Fprintln(out, stdout.String())

		// If we called diff, we shouldn't output to stdout.
		out = ioutil.Discard
	}

	if fmtParams.overwrite {
		outfile, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open file for writing: %v", err)
		}
		defer outfile.Close()
		out = outfile
	}

	_, err = out.Write(formatted)
	if err != nil {
		return newError("failed writing formatted contents: %v", err)
	}

	return nil
}

func formatStdin(r io.Reader, w io.Writer) error {

	contents, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	formatted, err := format.Source("stdin", contents)
	if err != nil {
		return err
	}

	if !bytes.Equal(formatted, contents) {
		_, err := w.Write(formatted)
		return err
	}

	return nil
}

func doDiff(old, new []byte) (stdout, stderr bytes.Buffer, err error) {
	o, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	defer os.Remove(o.Name())
	defer o.Close()

	n, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	defer os.Remove(n.Name())
	defer n.Close()

	o.Write(old)
	n.Write(new)

	cmd := exec.Command("diff", "-u", o.Name(), n.Name())
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	return stdout, stderr, cmd.Run()
}

type fmtError struct {
	msg  string
	code int
}

func (e fmtError) Error() string {
	return fmt.Sprintf("%s (%d)", e.msg, e.code)
}

func newError(msg string, a ...interface{}) fmtError {
	return fmtError{
		msg:  fmt.Sprintf(msg, a...),
		code: 2,
	}
}

func init() {
	formatCommand.Flags().BoolVarP(&fmtParams.overwrite, "write", "w", false, "overwrite the original source file")
	formatCommand.Flags().BoolVarP(&fmtParams.list, "list", "l", false, "list all files who would change when formatted")
	formatCommand.Flags().BoolVarP(&fmtParams.diff, "diff", "d", false, "only display a diff of the changes")
	RootCommand.AddCommand(formatCommand)
}
<|endoftext|>


<commit_before>// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// 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 (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"gopkg.in/yaml.v2"

	"github.com/ezbuy/ezorm/parser"
	"github.com/spf13/cobra"
)

// genCmd represents the gen command
var genCmd = &cobra.Command{
	Use:   "gen",
	Short: "Generate orm code",
	Run: func(cmd *cobra.Command, args []string) {
		var objs map[string]map[string]interface{}
		data, _ := ioutil.ReadFile(input)
		stat, err := os.Stat(input)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		err = yaml.Unmarshal([]byte(data), &objs)

		if err != nil {
			println(err.Error())
			return
		}

		if genPackageName == "" {
			genPackageName = strings.Split(stat.Name(), ".")[0]
		}
		if genGoPackageName == "" {
			genGoPackageName = genPackageName
		}

		databases := make(map[string]*parser.Obj)

		for key, obj := range objs {
			xwMetaObj := new(parser.Obj)
			xwMetaObj.Package = genPackageName
			xwMetaObj.GoPackage = genGoPackageName
			xwMetaObj.Name = key
			err := xwMetaObj.Read(obj)
			if err != nil {
				println(err.Error())
			}

			databases[xwMetaObj.Db] = xwMetaObj
			for _, genType := range xwMetaObj.GetGenTypes() {
				fileAbsPath := output + "/gen_" + xwMetaObj.Name + "_" + genType + ".go"
				executeTpl(fileAbsPath, genType, xwMetaObj)
			}
		}

		for db, obj := range databases {
			if tpl, ok := obj.GetConfigTemplate(); ok {
				fileAbsPath := output + "/gen_" + db + "_config.go"
				executeTpl(fileAbsPath, tpl, obj)
			}
		}

		oscmd := exec.Command("gofmt", "-w", output)
		oscmd.Run()
		fmt.Println("gen called")
	},
}

func executeTpl(fileAbsPath, tplName string, xwMetaObj *parser.Obj) {
	file, err := os.OpenFile(fileAbsPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		panic(err)
	}
	xwMetaObj.TplWriter = file

	err = parser.Tpl.ExecuteTemplate(file, tplName, xwMetaObj)
	file.Close()
	if err != nil {
		panic(err)
	}
}

var input string
var output string
var genPackageName string
var genGoPackageName string

func init() {
	RootCmd.AddCommand(genCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	genCmd.PersistentFlags().StringVarP(&input, "input", "i", "", "input file")
	genCmd.PersistentFlags().StringVarP(&output, "output", "o", "", "output path")
	genCmd.PersistentFlags().StringVarP(&genPackageName, "package name", "p", "", "package name")
	genCmd.PersistentFlags().StringVar(&genGoPackageName, "goPackage", "", "go package name")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// genCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}
<commit_msg>remove log<commit_after>// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// 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 (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"gopkg.in/yaml.v2"

	"github.com/ezbuy/ezorm/parser"
	"github.com/spf13/cobra"
)

// genCmd represents the gen command
var genCmd = &cobra.Command{
	Use:   "gen",
	Short: "Generate orm code",
	Run: func(cmd *cobra.Command, args []string) {
		var objs map[string]map[string]interface{}
		data, _ := ioutil.ReadFile(input)
		stat, err := os.Stat(input)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		err = yaml.Unmarshal([]byte(data), &objs)

		if err != nil {
			println(err.Error())
			return
		}

		if genPackageName == "" {
			genPackageName = strings.Split(stat.Name(), ".")[0]
		}
		if genGoPackageName == "" {
			genGoPackageName = genPackageName
		}

		databases := make(map[string]*parser.Obj)

		for key, obj := range objs {
			xwMetaObj := new(parser.Obj)
			xwMetaObj.Package = genPackageName
			xwMetaObj.GoPackage = genGoPackageName
			xwMetaObj.Name = key
			err := xwMetaObj.Read(obj)
			if err != nil {
				println(err.Error())
			}

			databases[xwMetaObj.Db] = xwMetaObj
			for _, genType := range xwMetaObj.GetGenTypes() {
				fileAbsPath := output + "/gen_" + xwMetaObj.Name + "_" + genType + ".go"
				executeTpl(fileAbsPath, genType, xwMetaObj)
			}
		}

		for db, obj := range databases {
			if tpl, ok := obj.GetConfigTemplate(); ok {
				fileAbsPath := output + "/gen_" + db + "_config.go"
				executeTpl(fileAbsPath, tpl, obj)
			}
		}

		oscmd := exec.Command("gofmt", "-w", output)
		oscmd.Run()
	},
}

func executeTpl(fileAbsPath, tplName string, xwMetaObj *parser.Obj) {
	file, err := os.OpenFile(fileAbsPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		panic(err)
	}
	xwMetaObj.TplWriter = file

	err = parser.Tpl.ExecuteTemplate(file, tplName, xwMetaObj)
	file.Close()
	if err != nil {
		panic(err)
	}
}

var input string
var output string
var genPackageName string
var genGoPackageName string

func init() {
	RootCmd.AddCommand(genCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	genCmd.PersistentFlags().StringVarP(&input, "input", "i", "", "input file")
	genCmd.PersistentFlags().StringVarP(&output, "output", "o", "", "output path")
	genCmd.PersistentFlags().StringVarP(&genPackageName, "package name", "p", "", "package name")
	genCmd.PersistentFlags().StringVar(&genGoPackageName, "goPackage", "", "go package name")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// genCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}
<|endoftext|>


<commit_before>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	Aws "github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/aws"
	"github.com/spf13/cobra"

	"github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/flags"
)

type GetFlags struct {
	Profile   string
	Region    string
	Log       flags.CWLogIdentifyFlags
	Pattern   string
	TimeRange flags.CWLogTimeRange
	Watch     bool
}

const watchInterval = 5 // seconds

// Create FilterLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsFilterLogEventsParam() cloudwatchlogs.FilterLogEventsInput {
	input := cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &this.Log.Group,
	}
	if this.Pattern != "" {
		pattern := fmt.Sprintf("\"%s\"", this.Pattern)
		input.FilterPattern = &pattern
	}
	if this.Log.Stream != "" {
		input.LogStreamNames = []*string{&this.Log.Stream}
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Create GetLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsGetLogEventsParam() cloudwatchlogs.GetLogEventsInput {
	input := cloudwatchlogs.GetLogEventsInput{
		LogGroupName:  &this.Log.Group,
		LogStreamName: &this.Log.Stream,
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Print any events to stdout
func printEvents(any interface{}) {
	if events, ok := any.([]*cloudwatchlogs.FilteredLogEvent); ok {
		for _, event := range events {
			fmt.Print("[" + time.Unix(*event.Timestamp/1000, 0).String() + "] ")
			fmt.Print("[" + *event.LogStreamName + "] ")
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	} else if events, ok := any.([]*cloudwatchlogs.OutputLogEvent); ok {
		for _, event := range events {
			fmt.Print("[" + time.Unix(*event.Timestamp/1000, 0).String() + "] ")
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	}
}

var _getFlags = &GetFlags{}

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "Lists log events from the specified log stream.",
	Long: `Lists log events from the specified log stream. You can list all the log events or filter using a time range.

By default, this operation returns as many log events as can fit in a response  size of 1MB (up to 10,000 log events).
If the results include tokens, there are more log events available.
You can get additional log events by specifying one of the tokens in a subsequent call.`,
	Run:    getRun,
	PreRun: preRun,
}

func preRun(cmd *cobra.Command, args []string) {
	if rootFlag.profile == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Profile is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if _getFlags.Log.Group == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Group is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if rootFlag.verbose {
		fmt.Printf("Local flags: %#v\n", _getFlags)
	}
}

func getRun(cmd *cobra.Command, args []string) {
	cwlogsClient := Aws.NewCloudWatchLogsClient(rootFlag.GetCloudWatchLogsClientParams())
	var err error

	if _getFlags.Watch {
		// Initialize startTime and endTime
		var startTime int64
		if _getFlags.TimeRange.StartTimeMilliseconds() != 0 {
			startTime = _getFlags.TimeRange.StartTimeMilliseconds()
		} else {
			startTime = time.Now().Add(-1*time.Duration(1)*time.Minute).Unix() * 1000
		}
		endTime := time.Now().Unix() * 1000

	WatchStart:
		if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
			options := _getFlags.GetCloudWatchLogsFilterLogEventsParam()
			options.StartTime = &startTime
			options.EndTime = &endTime
			if rootFlag.verbose {
				fmt.Printf("FilterLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
				printEvents(out.Events)
				// Update startTime and endTime
				if l := len(out.Events); l > 0 {
					startTime = *out.Events[l-1].Timestamp
					startTime = startTime + 1
				}
			})
		} else {
			options := _getFlags.GetCloudWatchLogsGetLogEventsParam()
			options.StartTime = &startTime
			options.EndTime = &endTime
			if rootFlag.verbose {
				fmt.Printf("GetLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
				printEvents(out.Events)
				// Update startTime and endTime
				if l := len(out.Events); l > 0 {
					startTime = *out.Events[l-1].Timestamp
					startTime = startTime + 1
				}
			})
		}
		if err == nil {
			if rootFlag.verbose {
				fmt.Printf("`watch` enabled. now sleep(%d) Zzz...\n", watchInterval)
			}
			time.Sleep(watchInterval * time.Second)
			if rootFlag.verbose {
				fmt.Println("`watch` enabled. wakeup now!")
			}
			endTime = time.Now().Unix() * 1000
			goto WatchStart
		} else {
			fmt.Println(err.Error())
			os.Exit(2)
		}
	} else {
		if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
			options := _getFlags.GetCloudWatchLogsFilterLogEventsParam()
			if rootFlag.verbose {
				fmt.Printf("FilterLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
				printEvents(out.Events)
			})
		} else {
			options := _getFlags.GetCloudWatchLogsGetLogEventsParam()
			if rootFlag.verbose {
				fmt.Printf("GetLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
				printEvents(out.Events)
			})
		}
		if err != nil {
			fmt.Println(err.Error())
			os.Exit(2)
		}
	}
}

func init() {
	RootCmd.AddCommand(getCmd)

	localFlags := getCmd.Flags()
	_getFlags.Log.Load(localFlags)
	_getFlags.TimeRange.Load(localFlags)
	localFlags.StringVarP(&_getFlags.Pattern, "filter-pattern", "f", "", "The filter pattern to use. If not provided, all the events are matched.")
	localFlags.BoolVarP(&_getFlags.Watch, "watch", "w", false, "Do not stop when end of log is reached, but rather to wait for additional data to be appended to the input.")

	// There is no guarantee that _getFlags will have a value here
	// I do not know until getRun function
}
<commit_msg>Add 'no-prefix' option<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	Aws "github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/aws"
	"github.com/spf13/cobra"

	"github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/flags"
)

type GetFlags struct {
	Profile   string
	Region    string
	Log       flags.CWLogIdentifyFlags
	Pattern   string
	TimeRange flags.CWLogTimeRange
	Watch     bool
	noPrefix  bool
}

const watchInterval = 5 // seconds

// Create FilterLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsFilterLogEventsParam() cloudwatchlogs.FilterLogEventsInput {
	input := cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &this.Log.Group,
	}
	if this.Pattern != "" {
		pattern := fmt.Sprintf("\"%s\"", this.Pattern)
		input.FilterPattern = &pattern
	}
	if this.Log.Stream != "" {
		input.LogStreamNames = []*string{&this.Log.Stream}
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Create GetLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsGetLogEventsParam() cloudwatchlogs.GetLogEventsInput {
	input := cloudwatchlogs.GetLogEventsInput{
		LogGroupName:  &this.Log.Group,
		LogStreamName: &this.Log.Stream,
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Print any events to stdout
func printEvents(any interface{}, appendPrefix bool) {
	if events, ok := any.([]*cloudwatchlogs.FilteredLogEvent); ok {
		for _, event := range events {
			if appendPrefix {
				fmt.Print("[" + time.Unix(*event.Timestamp/1000, 0).String() + "] ")
				fmt.Print("[" + *event.LogStreamName + "] ")
			}
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	} else if events, ok := any.([]*cloudwatchlogs.OutputLogEvent); ok {
		for _, event := range events {
			if appendPrefix {
				fmt.Print("[" + time.Unix(*event.Timestamp/1000, 0).String() + "] ")
			}
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	}
}

var _getFlags = &GetFlags{}

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "Lists log events from the specified log stream.",
	Long: `Lists log events from the specified log stream. You can list all the log events or filter using a time range.

By default, this operation returns as many log events as can fit in a response  size of 1MB (up to 10,000 log events).
If the results include tokens, there are more log events available.
You can get additional log events by specifying one of the tokens in a subsequent call.`,
	Run:    getRun,
	PreRun: preRun,
}

func preRun(cmd *cobra.Command, args []string) {
	if rootFlag.profile == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Profile is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if _getFlags.Log.Group == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Group is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if rootFlag.verbose {
		fmt.Printf("Local flags: %#v\n", _getFlags)
	}
}

func getRun(cmd *cobra.Command, args []string) {
	cwlogsClient := Aws.NewCloudWatchLogsClient(rootFlag.GetCloudWatchLogsClientParams())
	var err error

	if _getFlags.Watch {
		// Initialize startTime and endTime
		var startTime int64
		if _getFlags.TimeRange.StartTimeMilliseconds() != 0 {
			startTime = _getFlags.TimeRange.StartTimeMilliseconds()
		} else {
			startTime = time.Now().Add(-1*time.Duration(1)*time.Minute).Unix() * 1000
		}
		endTime := time.Now().Unix() * 1000

	WatchStart:
		if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
			options := _getFlags.GetCloudWatchLogsFilterLogEventsParam()
			options.StartTime = &startTime
			options.EndTime = &endTime
			if rootFlag.verbose {
				fmt.Printf("FilterLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
				printEvents(out.Events, !_getFlags.noPrefix)
				// Update startTime and endTime
				if l := len(out.Events); l > 0 {
					startTime = *out.Events[l-1].Timestamp
					startTime = startTime + 1
				}
			})
		} else {
			options := _getFlags.GetCloudWatchLogsGetLogEventsParam()
			options.StartTime = &startTime
			options.EndTime = &endTime
			if rootFlag.verbose {
				fmt.Printf("GetLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
				printEvents(out.Events, !_getFlags.noPrefix)
				// Update startTime and endTime
				if l := len(out.Events); l > 0 {
					startTime = *out.Events[l-1].Timestamp
					startTime = startTime + 1
				}
			})
		}
		if err == nil {
			if rootFlag.verbose {
				fmt.Printf("`watch` enabled. now sleep(%d) Zzz...\n", watchInterval)
			}
			time.Sleep(watchInterval * time.Second)
			if rootFlag.verbose {
				fmt.Println("`watch` enabled. wakeup now!")
			}
			endTime = time.Now().Unix() * 1000
			goto WatchStart
		} else {
			fmt.Println(err.Error())
			os.Exit(2)
		}
	} else {
		if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
			options := _getFlags.GetCloudWatchLogsFilterLogEventsParam()
			if rootFlag.verbose {
				fmt.Printf("FilterLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
				printEvents(out.Events, !_getFlags.noPrefix)
			})
		} else {
			options := _getFlags.GetCloudWatchLogsGetLogEventsParam()
			if rootFlag.verbose {
				fmt.Printf("GetLogEvents: options=%v\n", options)
			}
			err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
				printEvents(out.Events, !_getFlags.noPrefix)
			})
		}
		if err != nil {
			fmt.Println(err.Error())
			os.Exit(2)
		}
	}
}

func init() {
	RootCmd.AddCommand(getCmd)

	localFlags := getCmd.Flags()
	_getFlags.Log.Load(localFlags)
	_getFlags.TimeRange.Load(localFlags)
	localFlags.StringVarP(&_getFlags.Pattern, "filter-pattern", "f", "", "The filter pattern to use. If not provided, all the events are matched.")
	localFlags.BoolVarP(&_getFlags.Watch, "watch", "w", false, "Do not stop when end of log is reached, but rather to wait for additional data to be appended to the input.")
	localFlags.BoolVarP(&_getFlags.noPrefix, "no-prefix", "", false, "Do not display the time and stream name in the event at the begin of the line.")

	// There is no guarantee that _getFlags will have a value here
	// I do not know until getRun function
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"

	_ "github.com/Shopify/themekit/cmd/static" // This will import the asset bundle
	"github.com/Shopify/themekit/src/cmdutil"
	"github.com/Shopify/themekit/src/colors"
	"github.com/Shopify/themekit/src/shopify"
	"github.com/Shopify/themekit/src/static"
)

var newCmd = &cobra.Command{
	Use:   "new",
	Short: "New will create theme using Shopify in the same directory where it gets called from",
	Long: `New will create a new theme on Shopify, generate a minimal template of
	all the required files that a theme needs to be functional and then setup
	your config file for working with your new theme. Note: by default the new command will generate files in
	the same directory it's called from. Use the --dir flag to specify a custom directory where the generated files
	should be placed.

  For more documentation please see http://shopify.github.io/themekit/commands/#new
  `,
	RunE: func(cmd *cobra.Command, args []string) error {
		// This is a hack to get around theme ID validation for the list operation which doesn't need it
		flags.ThemeID = "1337"
		return cmdutil.ForDefaultClient(flags, args, func(ctx *cmdutil.Ctx) error {
			return newTheme(ctx, static.Unbundle)
		})
	},
}

func newTheme(ctx *cmdutil.Ctx, generate func(ctx *cmdutil.Ctx) error) error {
	theme, err := ctx.Client.CreateNewTheme(ctx.Flags.Name)
	if err != nil {
		if err == shopify.ErrThemeNameRequired {
			return fmt.Errorf("a theme name is required, please use the --name flag to define it")
		}
		return err
	}
	ctx.Log.Printf("[%s] theme created", colors.Yellow(ctx.Env.Domain))

	ctx.Env.ThemeID = fmt.Sprintf("%v", theme.ID)
	if err := createConfig(ctx); err != nil {
		return err
	}
	ctx.Log.Printf("[%s] config created", colors.Yellow(ctx.Env.Domain))

	if err := generate(ctx); err != nil {
		return err
	}

	ctx.Log.Printf("[%s] uploading new files to shopify", colors.Yellow(ctx.Env.Domain))
	return deploy(ctx)
}
<commit_msg>Update cmd/new.go<commit_after>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"

	_ "github.com/Shopify/themekit/cmd/static" // This will import the asset bundle
	"github.com/Shopify/themekit/src/cmdutil"
	"github.com/Shopify/themekit/src/colors"
	"github.com/Shopify/themekit/src/shopify"
	"github.com/Shopify/themekit/src/static"
)

var newCmd = &cobra.Command{
	Use:   "new",
	Short: "New will generate a new blank slate theme in the same directory where it gets called from and create a new theme on Shopify with those files.",
	Long: `New will create a new theme on Shopify, generate a minimal template of
	all the required files that a theme needs to be functional and then setup
	your config file for working with your new theme. Note: by default the new command will generate files in
	the same directory it's called from. Use the --dir flag to specify a custom directory where the generated files
	should be placed.

  For more documentation please see http://shopify.github.io/themekit/commands/#new
  `,
	RunE: func(cmd *cobra.Command, args []string) error {
		// This is a hack to get around theme ID validation for the list operation which doesn't need it
		flags.ThemeID = "1337"
		return cmdutil.ForDefaultClient(flags, args, func(ctx *cmdutil.Ctx) error {
			return newTheme(ctx, static.Unbundle)
		})
	},
}

func newTheme(ctx *cmdutil.Ctx, generate func(ctx *cmdutil.Ctx) error) error {
	theme, err := ctx.Client.CreateNewTheme(ctx.Flags.Name)
	if err != nil {
		if err == shopify.ErrThemeNameRequired {
			return fmt.Errorf("a theme name is required, please use the --name flag to define it")
		}
		return err
	}
	ctx.Log.Printf("[%s] theme created", colors.Yellow(ctx.Env.Domain))

	ctx.Env.ThemeID = fmt.Sprintf("%v", theme.ID)
	if err := createConfig(ctx); err != nil {
		return err
	}
	ctx.Log.Printf("[%s] config created", colors.Yellow(ctx.Env.Domain))

	if err := generate(ctx); err != nil {
		return err
	}

	ctx.Log.Printf("[%s] uploading new files to shopify", colors.Yellow(ctx.Env.Domain))
	return deploy(ctx)
}
<|endoftext|>


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

package main

import (
	"encoding/hex"
	"github.com/braintree/manners"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/securecookie"
	"github.com/pufferpanel/pufferpanel/v2"
	"github.com/pufferpanel/pufferpanel/v2/config"
	"github.com/pufferpanel/pufferpanel/v2/database"
	"github.com/pufferpanel/pufferpanel/v2/environments"
	"github.com/pufferpanel/pufferpanel/v2/logging"
	"github.com/pufferpanel/pufferpanel/v2/models"
	"github.com/pufferpanel/pufferpanel/v2/programs"
	"github.com/pufferpanel/pufferpanel/v2/services"
	"github.com/pufferpanel/pufferpanel/v2/sftp"
	"github.com/pufferpanel/pufferpanel/v2/web"
	uuid "github.com/satori/go.uuid"
	"github.com/spf13/cobra"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
)

var runCmd = &cobra.Command{
	Use:   "run",
	Short: "Runs the panel",
	Run:   executeRun,
}

func executeRun(cmd *cobra.Command, args []string) {
	err := internalRun(cmd, args)
	if err != nil {
		logging.Error().Printf("An error occurred: %s", err.Error())
	}
}

func internalRun(cmd *cobra.Command, args []string) error {
	if err := config.LoadConfigFile(""); err != nil {
		return err
	}

	logging.Initialize()

	defer logging.Close()
	defer database.Close()

	c := make(chan error)

	signal.Ignore(syscall.SIGPIPE, syscall.SIGHUP)

	go func() {
		quit := make(chan os.Signal)
		// kill (no param) default send syscall.SIGTERM
		// kill -2 is syscall.SIGINT
		// kill -9 is syscall.SIGKILL but can"t be catch, so don't need add it
		signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
		<-quit
		log.Println("Shutting down...")
		c <- nil
	}()

	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(gin.LoggerWithWriter(logging.Debug().Writer()))
	pufferpanel.Engine = router

	if config.GetBool("panel.enable") {
		panel(c)

		if config.GetString("panel.sessionKey") == "" {
			if err := config.Set("panel.sessionKey", securecookie.GenerateRandomKey(32)); err != nil {
				return err
			}
		}

		result, err := hex.DecodeString(config.GetString("panel.sessionKey"))
		if err != nil {
			return err
		}
		sessionStore := cookie.NewStore(result)
		router.Use(sessions.Sessions("session", sessionStore))
	}

	if config.GetBool("daemon.enable") {
		daemon(c)
	}

	web.RegisterRoutes(router)

	go func() {
		l, err := net.Listen("tcp4", config.GetString("web.host"))
		if err != nil {
			c <- err
			return
		}

		logging.Info().Printf("Listening for HTTP requests on %s", l.Addr().String())
		for err = manners.Serve(l, router); err != nil && err != http.ErrServerClosed; err = manners.Serve(l, router) {
			c <- err
		}
	}()

	return <-c
}

func panel(ch chan error) {
	services.ValidateTokenLoaded()
	services.LoadEmailService()

	//if we have the web, then let's use our sftp auth instead
	sftp.SetAuthorization(&services.DatabaseSFTPAuthorization{})

	err := config.LoadConfigDatabase(database.GetConnector())
	if err != nil {
		logging.Error().Printf("Error loading config from database: %s", err.Error())
	}

	//validate local daemon is configured in this panel
	if config.GetBool("daemon.enable") {
		db, err := database.GetConnection()
		if err != nil {
			return
		}
		ns := &services.Node{DB: db}
		nodes, err := ns.GetAll()
		if err != nil {
			logging.Error().Printf("Failed to get nodes: %s", err.Error())
			return
		}
		exists := false
		for _, n := range *nodes {
			if n.IsLocal() {
				exists = true
			}
		}
		if !exists {
			logging.Info().Printf("Adding local node")
			create := &models.Node{
				Name:        "LocalNode",
				PublicHost:  "127.0.0.1",
				PrivateHost: "127.0.0.1",
				PublicPort:  8080,
				PrivatePort: 8080,
				SFTPPort:    5657,
				Secret:      strings.Replace(uuid.NewV4().String(), "-", "", -1),
			}
			nodeHost := config.GetString("web.host")
			sftpHost := config.GetString("daemon.sftp.host")
			hostParts := strings.SplitN(nodeHost, ":", 2)
			sftpParts := strings.SplitN(sftpHost, ":", 2)

			if len(hostParts) == 2 {
				port, err := strconv.Atoi(hostParts[1])
				if err == nil {
					create.PublicPort = uint(port)
					create.PrivatePort = uint(port)
				}
			}
			if len(sftpParts) == 2 {
				port, err := strconv.Atoi(sftpParts[1])
				if err == nil {
					create.SFTPPort = uint(port)
				}
			}

			err = ns.Create(create)
			if err != nil {
				logging.Error().Printf("Failed to add local node: %s", err.Error())
			}
		}
	}
}

func daemon(ch chan error) {
	sftp.Run()

	pufferpanel.InitEnvironment()
	environments.LoadModules()
	programs.Initialize()

	var err error

	if _, err = os.Stat(pufferpanel.ServerFolder); os.IsNotExist(err) {
		logging.Error().Printf("No server directory found, creating")
		err = os.MkdirAll(pufferpanel.ServerFolder, 0755)
		if err != nil && !os.IsExist(err) {
			ch <- err
			return
		}
	}

	programs.LoadFromFolder()

	programs.InitService()

	for _, element := range programs.GetAll() {
		if element.IsEnabled() {
			element.GetEnvironment().DisplayToConsole(true, "Daemon has been started\n")
			if element.IsAutoStart() {
				logging.Info().Printf("Queued server %s", element.Id())
				element.GetEnvironment().DisplayToConsole(true, "Server has been queued to start\n")
				programs.StartViaService(element)
			}
		}
	}
}
<commit_msg>Only add local node if no other nodes<commit_after>/*
 Copyright 2020 Padduck, LLC
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  	http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

package main

import (
	"encoding/hex"
	"github.com/braintree/manners"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/securecookie"
	"github.com/pufferpanel/pufferpanel/v2"
	"github.com/pufferpanel/pufferpanel/v2/config"
	"github.com/pufferpanel/pufferpanel/v2/database"
	"github.com/pufferpanel/pufferpanel/v2/environments"
	"github.com/pufferpanel/pufferpanel/v2/logging"
	"github.com/pufferpanel/pufferpanel/v2/models"
	"github.com/pufferpanel/pufferpanel/v2/programs"
	"github.com/pufferpanel/pufferpanel/v2/services"
	"github.com/pufferpanel/pufferpanel/v2/sftp"
	"github.com/pufferpanel/pufferpanel/v2/web"
	uuid "github.com/satori/go.uuid"
	"github.com/spf13/cobra"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
)

var runCmd = &cobra.Command{
	Use:   "run",
	Short: "Runs the panel",
	Run:   executeRun,
}

func executeRun(cmd *cobra.Command, args []string) {
	err := internalRun(cmd, args)
	if err != nil {
		logging.Error().Printf("An error occurred: %s", err.Error())
	}
}

func internalRun(cmd *cobra.Command, args []string) error {
	if err := config.LoadConfigFile(""); err != nil {
		return err
	}

	logging.Initialize()

	defer logging.Close()
	defer database.Close()

	c := make(chan error)

	signal.Ignore(syscall.SIGPIPE, syscall.SIGHUP)

	go func() {
		quit := make(chan os.Signal)
		// kill (no param) default send syscall.SIGTERM
		// kill -2 is syscall.SIGINT
		// kill -9 is syscall.SIGKILL but can"t be catch, so don't need add it
		signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
		<-quit
		log.Println("Shutting down...")
		c <- nil
	}()

	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(gin.LoggerWithWriter(logging.Debug().Writer()))
	pufferpanel.Engine = router

	if config.GetBool("panel.enable") {
		panel(c)

		if config.GetString("panel.sessionKey") == "" {
			if err := config.Set("panel.sessionKey", securecookie.GenerateRandomKey(32)); err != nil {
				return err
			}
		}

		result, err := hex.DecodeString(config.GetString("panel.sessionKey"))
		if err != nil {
			return err
		}
		sessionStore := cookie.NewStore(result)
		router.Use(sessions.Sessions("session", sessionStore))
	}

	if config.GetBool("daemon.enable") {
		daemon(c)
	}

	web.RegisterRoutes(router)

	go func() {
		l, err := net.Listen("tcp4", config.GetString("web.host"))
		if err != nil {
			c <- err
			return
		}

		logging.Info().Printf("Listening for HTTP requests on %s", l.Addr().String())
		for err = manners.Serve(l, router); err != nil && err != http.ErrServerClosed; err = manners.Serve(l, router) {
			c <- err
		}
	}()

	return <-c
}

func panel(ch chan error) {
	services.ValidateTokenLoaded()
	services.LoadEmailService()

	//if we have the web, then let's use our sftp auth instead
	sftp.SetAuthorization(&services.DatabaseSFTPAuthorization{})

	err := config.LoadConfigDatabase(database.GetConnector())
	if err != nil {
		logging.Error().Printf("Error loading config from database: %s", err.Error())
	}

	//validate local daemon is configured in this panel
	if config.GetBool("daemon.enable") {
		db, err := database.GetConnection()
		if err != nil {
			return
		}
		ns := &services.Node{DB: db}
		nodes, err := ns.GetAll()
		if err != nil {
			logging.Error().Printf("Failed to get nodes: %s", err.Error())
			return
		}

		if len(*nodes) == 0 {
			logging.Info().Printf("Adding local node")
			create := &models.Node{
				Name:        "LocalNode",
				PublicHost:  "127.0.0.1",
				PrivateHost: "127.0.0.1",
				PublicPort:  8080,
				PrivatePort: 8080,
				SFTPPort:    5657,
				Secret:      strings.Replace(uuid.NewV4().String(), "-", "", -1),
			}
			nodeHost := config.GetString("web.host")
			sftpHost := config.GetString("daemon.sftp.host")
			hostParts := strings.SplitN(nodeHost, ":", 2)
			sftpParts := strings.SplitN(sftpHost, ":", 2)

			if len(hostParts) == 2 {
				port, err := strconv.Atoi(hostParts[1])
				if err == nil {
					create.PublicPort = uint(port)
					create.PrivatePort = uint(port)
				}
			}
			if len(sftpParts) == 2 {
				port, err := strconv.Atoi(sftpParts[1])
				if err == nil {
					create.SFTPPort = uint(port)
				}
			}

			err = ns.Create(create)
			if err != nil {
				logging.Error().Printf("Failed to add local node: %s", err.Error())
			}
		}
	}
}

func daemon(ch chan error) {
	sftp.Run()

	pufferpanel.InitEnvironment()
	environments.LoadModules()
	programs.Initialize()

	var err error

	if _, err = os.Stat(pufferpanel.ServerFolder); os.IsNotExist(err) {
		logging.Error().Printf("No server directory found, creating")
		err = os.MkdirAll(pufferpanel.ServerFolder, 0755)
		if err != nil && !os.IsExist(err) {
			ch <- err
			return
		}
	}

	programs.LoadFromFolder()

	programs.InitService()

	for _, element := range programs.GetAll() {
		if element.IsEnabled() {
			element.GetEnvironment().DisplayToConsole(true, "Daemon has been started\n")
			if element.IsAutoStart() {
				logging.Info().Printf("Queued server %s", element.Id())
				element.GetEnvironment().DisplayToConsole(true, "Server has been queued to start\n")
				programs.StartViaService(element)
			}
		}
	}
}
<|endoftext|>


<commit_before>// A useful example app.  You can use this to debug your tokens on the command line.
// This is also a great place to look at how you might use this library.
//
// Example usage:
// The following will create and sign a token, then verify it and output the original claims.
//     echo {\"foo\":\"bar\"} | bin/jwt -key test/sample_key -alg RS256 -sign - | bin/jwt -key test/sample_key.pub -verify -
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"
	"strings"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	// Options
	flagAlg     = flag.String("alg", "", "signing algorithm identifier")
	flagKey     = flag.String("key", "", "path to key file or '-' to read from stdin")
	flagCompact = flag.Bool("compact", false, "output compact JSON")
	flagDebug   = flag.Bool("debug", false, "print out all kinds of debug data")
	flagClaims  = make(ArgList)
	flagHead    = make(ArgList)

	// Modes - exactly one of these is required
	flagSign   = flag.String("sign", "", "path to claims object to sign, '-' to read from stdin, or '+' to use only -claim args")
	flagVerify = flag.String("verify", "", "path to JWT token to verify or '-' to read from stdin")
	flagShow   = flag.String("show", "", "path to JWT file or '-' to read from stdin")
)

func main() {
	// Plug in Var flags
	flag.Var(flagClaims, "claim", "add additional claims. may be used more than once")
	flag.Var(flagHead, "header", "add additional header params. may be used more than once")

	// Usage message if you ask for -help or if you mess up inputs.
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "  One of the following flags is required: sign, verify\n")
		flag.PrintDefaults()
	}

	// Parse command line options
	flag.Parse()

	// Do the thing.  If something goes wrong, print error to stderr
	// and exit with a non-zero status code
	if err := start(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

// Figure out which thing to do and then do that
func start() error {
	if *flagSign != "" {
		return signToken()
	} else if *flagVerify != "" {
		return verifyToken()
	} else if *flagShow != "" {
		return showToken()
	} else {
		flag.Usage()
		return fmt.Errorf("None of the required flags are present.  What do you want me to do?")
	}
}

// Helper func:  Read input from specified file or stdin
func loadData(p string) ([]byte, error) {
	if p == "" {
		return nil, fmt.Errorf("No path specified")
	}

	var rdr io.Reader
	if p == "-" {
		rdr = os.Stdin
	} else if p == "+" {
		return []byte("{}"), nil
	} else {
		if f, err := os.Open(p); err == nil {
			rdr = f
			defer f.Close()
		} else {
			return nil, err
		}
	}
	return ioutil.ReadAll(rdr)
}

// Print a json object in accordance with the prophecy (or the command line options)
func printJSON(j interface{}) error {
	var out []byte
	var err error

	if *flagCompact == false {
		out, err = json.MarshalIndent(j, "", "    ")
	} else {
		out, err = json.Marshal(j)
	}

	if err == nil {
		fmt.Println(string(out))
	}

	return err
}

// Verify a token and output the claims.  This is a great example
// of how to verify and view a token.
func verifyToken() error {
	// get the token
	tokData, err := loadData(*flagVerify)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	}

	// trim possible whitespace from token
	tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
	}

	// Parse the token.  Load the key from command line option
	token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) {
		data, err := loadData(*flagKey)
		if err != nil {
			return nil, err
		}
		if isEs() {
			return jwt.ParseECPublicKeyFromPEM(data)
		} else if isRs() {
			return jwt.ParseRSAPublicKeyFromPEM(data)
		}
		return data, nil
	})

	// Print some debug data
	if *flagDebug && token != nil {
		fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header)
		fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims)
	}

	// Print an error if we can't parse for some reason
	if err != nil {
		return fmt.Errorf("Couldn't parse token: %v", err)
	}

	// Is token invalid?
	if !token.Valid {
		return fmt.Errorf("Token is invalid")
	}

	// Print the token details
	if err := printJSON(token.Claims); err != nil {
		return fmt.Errorf("Failed to output claims: %v", err)
	}

	return nil
}

// Create, sign, and output a token.  This is a great, simple example of
// how to use this library to create and sign a token.
func signToken() error {
	// get the token data from command line arguments
	tokData, err := loadData(*flagSign)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	} else if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData))
	}

	// parse the JSON of the claims
	var claims jwt.MapClaims
	if err := json.Unmarshal(tokData, &claims); err != nil {
		return fmt.Errorf("Couldn't parse claims JSON: %v", err)
	}

	// add command line claims
	if len(flagClaims) > 0 {
		for k, v := range flagClaims {
			claims[k] = v
		}
	}

	// get the key
	var key interface{}
	key, err = loadData(*flagKey)
	if err != nil {
		return fmt.Errorf("Couldn't read key: %v", err)
	}

	// get the signing alg
	alg := jwt.GetSigningMethod(*flagAlg)
	if alg == nil {
		return fmt.Errorf("Couldn't find signing method: %v", *flagAlg)
	}

	// create a new token
	token := jwt.NewWithClaims(alg, claims)

	// add command line headers
	if len(flagHead) > 0 {
		for k, v := range flagHead {
			token.Header[k] = v
		}
	}

	if isEs() {
		if k, ok := key.([]byte); !ok {
			return fmt.Errorf("Couldn't convert key data to key")
		} else {
			key, err = jwt.ParseECPrivateKeyFromPEM(k)
			if err != nil {
				return err
			}
		}
	} else if isRs() {
		if k, ok := key.([]byte); !ok {
			return fmt.Errorf("Couldn't convert key data to key")
		} else {
			key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
			if err != nil {
				return err
			}
		}
	}

	if out, err := token.SignedString(key); err == nil {
		fmt.Println(out)
	} else {
		return fmt.Errorf("Error signing token: %v", err)
	}

	return nil
}

// showToken pretty-prints the token on the command line.
func showToken() error {
	// get the token
	tokData, err := loadData(*flagShow)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	}

	// trim possible whitespace from token
	tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
	}

	token, err := jwt.Parse(string(tokData), nil)
	if token == nil {
		return fmt.Errorf("malformed token: %v", err)
	}

	// Print the token details
	fmt.Println("Header:")
	if err := printJSON(token.Header); err != nil {
		return fmt.Errorf("Failed to output header: %v", err)
	}

	fmt.Println("Claims:")
	if err := printJSON(token.Claims); err != nil {
		return fmt.Errorf("Failed to output claims: %v", err)
	}

	return nil
}

func isEs() bool {
	return strings.HasPrefix(*flagAlg, "ES")
}

func isRs() bool {
	return strings.HasPrefix(*flagAlg, "RS")
}
<commit_msg>Added support for RSA-PSS in jwt CLI<commit_after>// A useful example app.  You can use this to debug your tokens on the command line.
// This is also a great place to look at how you might use this library.
//
// Example usage:
// The following will create and sign a token, then verify it and output the original claims.
//     echo {\"foo\":\"bar\"} | bin/jwt -key test/sample_key -alg RS256 -sign - | bin/jwt -key test/sample_key.pub -verify -
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"
	"strings"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	// Options
	flagAlg     = flag.String("alg", "", "signing algorithm identifier")
	flagKey     = flag.String("key", "", "path to key file or '-' to read from stdin")
	flagCompact = flag.Bool("compact", false, "output compact JSON")
	flagDebug   = flag.Bool("debug", false, "print out all kinds of debug data")
	flagClaims  = make(ArgList)
	flagHead    = make(ArgList)

	// Modes - exactly one of these is required
	flagSign   = flag.String("sign", "", "path to claims object to sign, '-' to read from stdin, or '+' to use only -claim args")
	flagVerify = flag.String("verify", "", "path to JWT token to verify or '-' to read from stdin")
	flagShow   = flag.String("show", "", "path to JWT file or '-' to read from stdin")
)

func main() {
	// Plug in Var flags
	flag.Var(flagClaims, "claim", "add additional claims. may be used more than once")
	flag.Var(flagHead, "header", "add additional header params. may be used more than once")

	// Usage message if you ask for -help or if you mess up inputs.
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "  One of the following flags is required: sign, verify\n")
		flag.PrintDefaults()
	}

	// Parse command line options
	flag.Parse()

	// Do the thing.  If something goes wrong, print error to stderr
	// and exit with a non-zero status code
	if err := start(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

// Figure out which thing to do and then do that
func start() error {
	if *flagSign != "" {
		return signToken()
	} else if *flagVerify != "" {
		return verifyToken()
	} else if *flagShow != "" {
		return showToken()
	} else {
		flag.Usage()
		return fmt.Errorf("None of the required flags are present.  What do you want me to do?")
	}
}

// Helper func:  Read input from specified file or stdin
func loadData(p string) ([]byte, error) {
	if p == "" {
		return nil, fmt.Errorf("No path specified")
	}

	var rdr io.Reader
	if p == "-" {
		rdr = os.Stdin
	} else if p == "+" {
		return []byte("{}"), nil
	} else {
		if f, err := os.Open(p); err == nil {
			rdr = f
			defer f.Close()
		} else {
			return nil, err
		}
	}
	return ioutil.ReadAll(rdr)
}

// Print a json object in accordance with the prophecy (or the command line options)
func printJSON(j interface{}) error {
	var out []byte
	var err error

	if *flagCompact == false {
		out, err = json.MarshalIndent(j, "", "    ")
	} else {
		out, err = json.Marshal(j)
	}

	if err == nil {
		fmt.Println(string(out))
	}

	return err
}

// Verify a token and output the claims.  This is a great example
// of how to verify and view a token.
func verifyToken() error {
	// get the token
	tokData, err := loadData(*flagVerify)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	}

	// trim possible whitespace from token
	tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
	}

	// Parse the token.  Load the key from command line option
	token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) {
		data, err := loadData(*flagKey)
		if err != nil {
			return nil, err
		}
		if isEs() {
			return jwt.ParseECPublicKeyFromPEM(data)
		} else if isRs() {
			return jwt.ParseRSAPublicKeyFromPEM(data)
		}
		return data, nil
	})

	// Print some debug data
	if *flagDebug && token != nil {
		fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header)
		fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims)
	}

	// Print an error if we can't parse for some reason
	if err != nil {
		return fmt.Errorf("Couldn't parse token: %v", err)
	}

	// Is token invalid?
	if !token.Valid {
		return fmt.Errorf("Token is invalid")
	}

	// Print the token details
	if err := printJSON(token.Claims); err != nil {
		return fmt.Errorf("Failed to output claims: %v", err)
	}

	return nil
}

// Create, sign, and output a token.  This is a great, simple example of
// how to use this library to create and sign a token.
func signToken() error {
	// get the token data from command line arguments
	tokData, err := loadData(*flagSign)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	} else if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData))
	}

	// parse the JSON of the claims
	var claims jwt.MapClaims
	if err := json.Unmarshal(tokData, &claims); err != nil {
		return fmt.Errorf("Couldn't parse claims JSON: %v", err)
	}

	// add command line claims
	if len(flagClaims) > 0 {
		for k, v := range flagClaims {
			claims[k] = v
		}
	}

	// get the key
	var key interface{}
	key, err = loadData(*flagKey)
	if err != nil {
		return fmt.Errorf("Couldn't read key: %v", err)
	}

	// get the signing alg
	alg := jwt.GetSigningMethod(*flagAlg)
	if alg == nil {
		return fmt.Errorf("Couldn't find signing method: %v", *flagAlg)
	}

	// create a new token
	token := jwt.NewWithClaims(alg, claims)

	// add command line headers
	if len(flagHead) > 0 {
		for k, v := range flagHead {
			token.Header[k] = v
		}
	}

	if isEs() {
		if k, ok := key.([]byte); !ok {
			return fmt.Errorf("Couldn't convert key data to key")
		} else {
			key, err = jwt.ParseECPrivateKeyFromPEM(k)
			if err != nil {
				return err
			}
		}
	} else if isRs() {
		if k, ok := key.([]byte); !ok {
			return fmt.Errorf("Couldn't convert key data to key")
		} else {
			key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
			if err != nil {
				return err
			}
		}
	}

	if out, err := token.SignedString(key); err == nil {
		fmt.Println(out)
	} else {
		return fmt.Errorf("Error signing token: %v", err)
	}

	return nil
}

// showToken pretty-prints the token on the command line.
func showToken() error {
	// get the token
	tokData, err := loadData(*flagShow)
	if err != nil {
		return fmt.Errorf("Couldn't read token: %v", err)
	}

	// trim possible whitespace from token
	tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
	}

	token, err := jwt.Parse(string(tokData), nil)
	if token == nil {
		return fmt.Errorf("malformed token: %v", err)
	}

	// Print the token details
	fmt.Println("Header:")
	if err := printJSON(token.Header); err != nil {
		return fmt.Errorf("Failed to output header: %v", err)
	}

	fmt.Println("Claims:")
	if err := printJSON(token.Claims); err != nil {
		return fmt.Errorf("Failed to output claims: %v", err)
	}

	return nil
}

func isEs() bool {
	return strings.HasPrefix(*flagAlg, "ES")
}

func isRs() bool {
	return strings.HasPrefix(*flagAlg, "RS") || strings.HasPrefix(*flagAlg, "PS")
}
<|endoftext|>


<commit_before>package cmd

import "github.com/spf13/cobra"

func init() {
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Displays the version of mbt",
	Run: func(cmd *cobra.Command, args []string) {
		println("0.1.22")
	},
}
<commit_msg>Bump version<commit_after>package cmd

import "github.com/spf13/cobra"

func init() {
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Displays the version of mbt",
	Run: func(cmd *cobra.Command, args []string) {
		println("0.1.23")
	},
}
<|endoftext|>


<commit_before>package brightbox

import (
	"fmt"
	"log"
	"strings"

	brightbox "github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
)

func resourceBrightboxConfigMap() *schema.Resource {
	return &schema.Resource{
		Create: resourceBrightboxConfigMapCreate,
		Read:   resourceBrightboxConfigMapRead,
		Update: resourceBrightboxConfigMapUpdate,
		Delete: resourceBrightboxConfigMapDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(defaultTimeout),
			Delete: schema.DefaultTimeout(defaultTimeout),
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Description: "User editable label",
				Type:        schema.TypeString,
				Optional:    true,
			},

			"data": {
				Description: "keys/values making up the ConfigMap",
				Required:    true,
				Type:        schema.TypeMap,
				Elem: &schema.Schema{
					Type:             schema.TypeString,
					ValidateFunc:     validateJSONObject,
					DiffSuppressFunc: diffSuppressJSONObject,
					StateFunc: func(v interface{}) string {
						json, _ := structure.NormalizeJsonString(v)
						return json
					},
				},
			},
		},
	}
}

func resourceBrightboxConfigMapCreate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).APIClient

	log.Printf("[INFO] Creating Config Map")
	configMapOpts := &brightbox.ConfigMapOptions{}
	err := addUpdateableConfigMapOptions(d, configMapOpts)
	if err != nil {
		return err
	}

	log.Printf("[DEBUG] Config Map create configuration %#v", configMapOpts)
	configMap, err := client.CreateConfigMap(configMapOpts)
	if err != nil {
		return fmt.Errorf("Error creating Config Map: %s", err)
	}

	d.SetId(configMap.Id)

	return setConfigMapAttributes(d, configMap)
}

func resourceBrightboxConfigMapRead(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).APIClient

	configMap, err := client.ConfigMap(d.Id())
	if err != nil {
		if strings.HasPrefix(err.Error(), "missing_resource:") {
			log.Printf("[WARN] Config Map not found, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving Config Map details: %s", err)
	}

	return setConfigMapAttributes(d, configMap)
}

func resourceBrightboxConfigMapDelete(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).APIClient

	log.Printf("[INFO] Deleting Config Map %s", d.Id())
	err := client.DestroyConfigMap(d.Id())
	if err != nil {
		return fmt.Errorf("Error deleting Config Map (%s): %s", d.Id(), err)
	}
	return nil
}

func resourceBrightboxConfigMapUpdate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).APIClient

	configMapOpts := &brightbox.ConfigMapOptions{
		Id: d.Id(),
	}
	err := addUpdateableConfigMapOptions(d, configMapOpts)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Config Map update configuration: %#v", configMapOpts)

	configMap, err := client.UpdateConfigMap(configMapOpts)
	if err != nil {
		return fmt.Errorf("Error updating Config Map (%s): %s", configMapOpts.Id, err)
	}

	return setConfigMapAttributes(d, configMap)
}

func addUpdateableConfigMapOptions(
	d *schema.ResourceData,
	opts *brightbox.ConfigMapOptions,
) error {
	assign_string(d, &opts.Name, "name")
	assign_map(d, &opts.Data, "data")
	return nil
}

func setConfigMapAttributes(
	d *schema.ResourceData,
	configMap *brightbox.ConfigMap,
) error {
	d.Set("name", configMap.Name)
	d.Set("data", configMap.Data)
	return nil
}
<commit_msg>Ensure Config Map resource is lint clear<commit_after>package brightbox

import (
	"context"
	"fmt"
	"log"
	"strings"

	brightbox "github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
)

func resourceBrightboxConfigMap() *schema.Resource {
	return &schema.Resource{
		Description:   "Provides a Brightbox Config Map resource",
		CreateContext: resourceBrightboxConfigMapCreate,
		ReadContext:   resourceBrightboxConfigMapRead,
		UpdateContext: resourceBrightboxConfigMapUpdate,
		DeleteContext: resourceBrightboxConfigMapDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(defaultTimeout),
			Delete: schema.DefaultTimeout(defaultTimeout),
		},

		Schema: map[string]*schema.Schema{
			"data": {
				Description: "keys/values making up the ConfigMap",
				Required:    true,
				Type:        schema.TypeMap,
				Elem: &schema.Schema{
					Type:             schema.TypeString,
					ValidateFunc:     validateJSONObject,
					DiffSuppressFunc: diffSuppressJSONObject,
					StateFunc: func(v interface{}) string {
						json, _ := structure.NormalizeJsonString(v)
						return json
					},
				},
			},

			"name": {
				Description: "User editable label",
				Type:        schema.TypeString,
				Optional:    true,
			},
		},
	}
}

func resourceBrightboxConfigMapCreate(
	ctx context.Context,
	d *schema.ResourceData,
	meta interface{},
) diag.Diagnostics {
	client := meta.(*CompositeClient).APIClient

	log.Printf("[INFO] Creating Config Map")
	configMapOpts := &brightbox.ConfigMapOptions{}
	err := addUpdateableConfigMapOptions(d, configMapOpts)
	if err != nil {
		return diag.FromErr(err)
	}

	log.Printf("[DEBUG] Config Map create configuration %#v", configMapOpts)
	configMap, err := client.CreateConfigMap(configMapOpts)
	if err != nil {
		return diag.FromErr(fmt.Errorf("Error creating Config Map: %s", err))
	}

	d.SetId(configMap.Id)

	return setConfigMapAttributes(d, configMap)
}

func resourceBrightboxConfigMapRead(
	ctx context.Context,
	d *schema.ResourceData,
	meta interface{},
) diag.Diagnostics {
	client := meta.(*CompositeClient).APIClient

	configMap, err := client.ConfigMap(d.Id())
	if err != nil {
		if strings.HasPrefix(err.Error(), "missing_resource:") {
			log.Printf("[WARN] Config Map not found, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return diag.FromErr(fmt.Errorf("Error retrieving Config Map details: %s", err))
	}

	return setConfigMapAttributes(d, configMap)
}

func resourceBrightboxConfigMapDelete(
	ctx context.Context,
	d *schema.ResourceData,
	meta interface{},
) diag.Diagnostics {
	client := meta.(*CompositeClient).APIClient

	log.Printf("[INFO] Deleting Config Map %s", d.Id())
	err := client.DestroyConfigMap(d.Id())
	if err != nil {
		return diag.FromErr(fmt.Errorf("Error deleting Config Map (%s): %s", d.Id(), err))
	}
	return nil
}

func resourceBrightboxConfigMapUpdate(
	ctx context.Context,
	d *schema.ResourceData,
	meta interface{},
) diag.Diagnostics {
	client := meta.(*CompositeClient).APIClient

	configMapOpts := &brightbox.ConfigMapOptions{
		Id: d.Id(),
	}
	err := addUpdateableConfigMapOptions(d, configMapOpts)
	if err != nil {
		return diag.FromErr(err)
	}
	log.Printf("[DEBUG] Config Map update configuration: %#v", configMapOpts)

	configMap, err := client.UpdateConfigMap(configMapOpts)
	if err != nil {
		return diag.FromErr(fmt.Errorf("Error updating Config Map (%s): %s", configMapOpts.Id, err))
	}

	return setConfigMapAttributes(d, configMap)
}

func addUpdateableConfigMapOptions(
	d *schema.ResourceData,
	opts *brightbox.ConfigMapOptions,
) error {
	assign_string(d, &opts.Name, "name")
	assign_map(d, &opts.Data, "data")
	return nil
}

func setConfigMapAttributes(
	d *schema.ResourceData,
	configMap *brightbox.ConfigMap,
) diag.Diagnostics {
	var diags diag.Diagnostics
	err := d.Set("name", configMap.Name)
	if err != nil {
		diags = append(diags, diag.Errorf("unexpected: %s", err)...)
	}
	err = d.Set("data", configMap.Data)
	if err != nil {
		diags = append(diags, diag.Errorf("unexpected: %s", err)...)
	}
	return diags
}
<|endoftext|>


<commit_before>// Package app is used to accept command line arguments when starting the container.
//
// Copyright (c) 2016 VMware
// Author: Luis M. Valerio (lvaleriocasti@vmware.com)
//
// License: MIT
//
package app

import (
	"fmt"
	"log"
	"net/http"

	"github.com/vmtrain/data-manager/models"
)

// Constants used to map the queries to tables and columns found in the
// database schema
const (
	blobId = 04
)

// Backend is a struct used for storage by the API server. It has a single
// field which is an interface for the storage medium to use via db or in memory
// map as the one used for testing.
type Backend struct {
	datastore Datastore
}

// NewBackend is a constructor that returns a new instance of the Backend
// struct.
func NewBackend(ds Datastore) Backend {
	return Backend{
		datastore: ds,
	}
}

// GetServers is a function to look up data about multiple servers.
func (b Backend) GetServers() (*models.ServerList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	serverList := []models.Server{}
	for _, server := range blob.Content.Servers {
		serverList = append(serverList, server)
	}
	var servers models.ServerList = serverList

	return &servers, http.StatusOK, nil
}

// SaveServer is a function to stored the data about a server.
func (b Backend) SaveServer(server models.Server) (*models.Server, int, error) {
	// Read data from the blob service
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	blob.Content.Lock()
	blob.Content.Servers[server.UUID] = server
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return &server, http.StatusOK, nil
}

// GetReservations is a function to look up data about multiple servers.
func (b Backend) GetReservations() (*models.ReservationList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	reservationList := []models.Reservation{}
	for _, reservation := range blob.Content.Reservations {
		reservationList = append(reservationList, reservation)
	}
	var reservations models.ReservationList = reservationList

	return &reservations, http.StatusOK, nil
}

// GetReservation is a function to look up data about a single reservation.
func (b Backend) GetReservation(id string) (*models.Reservation, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	res, ok := blob.Content.Reservations[id]
	if !ok {
		return nil,
			http.StatusNotFound,
			fmt.Errorf("Reservation with uuid: %s not found", id)
	}

	return &res, http.StatusOK, nil
}

// SaveReservation is a function to stored the data about a server.
func (b Backend) SaveReservation(reservation models.Reservation) (*models.Reservation, int, error) {
	var returnReservation *models.Reservation
	// Read data from the blob service
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	// Update or create new reservation in the blob
	blob.Content.Lock()
	resFound, ok := blob.Content.Reservations[reservation.UUID]
	if ok {
		resFound.Update(reservation)
		blob.Content.Reservations[reservation.UUID] = resFound
		returnReservation = &resFound
	} else {
		blob.Content.Reservations[reservation.UUID] = reservation
		returnReservation = &reservation
	}
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return returnReservation, http.StatusOK, nil
}

// GetUsers is a function to look up data about multiple users.
func (b Backend) GetUsers() (*models.UserList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	userList := []models.User{}
	for _, user := range blob.Content.Users {
		userList = append(userList, user)
	}
	var users models.UserList = userList

	return &users, http.StatusOK, nil
}

// SaveUser is a function to stored the data about a user.
func (b Backend) SaveUser(user models.User) (*models.User, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	blob.Content.Lock()
	blob.Content.Users[user.UUID] = user
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return &user, http.StatusOK, nil
}
<commit_msg>Added lock and unlocks when accessing map information<commit_after>// Package app is used to accept command line arguments when starting the container.
//
// Copyright (c) 2016 VMware
// Author: Luis M. Valerio (lvaleriocasti@vmware.com)
//
// License: MIT
//
package app

import (
	"fmt"
	"log"
	"net/http"

	"github.com/vmtrain/data-manager/models"
)

// Constants used to map the queries to tables and columns found in the
// database schema
const (
	blobId = 04
)

// Backend is a struct used for storage by the API server. It has a single
// field which is an interface for the storage medium to use via db or in memory
// map as the one used for testing.
type Backend struct {
	datastore Datastore
}

// NewBackend is a constructor that returns a new instance of the Backend
// struct.
func NewBackend(ds Datastore) Backend {
	return Backend{
		datastore: ds,
	}
}

// GetServers is a function to look up data about multiple servers.
func (b Backend) GetServers() (*models.ServerList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	serverList := []models.Server{}
	blob.Content.Lock()
	for _, server := range blob.Content.Servers {
		serverList = append(serverList, server)
	}
	blob.Content.Unlock()
	var servers models.ServerList = serverList

	return &servers, http.StatusOK, nil
}

// SaveServer is a function to stored the data about a server.
func (b Backend) SaveServer(server models.Server) (*models.Server, int, error) {
	// Read data from the blob service
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	blob.Content.Lock()
	blob.Content.Servers[server.UUID] = server
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return &server, http.StatusOK, nil
}

// GetReservations is a function to look up data about multiple servers.
func (b Backend) GetReservations() (*models.ReservationList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	reservationList := []models.Reservation{}
	blob.Content.Lock()
	for _, reservation := range blob.Content.Reservations {
		reservationList = append(reservationList, reservation)
	}
	blob.Content.Unlock()
	var reservations models.ReservationList = reservationList

	return &reservations, http.StatusOK, nil
}

// GetReservation is a function to look up data about a single reservation.
func (b Backend) GetReservation(id string) (*models.Reservation, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}
	blob.Content.Lock()
	res, ok := blob.Content.Reservations[id]
	blob.Content.Unlock()
	if !ok {
		return nil,
			http.StatusNotFound,
			fmt.Errorf("Reservation with uuid: %s not found", id)
	}

	return &res, http.StatusOK, nil
}

// SaveReservation is a function to stored the data about a server.
func (b Backend) SaveReservation(reservation models.Reservation) (*models.Reservation, int, error) {
	var returnReservation *models.Reservation
	// Read data from the blob service
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	// Update or create new reservation in the blob
	blob.Content.Lock()
	resFound, ok := blob.Content.Reservations[reservation.UUID]
	if ok {
		resFound.Update(reservation)
		blob.Content.Reservations[reservation.UUID] = resFound
		returnReservation = &resFound
	} else {
		blob.Content.Reservations[reservation.UUID] = reservation
		returnReservation = &reservation
	}
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return returnReservation, http.StatusOK, nil
}

// GetUsers is a function to look up data about multiple users.
func (b Backend) GetUsers() (*models.UserList, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil,
			http.StatusInternalServerError,
			fmt.Errorf("Failed to read blob data from service. Caused by: %v", err)
	}

	userList := []models.User{}
	blob.Content.Lock()
	for _, user := range blob.Content.Users {
		userList = append(userList, user)
	}
	blob.Content.Unlock()
	var users models.UserList = userList

	return &users, http.StatusOK, nil
}

// SaveUser is a function to stored the data about a user.
func (b Backend) SaveUser(user models.User) (*models.User, int, error) {
	blob, err := b.datastore.Read(blobId)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	log.Printf("The blob found was %+v", blob)

	blob.Content.Lock()
	blob.Content.Users[user.UUID] = user
	blob.Content.Unlock()

	err = b.datastore.Write(blob)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}
	return &user, http.StatusOK, nil
}
<|endoftext|>