<commit_before>package cmd

import (
	"fmt"

	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
	log "github.com/sirupsen/logrus"
)

func init() {
	Register("add <container-name>", "Adds a container to your channel.", add)
}

func add(request *slacker.Request, response slacker.ResponseWriter) {
	response.Typing()

	event := getEvent(request)

	if direct, err := isDirect(event.Channel); direct {
		response.Reply(err.Error())
		return
	}

	containerName := request.Param("container-name")

	if hasUser, err := hasUserOnText(containerName); hasUser {
		response.Reply(err.Error())
		return
	}

	if hasChannel, err := hasChannelOnText(containerName); hasChannel {
		response.Reply(err.Error())
		return
	}

	container, err := model.GetContainer(event.Team, event.Channel, containerName)

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

	if container != (model.Container{}) {
		response.Reply(Messages["same-name"])
		return
	}

	err = model.Container{
		TeamID: event.Team, ChannelID: event.Channel, Name: containerName, InUseBy: "", InUseForReason: "", CreatedByUser: event.User,
	}.Add()

	if err != nil {
		log.Errorf("ADD. [%s, %s, %s] %s", event.Team, event.Channel, containerName, err)
		response.Reply(err.Error())
		return
	}

	response.Reply(fmt.Sprintf(Messages["added-to-channel"], containerName, event.Channel))
}
<commit_msg>Using one function instead of two<commit_after>package cmd

import (
	"fmt"

	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
	log "github.com/sirupsen/logrus"
)

func init() {
	Register("add <container-name>", "Adds a container to your channel.", add)
}

func add(request *slacker.Request, response slacker.ResponseWriter) {
	response.Typing()

	event := getEvent(request)

	if direct, err := isDirect(event.Channel); direct {
		response.Reply(err.Error())
		return
	}

	containerName := request.Param("container-name")

	if hasUserOrChannel, err := hasUserOrChannelOnText(containerName); hasUserOrChannel {
		response.Reply(err.Error())
		return
	}

	container, err := model.GetContainer(event.Team, event.Channel, containerName)

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

	if container != (model.Container{}) {
		response.Reply(Messages["same-name"])
		return
	}

	err = model.Container{
		TeamID: event.Team, ChannelID: event.Channel, Name: containerName, InUseBy: "", InUseForReason: "", CreatedByUser: event.User,
	}.Add()

	if err != nil {
		log.Errorf("ADD. [%s, %s, %s] %s", event.Team, event.Channel, containerName, err)
		response.Reply(err.Error())
		return
	}

	response.Reply(fmt.Sprintf(Messages["added-to-channel"], containerName, event.Channel))
}
<|endoftext|>


<commit_before>package cmd

type CmdError struct {
	Stderr string
	Err    error
}

func (ce CmdError) Error() string {
	return ce.Error() + " stderr: " + ce.Stderr
}

type CmdRunner interface {
	SetError(cmdError CmdError)
	RunCmd(name string, args ...string) (string, CmdError)
	RunInNewRunner(name string, args ...string) (string, CmdError)
	NewRunner() CmdRunner
	LastError() CmdError
	HasError() bool
}
<commit_msg>fix CmdError to return the correct error string<commit_after>package cmd

type CmdError struct {
	Stderr string
	Err    error
}

func (ce CmdError) Error() string {
	return ce.Err.Error() + " stderr: " + ce.Stderr
}

type CmdRunner interface {
	SetError(cmdError CmdError)
	RunCmd(name string, args ...string) (string, CmdError)
	RunInNewRunner(name string, args ...string) (string, CmdError)
	NewRunner() CmdRunner
	LastError() CmdError
	HasError() bool
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"syscall"

	"github.com/bfirsh/whalebrew/packages"
	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh/terminal"
)

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

var runCommand = &cobra.Command{
	Use:                "run PACKAGEPATH [ARGS ...]",
	Short:              "Run a package",
	DisableFlagParsing: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return cmd.Help()
		}

		pkg, err := packages.LoadPackageFromPath(args[0])
		if err != nil {
			return err
		}
		dockerPath, err := exec.LookPath("docker")
		if err != nil {
			return err
		}

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		dockerArgs := []string{
			dockerPath,
			"run",
			"--interactive",
			"--rm",
			"--workdir", "/workdir",
			"-v", fmt.Sprintf("%s:/workdir", cwd),
		}
		if terminal.IsTerminal(int(os.Stdin.Fd())) {
			dockerArgs = append(dockerArgs, "--tty")
		}
		for _, volume := range pkg.Volumes {
			// special case expanding home directory
			if strings.HasPrefix(volume, "~/") {
				user, err := user.Current()
				if err != nil {
					return err
				}
				volume = user.HomeDir + volume[1:]
			}
			dockerArgs = append(dockerArgs, "-v")
			dockerArgs = append(dockerArgs, volume)
		}
		for _, envvar := range pkg.Environment {
			dockerArgs = append(dockerArgs, "-e")
			dockerArgs = append(dockerArgs, envvar)
		}
		for _, portmap := range pkg.Ports {
			dockerArgs = append(dockerArgs, "-p")
			dockerArgs = append(dockerArgs, portmap)
		}
		dockerArgs = append(dockerArgs, pkg.Image)
		dockerArgs = append(dockerArgs, args[1:]...)

		return syscall.Exec(dockerPath, dockerArgs, os.Environ())
	},
}
<commit_msg>Use executing users' permissions (for files etc.)<commit_after>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"syscall"

	"github.com/bfirsh/whalebrew/packages"
	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh/terminal"
)

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

var runCommand = &cobra.Command{
	Use:                "run PACKAGEPATH [ARGS ...]",
	Short:              "Run a package",
	DisableFlagParsing: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return cmd.Help()
		}

		pkg, err := packages.LoadPackageFromPath(args[0])
		if err != nil {
			return err
		}
		dockerPath, err := exec.LookPath("docker")
		if err != nil {
			return err
		}

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		dockerArgs := []string{
			dockerPath,
			"run",
			"--interactive",
			"--rm",
			"--workdir", "/workdir",
			"-v", fmt.Sprintf("%s:/workdir", cwd),
		}
		if terminal.IsTerminal(int(os.Stdin.Fd())) {
			dockerArgs = append(dockerArgs, "--tty")
		}
		for _, volume := range pkg.Volumes {
			// special case expanding home directory
			if strings.HasPrefix(volume, "~/") {
				user, err := user.Current()
				if err != nil {
					return err
				}
				volume = user.HomeDir + volume[1:]
			}
			dockerArgs = append(dockerArgs, "-v")
			dockerArgs = append(dockerArgs, volume)
		}
		for _, envvar := range pkg.Environment {
			dockerArgs = append(dockerArgs, "-e")
			dockerArgs = append(dockerArgs, envvar)
		}
		for _, portmap := range pkg.Ports {
			dockerArgs = append(dockerArgs, "-p")
			dockerArgs = append(dockerArgs, portmap)
		}

		user, err := user.Current()
		if err != nil {
			return err
		}
		dockerArgs = append(dockerArgs, "-u")
		dockerArgs = append(dockerArgs, user.Uid + ":" + user.Gid)

		dockerArgs = append(dockerArgs, pkg.Image)
		dockerArgs = append(dockerArgs, args[1:]...)

		return syscall.Exec(dockerPath, dockerArgs, os.Environ())
	},
}
<|endoftext|>


<commit_before>package cmd

import (
	"os"
	"path"
	"time"

	"github.com/containerum/chkit/cmd/config_dir"

	kubeClientModels "git.containerum.net/ch/kube-client/pkg/model"
	"github.com/blang/semver"
	"github.com/containerum/chkit/cmd/util"
	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/client"
	"github.com/containerum/chkit/pkg/model"
	"github.com/sirupsen/logrus"
	cli "gopkg.in/urfave/cli.v2"
)

var (
	Version        = "3.0.0-alpha"
	FlagConfigFile = "config"
	FlagAPIaddr    = "apiaddr"
)

var (
	ErrFatalError chkitErrors.Err = "fatal error"
)

func Run(args []string) error {
	logrus.SetLevel(logrus.DebugLevel)
	logrus.SetFormatter(&logrus.TextFormatter{
		FullTimestamp:   true,
		TimestampFormat: time.RFC1123,
	})

	if !DEBUG {
		logFile := path.Join(confDir.ConfigDir(), util.LogFileName())
		file, err := os.OpenFile(logFile, os.O_CREATE|os.O_RDWR, os.ModePerm)
		if err != nil {
			logrus.Fatalf("error while creating log file: %v", err)
		}
		logrus.SetOutput(file)
	}
	var App = &cli.App{
		Name:    "chkit",
		Usage:   "containerum cli",
		Version: semver.MustParse(Version).String(),
		/*Before: func(ctx *cli.Context) error {
			var updater update.LatestCheckerDownloader
			currVersion := semver.MustParse(Version)
			updater = update.NewGithubLatestCheckerDownloader(ctx, "containerum", "chkit")
			version, err := updater.LatestVersion()
			if err != nil {
				return err
			}
			if currVersion.LE(version) {
				if yes, err := update.AskForUpdate(ctx, version); err != nil {
					return err
				} else if yes {
					if err := update.Update(ctx, updater, true); err != nil {
						return err
					}
				}
			}
			return nil
		},*/
		Action: runAction,
		Metadata: map[string]interface{}{
			"client":     chClient.Client{},
			"configPath": confDir.ConfigDir(),
			"config":     model.Config{},
			"tokens":     kubeClientModels.Tokens{},
			"version":    semver.MustParse(Version),
		},
		Commands: []*cli.Command{
			commandLogin,
			commandGet,
			commandUpdate,
		},
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:    "config",
				Usage:   "config file",
				Aliases: []string{"c"},
				Value:   path.Join(confDir.ConfigDir(), "config.toml"),
			},
			&cli.StringFlag{
				Name:    "api",
				Usage:   "API address",
				Value:   "",
				Hidden:  true,
				EnvVars: []string{"CONTAINERUM_API"},
			},
			&cli.BoolFlag{
				Name:   "debug-requests",
				Value:  false,
				Hidden: true,
			},
			&cli.StringFlag{
				Name:  "username",
				Usage: "your account email",
			},
			&cli.StringFlag{
				Name:  "pass",
				Usage: "password to system",
			},
			&cli.StringFlag{
				Name:    "namespace",
				Aliases: []string{"n"},
				Usage:   "namespace to use",
			},
		},
	}
	return App.Run(args)
}

func runAction(ctx *cli.Context) error {
	logrus.Debugf("loading config")
	if err := loadConfig(ctx); err != nil {
		return err
	}
	logrus.Debugf("running setup")
	err := setupConfig(ctx)
	config := util.GetConfig(ctx)
	switch {
	case err == nil:
		// pass
	case ErrInvalidUserInfo.Match(err):
		logrus.Debugf("invalid user information")
		logrus.Debugf("running login")
		user, err := login(ctx)
		if err != nil {
			return err
		}
		config.UserInfo = user
		util.SetConfig(ctx, config)
	default:
		logrus.Debugf("fatal error")
		return ErrFatalError.Wrap(err)
	}
	logrus.Debugf("client initialisation")
	if err := setupClient(ctx); err != nil {
		return err
	}
	client := util.GetClient(ctx)
	if err := util.SaveTokens(ctx, client.Tokens); err != nil {
		return chkitErrors.NewExitCoder(err)
	}
	config.DefaultNamespace, err = util.GetFirstClientNamespace(ctx)
	if err != nil {
		return err
	}
	util.SetConfig(ctx, config)
	if err := persist(ctx); err != nil {
		logrus.Fatalf("%v", err)
	}
	// re-setup client to save default namespace
	if err := setupClient(ctx); err != nil {
		return err
	}
	clientConfig := client.Config
	logrus.Infof("Hello, %q!", clientConfig.Username)
	if err := mainActivity(ctx); err != nil {
		logrus.Fatalf("error in main activity: %v", err)
	}
	return nil
}
<commit_msg>fix log file mode<commit_after>package cmd

import (
	"os"
	"path"
	"time"

	"github.com/containerum/chkit/cmd/config_dir"

	kubeClientModels "git.containerum.net/ch/kube-client/pkg/model"
	"github.com/blang/semver"
	"github.com/containerum/chkit/cmd/util"
	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/client"
	"github.com/containerum/chkit/pkg/model"
	"github.com/sirupsen/logrus"
	cli "gopkg.in/urfave/cli.v2"
)

var (
	Version        = "3.0.0-alpha"
	FlagConfigFile = "config"
	FlagAPIaddr    = "apiaddr"
)

var (
	ErrFatalError chkitErrors.Err = "fatal error"
)

func Run(args []string) error {
	logrus.SetLevel(logrus.DebugLevel)
	logrus.SetFormatter(&logrus.TextFormatter{
		FullTimestamp:   true,
		TimestampFormat: time.RFC1123,
	})

	if !DEBUG {
		logFile := path.Join(confDir.ConfigDir(), util.LogFileName())
		file, err := os.OpenFile(logFile, os.O_CREATE|os.O_APPEND, os.ModePerm)
		if err != nil {
			logrus.Fatalf("error while creating log file: %v", err)
		}
		logrus.SetOutput(file)
	}
	var App = &cli.App{
		Name:    "chkit",
		Usage:   "containerum cli",
		Version: semver.MustParse(Version).String(),
		/*Before: func(ctx *cli.Context) error {
			var updater update.LatestCheckerDownloader
			currVersion := semver.MustParse(Version)
			updater = update.NewGithubLatestCheckerDownloader(ctx, "containerum", "chkit")
			version, err := updater.LatestVersion()
			if err != nil {
				return err
			}
			if currVersion.LE(version) {
				if yes, err := update.AskForUpdate(ctx, version); err != nil {
					return err
				} else if yes {
					if err := update.Update(ctx, updater, true); err != nil {
						return err
					}
				}
			}
			return nil
		},*/
		Action: runAction,
		Metadata: map[string]interface{}{
			"client":     chClient.Client{},
			"configPath": confDir.ConfigDir(),
			"config":     model.Config{},
			"tokens":     kubeClientModels.Tokens{},
			"version":    semver.MustParse(Version),
		},
		Commands: []*cli.Command{
			commandLogin,
			commandGet,
			commandUpdate,
		},
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:    "config",
				Usage:   "config file",
				Aliases: []string{"c"},
				Value:   path.Join(confDir.ConfigDir(), "config.toml"),
			},
			&cli.StringFlag{
				Name:    "api",
				Usage:   "API address",
				Value:   "",
				Hidden:  true,
				EnvVars: []string{"CONTAINERUM_API"},
			},
			&cli.BoolFlag{
				Name:   "debug-requests",
				Value:  false,
				Hidden: true,
			},
			&cli.StringFlag{
				Name:  "username",
				Usage: "your account email",
			},
			&cli.StringFlag{
				Name:  "pass",
				Usage: "password to system",
			},
			&cli.StringFlag{
				Name:    "namespace",
				Aliases: []string{"n"},
				Usage:   "namespace to use",
			},
		},
	}
	return App.Run(args)
}

func runAction(ctx *cli.Context) error {
	logrus.Debugf("loading config")
	if err := loadConfig(ctx); err != nil {
		return err
	}
	logrus.Debugf("running setup")
	err := setupConfig(ctx)
	config := util.GetConfig(ctx)
	switch {
	case err == nil:
		// pass
	case ErrInvalidUserInfo.Match(err):
		logrus.Debugf("invalid user information")
		logrus.Debugf("running login")
		user, err := login(ctx)
		if err != nil {
			return err
		}
		config.UserInfo = user
		util.SetConfig(ctx, config)
	default:
		logrus.Debugf("fatal error")
		return ErrFatalError.Wrap(err)
	}
	logrus.Debugf("client initialisation")
	if err := setupClient(ctx); err != nil {
		return err
	}
	client := util.GetClient(ctx)
	if err := util.SaveTokens(ctx, client.Tokens); err != nil {
		return chkitErrors.NewExitCoder(err)
	}
	config.DefaultNamespace, err = util.GetFirstClientNamespace(ctx)
	if err != nil {
		return err
	}
	util.SetConfig(ctx, config)
	if err := persist(ctx); err != nil {
		logrus.Fatalf("%v", err)
	}
	// re-setup client to save default namespace
	if err := setupClient(ctx); err != nil {
		return err
	}
	clientConfig := client.Config
	logrus.Infof("Hello, %q!", clientConfig.Username)
	if err := mainActivity(ctx); err != nil {
		logrus.Fatalf("error in main activity: %v", err)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2014 Josh Holland
//
// Part of julia, released under the MIT licence.
// Full source available at https://github.com/jshholland/julia

package main

import (
	"fmt"
	"image/png"
	"os"
)

func main() {
	f := NewPoly(-1+.1i, 0, 1)
	m := Draw(f, -2, 2, -2, 2, 0.001)

	out, err := os.Create("julia.png")
	if err != nil {
		fmt.Println(err)
		return
	}

	png.Encode(out, m)
}
<commit_msg>Add some kind of command line interface<commit_after>// Copyright © 2014 Josh Holland
//
// Part of julia, released under the MIT licence.
// Full source available at https://github.com/jshholland/julia

package main

import (
	"flag"
	"fmt"
	"image/png"
	"os"
)

var (
	re   = flag.Float64("real", 0.0, "real part of the constant whose quadratic Julia set to plot")
	im   = flag.Float64("imag", 0.0, "imaginary part of the constant whose quadratic Julia set to plot")
	size = flag.Int("size", 4000, "size in pixels to draw fractal at")
	out  = flag.String("out", "julia.png", "filename to save output to")
)

func main() {
	flag.Parse()
	f := NewPoly(complex(*re, *im), 0, 1)
	m := Draw(f, -2, 2, -2, 2, 4/float64(*size))

	out, err := os.Create(*out)
	if err != nil {
		fmt.Println(err)
		return
	}

	png.Encode(out, m)
}
<|endoftext|>


<commit_before>package junos

import (
	"fmt"
	"github.com/Juniper/go-netconf/netconf"
	"log"
)

type Session struct {
	Conn *netconf.Session
}

func NewSession(host, user, password string) *Session {
    s, err := netconf.DialSSH(host, netconf.SSHConfigPassword(user, password))
    if err != nil {
        log.Fatal(err)
    }

    return &Session{
        Conn: s,
    }
}

func (s *Session) Lock() {
	resp, err := s.Conn.Exec("<rpc><lock-configuration/></rpc>")
	if err != nil {
		fmt.Printf("Error: %+v\n", err)
	}

    fmt.Printf("%+v\n", resp)
}

func (s *Session) Unlock() {
	resp, err := s.Conn.Exec("<rpc><unlock-configuration/></rpc>")
	if err != nil {
		fmt.Printf("Error: %+v\n", err)
	}

    fmt.Printf("%+v\n", resp)
}

func (s *Session) Close() {
    s.Conn.Close()
}<commit_msg>Testing functions<commit_after>package junos

import (
	"fmt"
	"github.com/Juniper/go-netconf/netconf"
	"log"
)

type Session struct {
	Conn *netconf.Session
}

func NewSession(host, user, password string) *Session {
    s, err := netconf.DialSSH(host, netconf.SSHConfigPassword(user, password))
    if err != nil {
        log.Fatal(err)
    }

    return &Session{
        Conn: s,
    }
}

func (s *Session) Lock() {
	resp, err := s.Conn.Exec("<rpc><lock-configuration/></rpc>")
	if err != nil {
		fmt.Printf("Error: %+v\n", err)
	}

    fmt.Println(resp["Data"])
}

func (s *Session) Unlock() {
	resp, err := s.Conn.Exec("<rpc><unlock-configuration/></rpc>")
	if err != nil {
		fmt.Printf("Error: %+v\n", err)
	}

    fmt.Println(resp["Data"])
}

func (s *Session) Close() {
    s.Conn.Close()
}<|endoftext|>


<commit_before>package main

/// had to have a `util` file.
/// Because pragmatism.
/// Because irony.

import (
  "os"
  "fmt"
  "time"
  "regexp"
  "runtime"
  "github.com/parnurzeal/gorequest"
  "github.com/olekukonko/tablewriter"
  "github.com/briandowns/spinner"
)

func AugmentRequest(c *gorequest.SuperAgent, cfg *Config) *gorequest.SuperAgent {
  return c.
    AddCookie(cfg.GetAuthCookie()).
    Set("Content-type","application/json").
    Set("User-Agent", "Nelson CLI ("+runtime.GOOS+"); "+CurrentVersion()).
    Timeout(15*time.Second).
    SetCurlCommand(false).
    SetDebug(globalEnableDebug)
}

func RenderTableToStdout(headers []string, data [][]string){
  table := tablewriter.NewWriter(os.Stdout)
  table.SetHeader(headers)
  table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false})
  table.SetHeaderLine(false)
  table.SetRowLine(false)
  table.SetColWidth(100)
  table.SetColumnSeparator("")
  table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  table.SetAlignment(tablewriter.ALIGN_LEFT)
  table.AppendBulk(data) // Add Bulk Data
  table.Render()
}

func JavaEpochToDateStr(long int64) string {
  t := time.Unix(0, long*int64(time.Millisecond))
  return t.Format(time.RFC3339)
}

func ProgressIndicator() *spinner.Spinner {
  s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
  s.Color("green")
  return s
}

func PrintTerminalErrors(errs []error){
  for i, j := 0, len(errs)-1; i < j; i, j = i+1, j-1 {
    errs[i], errs[j] = errs[j], errs[i]
  }

  for _,e := range errs {
    fmt.Println(e)
  }
}

func IsValidGUID(in string) bool {
  match, _ := regexp.MatchString(`^[a-z0-9]{12,12}$`, in)
  return match
}

func isValidCommaDelimitedList(str string) bool {
  match, _ := regexp.MatchString(`^([a-z0-9\\-]+,?)+$`, str)
  return match
}

func CurrentVersion() string {
  if len(globalBuildVersion) == 0 {
    return "devel"
  } else {
    return "v"+globalBuildVersion
  }
}
<commit_msg>update user agent string<commit_after>package main

/// had to have a `util` file.
/// Because pragmatism.
/// Because irony.

import (
  "os"
  "fmt"
  "time"
  "regexp"
  "runtime"
  "github.com/parnurzeal/gorequest"
  "github.com/olekukonko/tablewriter"
  "github.com/briandowns/spinner"
)

func AugmentRequest(c *gorequest.SuperAgent, cfg *Config) *gorequest.SuperAgent {
  return c.
    AddCookie(cfg.GetAuthCookie()).
    Set("Content-type","application/json").
    Set("User-Agent", "NelsonCLI/0.1."+globalBuildVersion+" ("+runtime.GOOS+")").
    Timeout(15*time.Second).
    SetCurlCommand(false).
    SetDebug(globalEnableDebug)
}

func RenderTableToStdout(headers []string, data [][]string){
  table := tablewriter.NewWriter(os.Stdout)
  table.SetHeader(headers)
  table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false})
  table.SetHeaderLine(false)
  table.SetRowLine(false)
  table.SetColWidth(100)
  table.SetColumnSeparator("")
  table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  table.SetAlignment(tablewriter.ALIGN_LEFT)
  table.AppendBulk(data) // Add Bulk Data
  table.Render()
}

func JavaEpochToDateStr(long int64) string {
  t := time.Unix(0, long*int64(time.Millisecond))
  return t.Format(time.RFC3339)
}

func ProgressIndicator() *spinner.Spinner {
  s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
  s.Color("green")
  return s
}

func PrintTerminalErrors(errs []error){
  for i, j := 0, len(errs)-1; i < j; i, j = i+1, j-1 {
    errs[i], errs[j] = errs[j], errs[i]
  }

  for _,e := range errs {
    fmt.Println(e)
  }
}

func IsValidGUID(in string) bool {
  match, _ := regexp.MatchString(`^[a-z0-9]{12,12}$`, in)
  return match
}

func isValidCommaDelimitedList(str string) bool {
  match, _ := regexp.MatchString(`^([a-z0-9\\-]+,?)+$`, str)
  return match
}

func CurrentVersion() string {
  if len(globalBuildVersion) == 0 {
    return "devel"
  } else {
    return "v"+globalBuildVersion
  }
}
<|endoftext|>


<commit_before>package kamino

import (
	"bytes"
	"fmt"
	"net/url"
	"os/exec"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/modcloth/go-fileutils"
)

type clone struct {
	*Genome
	workdir string
}

func (creator *clone) cachePath() string {
	return fmt.Sprintf("%s/%s/%s", creator.workdir, creator.Account, creator.Repo)
}

func (creator *clone) cloneCacheIfAvailable() (string, error) {
	if err := creator.updateToRef(creator.cachePath()); err != nil {
		return creator.cloneNoCache()
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneForceCache() (string, error) {
	if err := creator.updateToRef(creator.cachePath()); err != nil {
		return "", err
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneCreateCache() (string, error) {
	if err := creator.cloneRepo(creator.cachePath()); err != nil {
		return "", err
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneNoCache() (string, error) {
	uuid, err := nextUUID()
	if err != nil {
		return "", err
	}

	clonePath := fmt.Sprintf("%s/%s/%s", creator.workdir, creator.Account, uuid)

	if err = creator.cloneRepo(clonePath); err != nil {
		return "", err
	}

	return clonePath, nil
}

func (creator *clone) cloneRepo(dest string) error {
	git, err := fileutils.Which("git")
	if err != nil {
		return err
	}

	buff := &bytes.Buffer{}

	repoURL := &url.URL{
		Scheme: "https",
		Host:   "github.com",
		Path:   fmt.Sprintf("%s/%s", creator.Account, creator.Repo),
	}

	if creator.APIToken != "" {
		repoURL.User = url.User(creator.APIToken)
	}

	var cloneCmd *exec.Cmd

	cloneArgs := []string{"git", "clone"}

	if creator.Recursive {
		cloneArgs = append(cloneArgs, "--recursive")
	}

	if creator.Depth != "" {
		cloneArgs = append(cloneArgs, "--depth", creator.Depth)
	}

	cloneArgs = append(cloneArgs, repoURL.String(), dest)

	cloneCmd = &exec.Cmd{
		Path:   git,
		Args:   cloneArgs,
		Stderr: buff,
	}

	if err := cloneCmd.Run(); err != nil {
		Logger.WithFields(logrus.Fields{
			"account":            creator.Account,
			"cache_method":       creator.UseCache,
			"depth":              creator.Depth,
			"ref":                creator.Ref,
			"repo":               creator.Repo,
			"api_token_provided": creator.APIToken != "",
			"go_error":           err,
			"stdout":             buff.String(),
		}).Error("error running clone command")

		return err
	}

	buff.Reset()
	checkoutCmd := &exec.Cmd{
		Path:   git,
		Dir:    dest,
		Args:   []string{"git", "checkout", "--force", creator.Ref},
		Stderr: buff,
	}

	if err := checkoutCmd.Run(); err != nil {
		Logger.WithFields(logrus.Fields{
			"account":            creator.Account,
			"cache_method":       creator.UseCache,
			"depth":              creator.Depth,
			"ref":                creator.Ref,
			"repo":               creator.Repo,
			"api_token_provided": creator.APIToken != "",
			"go_error":           err,
			"stdout":             buff.String(),
		}).Error("error running checkout command")

		return err
	}

	return nil
}

func (creator *clone) updateToRef(dest string) error {
	/*
		workflow as follows:
			git clean -d --force --quiet
			git fetch --prune --quiet
			git checkout --force --quiet <ref>
			git symbolic-ref --quiet HEAD && git pull --rebase --quiet
	*/
	git, err := fileutils.Which("git")
	if err != nil {
		return err
	}

	buff := &bytes.Buffer{}

	cmds := []*exec.Cmd{
		&exec.Cmd{
			Args: []string{"git", "clean", "-d", "--force"},
		},
		&exec.Cmd{
			Args: []string{"git", "fetch", "--prune"},
		},
		&exec.Cmd{
			Args: []string{"git", "checkout", "--force", creator.Ref},
		},
	}

	for _, cmd := range cmds {
		cmd.Path = git
		cmd.Dir = dest
		cmd.Stderr = buff

		if err := cmd.Run(); err != nil {
			Logger.WithFields(logrus.Fields{
				"account":            creator.Account,
				"cache_method":       creator.UseCache,
				"depth":              creator.Depth,
				"ref":                creator.Ref,
				"repo":               creator.Repo,
				"api_token_provided": creator.APIToken != "",
				"go_error":           err,
				"stdout":             buff.String(),
			}).Errorf("error running command %q", strings.Join(cmd.Args, " "))

			return err
		}

		buff.Reset()
	}

	detectBranch := &exec.Cmd{
		Path: git,
		Dir:  dest,
		Args: []string{"git", "symbolic-ref", "HEAD"},
	}

	// no error => we are on a proper branch (as opposed to a detached HEAD)
	if err := detectBranch.Run(); err == nil {
		pullRebase := &exec.Cmd{
			Path:   git,
			Dir:    dest,
			Args:   []string{"git", "pull", "--rebase"},
			Stderr: buff,
		}

		if err = pullRebase.Run(); err != nil {
			Logger.WithFields(logrus.Fields{
				"account":            creator.Account,
				"cache_method":       creator.UseCache,
				"depth":              creator.Depth,
				"ref":                creator.Ref,
				"repo":               creator.Repo,
				"api_token_provided": creator.APIToken != "",
				"go_error":           err,
				"stdout":             buff.String(),
			}).Errorf("error running command %q", strings.Join(pullRebase.Args, " "))

			return err
		}
	}

	return nil
}
<commit_msg>[TRIVIAL] Changing logging msgs to be more accurate<commit_after>package kamino

import (
	"bytes"
	"fmt"
	"net/url"
	"os/exec"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/modcloth/go-fileutils"
)

type clone struct {
	*Genome
	workdir string
}

func (creator *clone) cachePath() string {
	return fmt.Sprintf("%s/%s/%s", creator.workdir, creator.Account, creator.Repo)
}

func (creator *clone) cloneCacheIfAvailable() (string, error) {
	if err := creator.updateToRef(creator.cachePath()); err != nil {
		return creator.cloneNoCache()
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneForceCache() (string, error) {
	if err := creator.updateToRef(creator.cachePath()); err != nil {
		return "", err
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneCreateCache() (string, error) {
	if err := creator.cloneRepo(creator.cachePath()); err != nil {
		return "", err
	}

	return creator.cachePath(), nil
}

func (creator *clone) cloneNoCache() (string, error) {
	uuid, err := nextUUID()
	if err != nil {
		return "", err
	}

	clonePath := fmt.Sprintf("%s/%s/%s", creator.workdir, creator.Account, uuid)

	if err = creator.cloneRepo(clonePath); err != nil {
		return "", err
	}

	return clonePath, nil
}

func (creator *clone) cloneRepo(dest string) error {
	git, err := fileutils.Which("git")
	if err != nil {
		return err
	}

	buff := &bytes.Buffer{}

	repoURL := &url.URL{
		Scheme: "https",
		Host:   "github.com",
		Path:   fmt.Sprintf("%s/%s", creator.Account, creator.Repo),
	}

	if creator.APIToken != "" {
		repoURL.User = url.User(creator.APIToken)
	}

	var cloneCmd *exec.Cmd

	cloneArgs := []string{"git", "clone"}

	if creator.Recursive {
		cloneArgs = append(cloneArgs, "--recursive")
	}

	if creator.Depth != "" {
		cloneArgs = append(cloneArgs, "--depth", creator.Depth)
	}

	cloneArgs = append(cloneArgs, repoURL.String(), dest)

	cloneCmd = &exec.Cmd{
		Path:   git,
		Args:   cloneArgs,
		Stderr: buff,
	}

	if err := cloneCmd.Run(); err != nil {
		Logger.WithFields(logrus.Fields{
			"account":            creator.Account,
			"cache_method":       creator.UseCache,
			"depth":              creator.Depth,
			"ref":                creator.Ref,
			"repo":               creator.Repo,
			"api_token_provided": creator.APIToken != "",
			"go_error":           err,
			"stderr":             buff.String(),
		}).Error("error running clone command")

		return err
	}

	buff.Reset()
	checkoutCmd := &exec.Cmd{
		Path:   git,
		Dir:    dest,
		Args:   []string{"git", "checkout", "--force", creator.Ref},
		Stderr: buff,
	}

	if err := checkoutCmd.Run(); err != nil {
		Logger.WithFields(logrus.Fields{
			"account":            creator.Account,
			"cache_method":       creator.UseCache,
			"depth":              creator.Depth,
			"ref":                creator.Ref,
			"repo":               creator.Repo,
			"api_token_provided": creator.APIToken != "",
			"go_error":           err,
			"stderr":             buff.String(),
		}).Error("error running checkout command")

		return err
	}

	return nil
}

func (creator *clone) updateToRef(dest string) error {
	/*
		workflow as follows:
			git clean -d --force --quiet
			git fetch --prune --quiet
			git checkout --force --quiet <ref>
			git symbolic-ref --quiet HEAD && git pull --rebase --quiet
	*/
	git, err := fileutils.Which("git")
	if err != nil {
		return err
	}

	buff := &bytes.Buffer{}

	cmds := []*exec.Cmd{
		&exec.Cmd{
			Args: []string{"git", "clean", "-d", "--force"},
		},
		&exec.Cmd{
			Args: []string{"git", "fetch", "--prune"},
		},
		&exec.Cmd{
			Args: []string{"git", "checkout", "--force", creator.Ref},
		},
	}

	for _, cmd := range cmds {
		cmd.Path = git
		cmd.Dir = dest
		cmd.Stderr = buff

		if err := cmd.Run(); err != nil {
			Logger.WithFields(logrus.Fields{
				"account":            creator.Account,
				"cache_method":       creator.UseCache,
				"depth":              creator.Depth,
				"ref":                creator.Ref,
				"repo":               creator.Repo,
				"api_token_provided": creator.APIToken != "",
				"go_error":           err,
				"stderr":             buff.String(),
			}).Errorf("error running command %q", strings.Join(cmd.Args, " "))

			return err
		}

		buff.Reset()
	}

	detectBranch := &exec.Cmd{
		Path: git,
		Dir:  dest,
		Args: []string{"git", "symbolic-ref", "HEAD"},
	}

	// no error => we are on a proper branch (as opposed to a detached HEAD)
	if err := detectBranch.Run(); err == nil {
		pullRebase := &exec.Cmd{
			Path:   git,
			Dir:    dest,
			Args:   []string{"git", "pull", "--rebase"},
			Stderr: buff,
		}

		if err = pullRebase.Run(); err != nil {
			Logger.WithFields(logrus.Fields{
				"account":            creator.Account,
				"cache_method":       creator.UseCache,
				"depth":              creator.Depth,
				"ref":                creator.Ref,
				"repo":               creator.Repo,
				"api_token_provided": creator.APIToken != "",
				"go_error":           err,
				"stderr":             buff.String(),
			}).Errorf("error running command %q", strings.Join(pullRebase.Args, " "))

			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package options

import (
	"fmt"
	"strings"

	"k8s.io/apimachinery/pkg/util/sets"
	cliflag "k8s.io/component-base/cli/flag"
	componentbaseconfig "k8s.io/component-base/config"
	"k8s.io/kubernetes/pkg/client/leaderelectionconfig"
	kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
)

// GenericControllerManagerConfigurationOptions holds the options which are generic.
type GenericControllerManagerConfigurationOptions struct {
	*kubectrlmgrconfig.GenericControllerManagerConfiguration
	Debugging *DebuggingOptions
}

// NewGenericControllerManagerConfigurationOptions returns generic configuration default values for both
// the kube-controller-manager and the cloud-contoller-manager. Any common changes should
// be made here. Any individual changes should be made in that controller.
func NewGenericControllerManagerConfigurationOptions(cfg *kubectrlmgrconfig.GenericControllerManagerConfiguration) *GenericControllerManagerConfigurationOptions {
	o := &GenericControllerManagerConfigurationOptions{
		GenericControllerManagerConfiguration: cfg,
		Debugging: &DebuggingOptions{
			DebuggingConfiguration: &componentbaseconfig.DebuggingConfiguration{},
		},
	}

	return o
}

// AddFlags adds flags related to generic for controller manager to the specified FlagSet.
func (o *GenericControllerManagerConfigurationOptions) AddFlags(fss *cliflag.NamedFlagSets, allControllers, disabledByDefaultControllers []string) {
	if o == nil {
		return
	}

	o.Debugging.AddFlags(fss.FlagSet("debugging"))
	genericfs := fss.FlagSet("generic")
	genericfs.DurationVar(&o.MinResyncPeriod.Duration, "min-resync-period", o.MinResyncPeriod.Duration, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod.")
	genericfs.StringVar(&o.ClientConnection.ContentType, "kube-api-content-type", o.ClientConnection.ContentType, "Content type of requests sent to apiserver.")
	genericfs.Float32Var(&o.ClientConnection.QPS, "kube-api-qps", o.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver.")
	genericfs.Int32Var(&o.ClientConnection.Burst, "kube-api-burst", o.ClientConnection.Burst, "Burst to use while talking with kubernetes apiserver.")
	genericfs.DurationVar(&o.ControllerStartInterval.Duration, "controller-start-interval", o.ControllerStartInterval.Duration, "Interval between starting controller managers.")
	genericfs.StringSliceVar(&o.Controllers, "controllers", o.Controllers, fmt.Sprintf(""+
		"A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller "+
		"named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s\nDisabled-by-default controllers: %s",
		strings.Join(allControllers, ", "), strings.Join(disabledByDefaultControllers, ", ")))

	leaderelectionconfig.BindFlags(&o.LeaderElection, genericfs)
}

// ApplyTo fills up generic config with options.
func (o *GenericControllerManagerConfigurationOptions) ApplyTo(cfg *kubectrlmgrconfig.GenericControllerManagerConfiguration) error {
	if o == nil {
		return nil
	}

	if err := o.Debugging.ApplyTo(&cfg.Debugging); err != nil {
		return err
	}

	cfg.Port = o.Port
	cfg.Address = o.Address
	cfg.MinResyncPeriod = o.MinResyncPeriod
	cfg.ClientConnection = o.ClientConnection
	cfg.ControllerStartInterval = o.ControllerStartInterval
	cfg.LeaderElection = o.LeaderElection
	cfg.Controllers = o.Controllers

	return nil
}

// Validate checks validation of GenericOptions.
func (o *GenericControllerManagerConfigurationOptions) Validate(allControllers []string, disabledByDefaultControllers []string) []error {
	if o == nil {
		return nil
	}

	errs := []error{}
	errs = append(errs, o.Debugging.Validate()...)

	allControllersSet := sets.NewString(allControllers...)
	for _, controller := range o.Controllers {
		if controller == "*" {
			continue
		}
		if strings.HasPrefix(controller, "-") {
			controller = controller[1:]
		}
		if !allControllersSet.Has(controller) {
			errs = append(errs, fmt.Errorf("%q is not in the list of known controllers", controller))
		}
	}

	return errs
}
<commit_msg>Clean up controller-manager.<commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package options

import (
	"fmt"
	"strings"

	"k8s.io/apimachinery/pkg/util/sets"
	cliflag "k8s.io/component-base/cli/flag"
	componentbaseconfig "k8s.io/component-base/config"
	"k8s.io/kubernetes/pkg/client/leaderelectionconfig"
	kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
)

// GenericControllerManagerConfigurationOptions holds the options which are generic.
type GenericControllerManagerConfigurationOptions struct {
	*kubectrlmgrconfig.GenericControllerManagerConfiguration
	Debugging *DebuggingOptions
}

// NewGenericControllerManagerConfigurationOptions returns generic configuration default values for both
// the kube-controller-manager and the cloud-contoller-manager. Any common changes should
// be made here. Any individual changes should be made in that controller.
func NewGenericControllerManagerConfigurationOptions(cfg *kubectrlmgrconfig.GenericControllerManagerConfiguration) *GenericControllerManagerConfigurationOptions {
	o := &GenericControllerManagerConfigurationOptions{
		GenericControllerManagerConfiguration: cfg,
		Debugging: &DebuggingOptions{
			DebuggingConfiguration: &componentbaseconfig.DebuggingConfiguration{},
		},
	}

	return o
}

// AddFlags adds flags related to generic for controller manager to the specified FlagSet.
func (o *GenericControllerManagerConfigurationOptions) AddFlags(fss *cliflag.NamedFlagSets, allControllers, disabledByDefaultControllers []string) {
	if o == nil {
		return
	}

	o.Debugging.AddFlags(fss.FlagSet("debugging"))
	genericfs := fss.FlagSet("generic")
	genericfs.DurationVar(&o.MinResyncPeriod.Duration, "min-resync-period", o.MinResyncPeriod.Duration, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod.")
	genericfs.StringVar(&o.ClientConnection.ContentType, "kube-api-content-type", o.ClientConnection.ContentType, "Content type of requests sent to apiserver.")
	genericfs.Float32Var(&o.ClientConnection.QPS, "kube-api-qps", o.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver.")
	genericfs.Int32Var(&o.ClientConnection.Burst, "kube-api-burst", o.ClientConnection.Burst, "Burst to use while talking with kubernetes apiserver.")
	genericfs.DurationVar(&o.ControllerStartInterval.Duration, "controller-start-interval", o.ControllerStartInterval.Duration, "Interval between starting controller managers.")
	genericfs.StringSliceVar(&o.Controllers, "controllers", o.Controllers, fmt.Sprintf(""+
		"A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller "+
		"named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s\nDisabled-by-default controllers: %s",
		strings.Join(allControllers, ", "), strings.Join(disabledByDefaultControllers, ", ")))

	leaderelectionconfig.BindFlags(&o.LeaderElection, genericfs)
}

// ApplyTo fills up generic config with options.
func (o *GenericControllerManagerConfigurationOptions) ApplyTo(cfg *kubectrlmgrconfig.GenericControllerManagerConfiguration) error {
	if o == nil {
		return nil
	}

	if err := o.Debugging.ApplyTo(&cfg.Debugging); err != nil {
		return err
	}

	cfg.Port = o.Port
	cfg.Address = o.Address
	cfg.MinResyncPeriod = o.MinResyncPeriod
	cfg.ClientConnection = o.ClientConnection
	cfg.ControllerStartInterval = o.ControllerStartInterval
	cfg.LeaderElection = o.LeaderElection
	cfg.Controllers = o.Controllers

	return nil
}

// Validate checks validation of GenericOptions.
func (o *GenericControllerManagerConfigurationOptions) Validate(allControllers []string, disabledByDefaultControllers []string) []error {
	if o == nil {
		return nil
	}

	errs := []error{}
	errs = append(errs, o.Debugging.Validate()...)

	allControllersSet := sets.NewString(allControllers...)
	for _, controller := range o.Controllers {
		if controller == "*" {
			continue
		}
		controller = strings.TrimPrefix(controller, "-")
		if !allControllersSet.Has(controller) {
			errs = append(errs, fmt.Errorf("%q is not in the list of known controllers", controller))
		}
	}

	return errs
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Jetstack cert-manager contributors.

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 certificate

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/reference"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/describe"
	"k8s.io/kubectl/pkg/util/i18n"
	"k8s.io/kubectl/pkg/util/templates"

	"github.com/jetstack/cert-manager/cmd/ctl/pkg/status/util"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
	cmclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	"github.com/jetstack/cert-manager/pkg/ctl"
	"github.com/jetstack/cert-manager/pkg/util/predicate"
)

var (
	long = templates.LongDesc(i18n.T(`
Get details about the current status of a cert-manager Certificate resource, including information on related resources like CertificateRequest.`))

	example = templates.Examples(i18n.T(`
# Query status of Certificate with name 'my-crt' in namespace 'my-namespace'
kubectl cert-manager status certificate my-crt --namespace my-namespace
`))
)

// Options is a struct to support status certificate command
type Options struct {
	CMClient   cmclient.Interface
	RESTConfig *restclient.Config
	// The Namespace that the Certificate to be queried about resides in.
	// This flag registration is handled by cmdutil.Factory
	Namespace string

	genericclioptions.IOStreams
}

// NewOptions returns initialized Options
func NewOptions(ioStreams genericclioptions.IOStreams) *Options {
	return &Options{
		IOStreams: ioStreams,
	}
}

// NewCmdStatusCert returns a cobra command for status certificate
func NewCmdStatusCert(ioStreams genericclioptions.IOStreams, factory cmdutil.Factory) *cobra.Command {
	o := NewOptions(ioStreams)
	cmd := &cobra.Command{
		Use:     "certificate",
		Short:   "Get details about the current status of a cert-manager Certificate resource",
		Long:    long,
		Example: example,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(o.Validate(args))
			cmdutil.CheckErr(o.Complete(factory))
			cmdutil.CheckErr(o.Run(args))
		},
	}
	return cmd
}

// Validate validates the provided options
func (o *Options) Validate(args []string) error {
	if len(args) < 1 {
		return errors.New("the name of the Certificate has to be provided as argument")
	}
	if len(args) > 1 {
		return errors.New("only one argument can be passed in: the name of the Certificate")
	}
	return nil
}

// Complete takes the factory and infers any remaining options.
func (o *Options) Complete(f cmdutil.Factory) error {
	var err error

	o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

	o.RESTConfig, err = f.ToRESTConfig()
	if err != nil {
		return err
	}

	o.CMClient, err = cmclient.NewForConfig(o.RESTConfig)
	if err != nil {
		return err
	}

	return nil
}

// Run executes status certificate command
func (o *Options) Run(args []string) error {
	ctx := context.TODO()
	crtName := args[0]

	clientSet, err := kubernetes.NewForConfig(o.RESTConfig)
	if err != nil {
		return err
	}

	crt, err := o.CMClient.CertmanagerV1alpha2().Certificates(o.Namespace).Get(ctx, crtName, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("error when getting Certificate resource: %v", err)
	}

	fmt.Fprintf(o.Out, fmt.Sprintf("Name: %s\nNamespace: %s\n", crt.Name, crt.Namespace))

	// Get necessary info from Certificate
	// Output one line about each type of Condition that is set.
	// Certificate can have multiple Conditions of different types set, e.g. "Ready" or "Issuing"
	conditionMsg := ""
	for _, con := range crt.Status.Conditions {
		conditionMsg += fmt.Sprintf("  %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message)
	}
	if conditionMsg == "" {
		conditionMsg = "  No Conditions set\n"
	}
	fmt.Fprintf(o.Out, fmt.Sprintf("Conditions:\n%s", conditionMsg))

	dnsNames := formatStringSlice(crt.Spec.DNSNames)
	fmt.Fprintf(o.Out, fmt.Sprintf("DNS Names:\n%s", dnsNames))

	crtRef, err := reference.GetReference(ctl.Scheme, crt)
	if err != nil {
		return err
	}
	// Ignore error, since if there was an error, crtEvents would be nil and handled down the line in DescribeEvents
	crtEvents, _ := clientSet.CoreV1().Events(o.Namespace).Search(ctl.Scheme, crtRef)
	prefixWriter := util.NewPrefixWriter(o.Out)
	describe.DescribeEvents(crtEvents, prefixWriter)

	issuerFormat := `Issuer:
  Name: %s
  Kind: %s`
	fmt.Fprintf(o.Out, fmt.Sprintf(issuerFormat+"\n", crt.Spec.IssuerRef.Name, crt.Spec.IssuerRef.Kind))

	fmt.Fprintf(o.Out, fmt.Sprintf("Secret Name: %s\n", crt.Spec.SecretName))

	fmt.Fprintf(o.Out, fmt.Sprintf("Not Before: %s\n", formatTimeString(crt.Status.NotBefore)))
	fmt.Fprintf(o.Out, fmt.Sprintf("Not After: %s\n", formatTimeString(crt.Status.NotAfter)))
	fmt.Fprintf(o.Out, fmt.Sprintf("Renewal Time: %s\n", formatTimeString(crt.Status.RenewalTime)))

	// TODO: What about timing issues? When I query condition it's not ready yet, but then looking for cr it's finished and deleted
	// Try find the CertificateRequest that is owned by crt and has the correct revision
	reqs, err := o.CMClient.CertmanagerV1alpha2().CertificateRequests(o.Namespace).List(ctx, metav1.ListOptions{})
	if err != nil {
		return err
	}
	req, err := findMatchingCR(reqs, crt)
	if err != nil {
		return err
	}
	fmt.Fprintf(o.Out, crInfoString(req))
	if req != nil {
		reqRef, err := reference.GetReference(ctl.Scheme, req)
		if err != nil {
			return err
		}
		// Ignore error, since if there was an error, reqEvents would be nil and handled down the line in DescribeEvents
		reqEvents, _ := clientSet.CoreV1().Events(o.Namespace).Search(ctl.Scheme, reqRef)

		prefixWriter.SetBaseLevel(1)
		describe.DescribeEvents(reqEvents, prefixWriter)
	}

	// TODO: print information about secret
	return nil
}

// formatStringSlice takes in a string slice and formats the contents of the slice
// into a single string where each element of the slice is prefixed with "- " and on a new line
func formatStringSlice(strings []string) string {
	result := ""
	for _, str := range strings {
		result += "- " + str + "\n"
	}
	return result
}

// formatTimeString returns the time as a string
// If nil, return "<none>"
func formatTimeString(t *metav1.Time) string {
	if t == nil {
		return "<none>"
	}
	return t.Time.Format(time.RFC3339)
}

// findMatchingCR tries to find a CertificateRequest that is owned by crt and has the correct revision annotated from reqs.
// If none found returns nil
// If one found returns the CR
// If multiple found returns error
func findMatchingCR(reqs *cmapi.CertificateRequestList, crt *cmapi.Certificate) (*cmapi.CertificateRequest, error) {
	possibleMatches := []*cmapi.CertificateRequest{}

	// CertificateRequest revisions begin from 1.
	// If no revision is set on the Certificate then assume the revision on the CertificateRequest should be 1.
	// If revision is set on the Certificate then revision on the CertificateRequest should be crt.Status.Revision + 1.
	nextRevision := 1
	if crt.Status.Revision != nil {
		nextRevision = *crt.Status.Revision + 1
	}
	for _, req := range reqs.Items {
		if predicate.CertificateRequestRevision(nextRevision)(&req) &&
			predicate.ResourceOwnedBy(crt)(&req) {
			possibleMatches = append(possibleMatches, &req)
		}
	}

	if len(possibleMatches) < 1 {
		return nil, nil
	} else if len(possibleMatches) == 1 {
		return possibleMatches[0], nil
	} else {
		return nil, errors.New("found multiple certificate requests with expected revision and owner")
	}
}

// crInfoString returns the information of a CR as a string to be printed as output
func crInfoString(cr *cmapi.CertificateRequest) string {
	if cr == nil {
		return "No CertificateRequest found for this Certificate"
	}

	crFormat := `
  Name: %s
  Namespace: %s
  Conditions:
  %s`
	conditionMsg := ""
	for _, con := range cr.Status.Conditions {
		conditionMsg += fmt.Sprintf("  %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message)
	}
	if conditionMsg == "" {
		conditionMsg = "  No Conditions set\n"
	}
	infos := fmt.Sprintf(crFormat, cr.Name, cr.Namespace, conditionMsg)
	return fmt.Sprintf("CertificateRequest:%s", infos)
}
<commit_msg>Review implementations<commit_after>/*
Copyright 2020 The Jetstack cert-manager contributors.

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 certificate

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/reference"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/describe"
	"k8s.io/kubectl/pkg/util/i18n"
	"k8s.io/kubectl/pkg/util/templates"

	"github.com/jetstack/cert-manager/cmd/ctl/pkg/status/util"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
	cmclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	"github.com/jetstack/cert-manager/pkg/ctl"
	"github.com/jetstack/cert-manager/pkg/util/predicate"
)

var (
	long = templates.LongDesc(i18n.T(`
Get details about the current status of a cert-manager Certificate resource, including information on related resources like CertificateRequest.`))

	example = templates.Examples(i18n.T(`
# Query status of Certificate with name 'my-crt' in namespace 'my-namespace'
kubectl cert-manager status certificate my-crt --namespace my-namespace
`))
)

// Options is a struct to support status certificate command
type Options struct {
	CMClient   cmclient.Interface
	RESTConfig *restclient.Config
	// The Namespace that the Certificate to be queried about resides in.
	// This flag registration is handled by cmdutil.Factory
	Namespace string

	genericclioptions.IOStreams
}

// NewOptions returns initialized Options
func NewOptions(ioStreams genericclioptions.IOStreams) *Options {
	return &Options{
		IOStreams: ioStreams,
	}
}

// NewCmdStatusCert returns a cobra command for status certificate
func NewCmdStatusCert(ioStreams genericclioptions.IOStreams, factory cmdutil.Factory) *cobra.Command {
	o := NewOptions(ioStreams)
	cmd := &cobra.Command{
		Use:     "certificate",
		Short:   "Get details about the current status of a cert-manager Certificate resource",
		Long:    long,
		Example: example,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(o.Validate(args))
			cmdutil.CheckErr(o.Complete(factory))
			cmdutil.CheckErr(o.Run(args))
		},
	}
	return cmd
}

// Validate validates the provided options
func (o *Options) Validate(args []string) error {
	if len(args) < 1 {
		return errors.New("the name of the Certificate has to be provided as argument")
	}
	if len(args) > 1 {
		return errors.New("only one argument can be passed in: the name of the Certificate")
	}
	return nil
}

// Complete takes the factory and infers any remaining options.
func (o *Options) Complete(f cmdutil.Factory) error {
	var err error

	o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

	o.RESTConfig, err = f.ToRESTConfig()
	if err != nil {
		return err
	}

	o.CMClient, err = cmclient.NewForConfig(o.RESTConfig)
	if err != nil {
		return err
	}

	return nil
}

// Run executes status certificate command
func (o *Options) Run(args []string) error {
	ctx := context.TODO()
	crtName := args[0]

	clientSet, err := kubernetes.NewForConfig(o.RESTConfig)
	if err != nil {
		return err
	}

	crt, err := o.CMClient.CertmanagerV1alpha2().Certificates(o.Namespace).Get(ctx, crtName, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("error when getting Certificate resource: %v", err)
	}

	fmt.Fprintf(o.Out, fmt.Sprintf("Name: %s\nNamespace: %s\n", crt.Name, crt.Namespace))

	// Get necessary info from Certificate
	// Output one line about each type of Condition that is set.
	// Certificate can have multiple Conditions of different types set, e.g. "Ready" or "Issuing"
	conditionMsg := ""
	for _, con := range crt.Status.Conditions {
		conditionMsg += fmt.Sprintf("  %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message)
	}
	if conditionMsg == "" {
		conditionMsg = "  No Conditions set\n"
	}
	fmt.Fprintf(o.Out, fmt.Sprintf("Conditions:\n%s", conditionMsg))

	dnsNames := formatStringSlice(crt.Spec.DNSNames)
	fmt.Fprintf(o.Out, fmt.Sprintf("DNS Names:\n%s", dnsNames))

	crtRef, err := reference.GetReference(ctl.Scheme, crt)
	if err != nil {
		return err
	}
	// Ignore error, since if there was an error, crtEvents would be nil and handled down the line in DescribeEvents
	crtEvents, _ := clientSet.CoreV1().Events(o.Namespace).Search(ctl.Scheme, crtRef)
	prefixWriter := util.NewPrefixWriter(o.Out)
	describe.DescribeEvents(crtEvents, prefixWriter)

	issuerFormat := `Issuer:
  Name: %s
  Kind: %s`
	issuerKind := crt.Spec.IssuerRef.Kind
	if issuerKind == "" {
		issuerKind = "Issuer"
	}
	fmt.Fprintf(o.Out, fmt.Sprintf(issuerFormat+"\n", crt.Spec.IssuerRef.Name, issuerKind))

	fmt.Fprintf(o.Out, fmt.Sprintf("Secret Name: %s\n", crt.Spec.SecretName))

	fmt.Fprintf(o.Out, fmt.Sprintf("Not Before: %s\n", formatTimeString(crt.Status.NotBefore)))
	fmt.Fprintf(o.Out, fmt.Sprintf("Not After: %s\n", formatTimeString(crt.Status.NotAfter)))
	fmt.Fprintf(o.Out, fmt.Sprintf("Renewal Time: %s\n", formatTimeString(crt.Status.RenewalTime)))

	// TODO: What about timing issues? When I query condition it's not ready yet, but then looking for cr it's finished and deleted
	// Try find the CertificateRequest that is owned by crt and has the correct revision
	reqs, err := o.CMClient.CertmanagerV1alpha2().CertificateRequests(o.Namespace).List(ctx, metav1.ListOptions{})
	if err != nil {
		return err
	}
	req, err := findMatchingCR(reqs, crt)
	if err != nil {
		return err
	}
	fmt.Fprintf(o.Out, crInfoString(req))
	if req != nil {
		reqRef, err := reference.GetReference(ctl.Scheme, req)
		if err != nil {
			return err
		}
		// Ignore error, since if there was an error, reqEvents would be nil and handled down the line in DescribeEvents
		reqEvents, _ := clientSet.CoreV1().Events(o.Namespace).Search(ctl.Scheme, reqRef)

		prefixWriter.SetBaseLevel(1)
		describe.DescribeEvents(reqEvents, prefixWriter)
	}

	// TODO: print information about secret
	return nil
}

// formatStringSlice takes in a string slice and formats the contents of the slice
// into a single string where each element of the slice is prefixed with "- " and on a new line
func formatStringSlice(strings []string) string {
	result := ""
	for _, str := range strings {
		result += "- " + str + "\n"
	}
	return result
}

// formatTimeString returns the time as a string
// If nil, return "<none>"
func formatTimeString(t *metav1.Time) string {
	if t == nil {
		return "<none>"
	}
	return t.Time.Format(time.RFC3339)
}

// findMatchingCR tries to find a CertificateRequest that is owned by crt and has the correct revision annotated from reqs.
// If none found returns nil
// If one found returns the CR
// If multiple found returns error
func findMatchingCR(reqs *cmapi.CertificateRequestList, crt *cmapi.Certificate) (*cmapi.CertificateRequest, error) {
	possibleMatches := []*cmapi.CertificateRequest{}

	// CertificateRequest revisions begin from 1.
	// If no revision is set on the Certificate then assume the revision on the CertificateRequest should be 1.
	// If revision is set on the Certificate then revision on the CertificateRequest should be crt.Status.Revision + 1.
	nextRevision := 1
	if crt.Status.Revision != nil {
		nextRevision = *crt.Status.Revision + 1
	}
	for _, req := range reqs.Items {
		if predicate.CertificateRequestRevision(nextRevision)(&req) &&
			predicate.ResourceOwnedBy(crt)(&req) {
			possibleMatches = append(possibleMatches, &req)
		}
	}

	if len(possibleMatches) < 1 {
		return nil, nil
	} else if len(possibleMatches) == 1 {
		return possibleMatches[0], nil
	} else {
		return nil, errors.New("found multiple certificate requests with expected revision and owner")
	}
}

// crInfoString returns the information of a CR as a string to be printed as output
func crInfoString(cr *cmapi.CertificateRequest) string {
	if cr == nil {
		return "No CertificateRequest found for this Certificate\n"
	}

	crFormat := `
  Name: %s
  Namespace: %s
  Conditions:
  %s`
	conditionMsg := ""
	for _, con := range cr.Status.Conditions {
		conditionMsg += fmt.Sprintf("  %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message)
	}
	if conditionMsg == "" {
		conditionMsg = "  No Conditions set\n"
	}
	infos := fmt.Sprintf(crFormat, cr.Name, cr.Namespace, conditionMsg)
	return fmt.Sprintf("CertificateRequest:%s", infos)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os/exec"
	"syscall"
)

type Command struct {
	Bin string
}

func (c *Command) Exec(cmds ...string) (string, int) {
	cmd := exec.Command(c.Bin, cmds...)

	stdout := &bytes.Buffer{}
	stderr := &bytes.Buffer{}
	cmd.Stderr = stderr

	reader, _ := cmd.StdoutPipe()
	scanner := bufio.NewScanner(reader)
	go func() {
		for scanner.Scan() {
			stdout.WriteString(fmt.Sprintf("%s\n", scanner.Bytes()))
		}
	}()

	if err := cmd.Start(); err != nil {
		return "Failed to spawn command\n", 1
	}

	if err := cmd.Wait(); err != nil {
		code := 1

		// Make sure we catch errors and return the correct exit code, if possible
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				code = status.ExitStatus()
			}
		}

		return stderr.String(), code
	}

	return stdout.String(), 0
}
<commit_msg>run format<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os/exec"
	"syscall"
)

type Command struct {
	Bin string
}

func (c *Command) Exec(cmds ...string) (string, int) {
	cmd := exec.Command(c.Bin, cmds...)

	stdout := &bytes.Buffer{}
	stderr := &bytes.Buffer{}
	cmd.Stderr = stderr

	reader, _ := cmd.StdoutPipe()
	scanner := bufio.NewScanner(reader)
	go func() {
		for scanner.Scan() {
			stdout.WriteString(fmt.Sprintf("%s\n", scanner.Bytes()))
		}
	}()

	if err := cmd.Start(); err != nil {
		return "Failed to spawn command\n", 1
	}

	if err := cmd.Wait(); err != nil {
		code := 1

		// Make sure we catch errors and return the correct exit code, if possible
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				code = status.ExitStatus()
			}
		}

		return stderr.String(), code
	}

	return stdout.String(), 0
}
<|endoftext|>


<commit_before>package cli

import (
	"flag"
	"fmt"
	"sort"
	"strings"
)

// Command is a subcommand for a cli.App.
type Command struct {
	// The name of the command
	Name string
	// A list of aliases for the command
	Aliases []string
	// A short description of the usage of this command
	Usage string
	// Custom text to show on USAGE section of help
	UsageText string
	// A longer explanation of how the command works
	Description string
	// A short description of the arguments of this command
	ArgsUsage string
	// The category the command is part of
	Category string
	// The function to call when checking for bash command completions
	BashComplete BashCompleteFunc
	// An action to execute before any sub-subcommands are run, but after the context is ready
	// If a non-nil error is returned, no sub-subcommands are run
	Before BeforeFunc
	// An action to execute after any subcommands are run, but after the subcommand has finished
	// It is run even if Action() panics
	After AfterFunc
	// The function to call when this command is invoked
	Action ActionFunc
	// Execute this function if a usage error occurs.
	OnUsageError OnUsageErrorFunc
	// List of child commands
	Subcommands []*Command
	// List of flags to parse
	Flags []Flag
	// Treat all flags as normal arguments if true
	SkipFlagParsing bool
	// Boolean to hide built-in help command and help flag
	HideHelp bool
	// Boolean to hide built-in help command but keep help flag
	// Ignored if HideHelp is true.
	HideHelpCommand bool
	// Boolean to hide this command from help or completion
	Hidden bool
	// Boolean to enable short-option handling so user can combine several
	// single-character bool arguments into one
	// i.e. foobar -o -v -> foobar -ov
	UseShortOptionHandling bool

	// Full name of command for help, defaults to full command name, including parent commands.
	HelpName        string
	commandNamePath []string

	// CustomHelpTemplate the text template for the command help topic.
	// cli.go uses text/template to render templates. You can
	// render custom help text by setting this variable.
	CustomHelpTemplate string
}

type Commands []*Command

type CommandsByName []*Command

func (c CommandsByName) Len() int {
	return len(c)
}

func (c CommandsByName) Less(i, j int) bool {
	return lexicographicLess(c[i].Name, c[j].Name)
}

func (c CommandsByName) Swap(i, j int) {
	c[i], c[j] = c[j], c[i]
}

// FullName returns the full name of the command.
// For subcommands this ensures that parent commands are part of the command path
func (c *Command) FullName() string {
	if c.commandNamePath == nil {
		return c.Name
	}
	return strings.Join(c.commandNamePath, " ")
}

// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c *Command) Run(ctx *Context) (err error) {
	if len(c.Subcommands) > 0 {
		return c.startApp(ctx)
	}

	if !c.HideHelp && HelpFlag != nil {
		// append help to flags
		c.appendFlag(HelpFlag)
	}

	if ctx.App.UseShortOptionHandling {
		c.UseShortOptionHandling = true
	}

	set, err := c.parseFlags(ctx.Args(), ctx.shellComplete)

	context := NewContext(ctx.App, set, ctx)
	context.Command = c
	if checkCommandCompletions(context, c.Name) {
		return nil
	}

	if err != nil {
		if c.OnUsageError != nil {
			err = c.OnUsageError(context, err, false)
			context.App.handleExitCoder(context, err)
			return err
		}
		_, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
		_, _ = fmt.Fprintln(context.App.Writer)
		_ = ShowCommandHelp(context, c.Name)
		return err
	}

	if checkCommandHelp(context, c.Name) {
		return nil
	}

	cerr := checkRequiredFlags(c.Flags, context)
	if cerr != nil {
		_ = ShowCommandHelp(context, c.Name)
		return cerr
	}

	if c.After != nil {
		defer func() {
			afterErr := c.After(context)
			if afterErr != nil {
				context.App.handleExitCoder(context, err)
				if err != nil {
					err = newMultiError(err, afterErr)
				} else {
					err = afterErr
				}
			}
		}()
	}

	if c.Before != nil {
		err = c.Before(context)
		if err != nil {
			_ = ShowCommandHelp(context, c.Name)
			context.App.handleExitCoder(context, err)
			return err
		}
	}

	if c.Action == nil {
		c.Action = helpSubcommand.Action
	}

	context.Command = c
	err = c.Action(context)

	if err != nil {
		context.App.handleExitCoder(context, err)
	}
	return err
}

func (c *Command) newFlagSet() (*flag.FlagSet, error) {
	return flagSet(c.Name, c.Flags)
}

func (c *Command) useShortOptionHandling() bool {
	return c.UseShortOptionHandling
}

func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) {
	set, err := c.newFlagSet()
	if err != nil {
		return nil, err
	}

	if c.SkipFlagParsing {
		return set, set.Parse(append([]string{"--"}, args.Tail()...))
	}

	err = parseIter(set, c, args.Tail(), shellComplete)
	if err != nil {
		return nil, err
	}

	err = normalizeFlags(c.Flags, set)
	if err != nil {
		return nil, err
	}

	return set, nil
}

// Names returns the names including short names and aliases.
func (c *Command) Names() []string {
	return append([]string{c.Name}, c.Aliases...)
}

// HasName returns true if Command.Name matches given name
func (c *Command) HasName(name string) bool {
	for _, n := range c.Names() {
		if n == name {
			return true
		}
	}
	return false
}

func (c *Command) startApp(ctx *Context) error {
	app := &App{
		Metadata: ctx.App.Metadata,
		Name:     fmt.Sprintf("%s %s", ctx.App.Name, c.Name),
	}

	if c.HelpName == "" {
		app.HelpName = c.HelpName
	} else {
		app.HelpName = app.Name
	}

	app.Usage = c.Usage
	app.Description = c.Description
	app.ArgsUsage = c.ArgsUsage

	// set CommandNotFound
	app.CommandNotFound = ctx.App.CommandNotFound
	app.CustomAppHelpTemplate = c.CustomHelpTemplate

	// set the flags and commands
	app.Commands = c.Subcommands
	app.Flags = c.Flags
	app.HideHelp = c.HideHelp
	app.HideHelpCommand = c.HideHelpCommand

	app.Version = ctx.App.Version
	app.HideVersion = ctx.App.HideVersion
	app.Compiled = ctx.App.Compiled
	app.Writer = ctx.App.Writer
	app.ErrWriter = ctx.App.ErrWriter
	app.ExitErrHandler = ctx.App.ExitErrHandler
	app.UseShortOptionHandling = ctx.App.UseShortOptionHandling

	app.categories = newCommandCategories()
	for _, command := range c.Subcommands {
		app.categories.AddCommand(command.Category, command)
	}

	sort.Sort(app.categories.(*commandCategories))

	// bash completion
	app.EnableBashCompletion = ctx.App.EnableBashCompletion
	if c.BashComplete != nil {
		app.BashComplete = c.BashComplete
	}

	// set the actions
	app.Before = c.Before
	app.After = c.After
	if c.Action != nil {
		app.Action = c.Action
	} else {
		app.Action = helpSubcommand.Action
	}
	app.OnUsageError = c.OnUsageError

	for index, cc := range app.Commands {
		app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
	}

	return app.RunAsSubcommand(ctx)
}

// VisibleFlags returns a slice of the Flags with Hidden=false
func (c *Command) VisibleFlags() []Flag {
	return visibleFlags(c.Flags)
}

func (c *Command) appendFlag(fl Flag) {
	if !hasFlag(c.Flags, fl) {
		c.Flags = append(c.Flags, fl)
	}
}

func hasCommand(commands []*Command, command *Command) bool {
	for _, existing := range commands {
		if command == existing {
			return true
		}
	}

	return false
}
<commit_msg>Harmonize BeforeError usage in Command#Run<commit_after>package cli

import (
	"flag"
	"fmt"
	"sort"
	"strings"
)

// Command is a subcommand for a cli.App.
type Command struct {
	// The name of the command
	Name string
	// A list of aliases for the command
	Aliases []string
	// A short description of the usage of this command
	Usage string
	// Custom text to show on USAGE section of help
	UsageText string
	// A longer explanation of how the command works
	Description string
	// A short description of the arguments of this command
	ArgsUsage string
	// The category the command is part of
	Category string
	// The function to call when checking for bash command completions
	BashComplete BashCompleteFunc
	// An action to execute before any sub-subcommands are run, but after the context is ready
	// If a non-nil error is returned, no sub-subcommands are run
	Before BeforeFunc
	// An action to execute after any subcommands are run, but after the subcommand has finished
	// It is run even if Action() panics
	After AfterFunc
	// The function to call when this command is invoked
	Action ActionFunc
	// Execute this function if a usage error occurs.
	OnUsageError OnUsageErrorFunc
	// List of child commands
	Subcommands []*Command
	// List of flags to parse
	Flags []Flag
	// Treat all flags as normal arguments if true
	SkipFlagParsing bool
	// Boolean to hide built-in help command and help flag
	HideHelp bool
	// Boolean to hide built-in help command but keep help flag
	// Ignored if HideHelp is true.
	HideHelpCommand bool
	// Boolean to hide this command from help or completion
	Hidden bool
	// Boolean to enable short-option handling so user can combine several
	// single-character bool arguments into one
	// i.e. foobar -o -v -> foobar -ov
	UseShortOptionHandling bool

	// Full name of command for help, defaults to full command name, including parent commands.
	HelpName        string
	commandNamePath []string

	// CustomHelpTemplate the text template for the command help topic.
	// cli.go uses text/template to render templates. You can
	// render custom help text by setting this variable.
	CustomHelpTemplate string
}

type Commands []*Command

type CommandsByName []*Command

func (c CommandsByName) Len() int {
	return len(c)
}

func (c CommandsByName) Less(i, j int) bool {
	return lexicographicLess(c[i].Name, c[j].Name)
}

func (c CommandsByName) Swap(i, j int) {
	c[i], c[j] = c[j], c[i]
}

// FullName returns the full name of the command.
// For subcommands this ensures that parent commands are part of the command path
func (c *Command) FullName() string {
	if c.commandNamePath == nil {
		return c.Name
	}
	return strings.Join(c.commandNamePath, " ")
}

// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c *Command) Run(ctx *Context) (err error) {
	if len(c.Subcommands) > 0 {
		return c.startApp(ctx)
	}

	if !c.HideHelp && HelpFlag != nil {
		// append help to flags
		c.appendFlag(HelpFlag)
	}

	if ctx.App.UseShortOptionHandling {
		c.UseShortOptionHandling = true
	}

	set, err := c.parseFlags(ctx.Args(), ctx.shellComplete)

	context := NewContext(ctx.App, set, ctx)
	context.Command = c
	if checkCommandCompletions(context, c.Name) {
		return nil
	}

	if err != nil {
		if c.OnUsageError != nil {
			err = c.OnUsageError(context, err, false)
			context.App.handleExitCoder(context, err)
			return err
		}
		_, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
		_, _ = fmt.Fprintln(context.App.Writer)
		_ = ShowCommandHelp(context, c.Name)
		return err
	}

	if checkCommandHelp(context, c.Name) {
		return nil
	}

	cerr := checkRequiredFlags(c.Flags, context)
	if cerr != nil {
		_ = ShowCommandHelp(context, c.Name)
		return cerr
	}

	if c.After != nil {
		defer func() {
			afterErr := c.After(context)
			if afterErr != nil {
				context.App.handleExitCoder(context, err)
				if err != nil {
					err = newMultiError(err, afterErr)
				} else {
					err = afterErr
				}
			}
		}()
	}

	if c.Before != nil {
		err = c.Before(context)
		if err != nil {
			context.App.handleExitCoder(context, err)
			return err
		}
	}

	if c.Action == nil {
		c.Action = helpSubcommand.Action
	}

	context.Command = c
	err = c.Action(context)

	if err != nil {
		context.App.handleExitCoder(context, err)
	}
	return err
}

func (c *Command) newFlagSet() (*flag.FlagSet, error) {
	return flagSet(c.Name, c.Flags)
}

func (c *Command) useShortOptionHandling() bool {
	return c.UseShortOptionHandling
}

func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) {
	set, err := c.newFlagSet()
	if err != nil {
		return nil, err
	}

	if c.SkipFlagParsing {
		return set, set.Parse(append([]string{"--"}, args.Tail()...))
	}

	err = parseIter(set, c, args.Tail(), shellComplete)
	if err != nil {
		return nil, err
	}

	err = normalizeFlags(c.Flags, set)
	if err != nil {
		return nil, err
	}

	return set, nil
}

// Names returns the names including short names and aliases.
func (c *Command) Names() []string {
	return append([]string{c.Name}, c.Aliases...)
}

// HasName returns true if Command.Name matches given name
func (c *Command) HasName(name string) bool {
	for _, n := range c.Names() {
		if n == name {
			return true
		}
	}
	return false
}

func (c *Command) startApp(ctx *Context) error {
	app := &App{
		Metadata: ctx.App.Metadata,
		Name:     fmt.Sprintf("%s %s", ctx.App.Name, c.Name),
	}

	if c.HelpName == "" {
		app.HelpName = c.HelpName
	} else {
		app.HelpName = app.Name
	}

	app.Usage = c.Usage
	app.Description = c.Description
	app.ArgsUsage = c.ArgsUsage

	// set CommandNotFound
	app.CommandNotFound = ctx.App.CommandNotFound
	app.CustomAppHelpTemplate = c.CustomHelpTemplate

	// set the flags and commands
	app.Commands = c.Subcommands
	app.Flags = c.Flags
	app.HideHelp = c.HideHelp
	app.HideHelpCommand = c.HideHelpCommand

	app.Version = ctx.App.Version
	app.HideVersion = ctx.App.HideVersion
	app.Compiled = ctx.App.Compiled
	app.Writer = ctx.App.Writer
	app.ErrWriter = ctx.App.ErrWriter
	app.ExitErrHandler = ctx.App.ExitErrHandler
	app.UseShortOptionHandling = ctx.App.UseShortOptionHandling

	app.categories = newCommandCategories()
	for _, command := range c.Subcommands {
		app.categories.AddCommand(command.Category, command)
	}

	sort.Sort(app.categories.(*commandCategories))

	// bash completion
	app.EnableBashCompletion = ctx.App.EnableBashCompletion
	if c.BashComplete != nil {
		app.BashComplete = c.BashComplete
	}

	// set the actions
	app.Before = c.Before
	app.After = c.After
	if c.Action != nil {
		app.Action = c.Action
	} else {
		app.Action = helpSubcommand.Action
	}
	app.OnUsageError = c.OnUsageError

	for index, cc := range app.Commands {
		app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
	}

	return app.RunAsSubcommand(ctx)
}

// VisibleFlags returns a slice of the Flags with Hidden=false
func (c *Command) VisibleFlags() []Flag {
	return visibleFlags(c.Flags)
}

func (c *Command) appendFlag(fl Flag) {
	if !hasFlag(c.Flags, fl) {
		c.Flags = append(c.Flags, fl)
	}
}

func hasCommand(commands []*Command, command *Command) bool {
	for _, existing := range commands {
		if command == existing {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

import (
	"context"
	"fmt"
	"net/url"
	"strings"

	"github.com/olivere/elastic/uritemplates"
)

// ClusterStateService allows to get a comprehensive state information of the whole cluster.
//
// See https://www.elastic.co/guide/en/elasticsearch/reference/6.2/cluster-state.html
// for details.
type ClusterStateService struct {
	client            *Client
	pretty            bool
	indices           []string
	metrics           []string
	allowNoIndices    *bool
	expandWildcards   string
	flatSettings      *bool
	ignoreUnavailable *bool
	local             *bool
	masterTimeout     string
}

// NewClusterStateService creates a new ClusterStateService.
func NewClusterStateService(client *Client) *ClusterStateService {
	return &ClusterStateService{
		client:  client,
		indices: make([]string, 0),
		metrics: make([]string, 0),
	}
}

// Index is a list of index names. Use _all or an empty string to
// perform the operation on all indices.
func (s *ClusterStateService) Index(indices ...string) *ClusterStateService {
	s.indices = append(s.indices, indices...)
	return s
}

// Metric limits the information returned to the specified metric.
// It can be one of: version, master_node, nodes, routing_table, metadata,
// blocks, or customs.
func (s *ClusterStateService) Metric(metrics ...string) *ClusterStateService {
	s.metrics = append(s.metrics, metrics...)
	return s
}

// AllowNoIndices indicates whether to ignore if a wildcard indices
// expression resolves into no concrete indices.
// (This includes `_all` string or when no indices have been specified).
func (s *ClusterStateService) AllowNoIndices(allowNoIndices bool) *ClusterStateService {
	s.allowNoIndices = &allowNoIndices
	return s
}

// ExpandWildcards indicates whether to expand wildcard expression to
// concrete indices that are open, closed or both..
func (s *ClusterStateService) ExpandWildcards(expandWildcards string) *ClusterStateService {
	s.expandWildcards = expandWildcards
	return s
}

// FlatSettings, when set, returns settings in flat format (default: false).
func (s *ClusterStateService) FlatSettings(flatSettings bool) *ClusterStateService {
	s.flatSettings = &flatSettings
	return s
}

// IgnoreUnavailable indicates whether specified concrete indices should be
// ignored when unavailable (missing or closed).
func (s *ClusterStateService) IgnoreUnavailable(ignoreUnavailable bool) *ClusterStateService {
	s.ignoreUnavailable = &ignoreUnavailable
	return s
}

// Local indicates whether to return local information. When set, it does not
// retrieve the state from master node (default: false).
func (s *ClusterStateService) Local(local bool) *ClusterStateService {
	s.local = &local
	return s
}

// MasterTimeout specifies timeout for connection to master.
func (s *ClusterStateService) MasterTimeout(masterTimeout string) *ClusterStateService {
	s.masterTimeout = masterTimeout
	return s
}

// Pretty indicates that the JSON response be indented and human readable.
func (s *ClusterStateService) Pretty(pretty bool) *ClusterStateService {
	s.pretty = pretty
	return s
}

// buildURL builds the URL for the operation.
func (s *ClusterStateService) buildURL() (string, url.Values, error) {
	// Build URL
	metrics := strings.Join(s.metrics, ",")
	if metrics == "" {
		metrics = "_all"
	}
	indices := strings.Join(s.indices, ",")
	if indices == "" {
		indices = "_all"
	}
	path, err := uritemplates.Expand("/_cluster/state/{metrics}/{indices}", map[string]string{
		"metrics": metrics,
		"indices": indices,
	})
	if err != nil {
		return "", url.Values{}, err
	}

	// Add query string parameters
	params := url.Values{}
	if s.pretty {
		params.Set("pretty", "true")
	}
	if s.allowNoIndices != nil {
		params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices))
	}
	if s.expandWildcards != "" {
		params.Set("expand_wildcards", s.expandWildcards)
	}
	if s.flatSettings != nil {
		params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings))
	}
	if s.ignoreUnavailable != nil {
		params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable))
	}
	if s.local != nil {
		params.Set("local", fmt.Sprintf("%v", *s.local))
	}
	if s.masterTimeout != "" {
		params.Set("master_timeout", s.masterTimeout)
	}
	return path, params, nil
}

// Validate checks if the operation is valid.
func (s *ClusterStateService) Validate() error {
	return nil
}

// Do executes the operation.
func (s *ClusterStateService) Do(ctx context.Context) (*ClusterStateResponse, error) {
	// Check pre-conditions
	if err := s.Validate(); err != nil {
		return nil, err
	}

	// Get URL for request
	path, params, err := s.buildURL()
	if err != nil {
		return nil, err
	}

	// Get HTTP response
	res, err := s.client.PerformRequest(ctx, PerformRequestOptions{
		Method: "GET",
		Path:   path,
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	// Return operation response
	ret := new(ClusterStateResponse)
	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
		return nil, err
	}
	return ret, nil
}

// ClusterStateResponse is the response of ClusterStateService.Do.
type ClusterStateResponse struct {
	ClusterName  string                               `json:"cluster_name"`
	Version      int64                                `json:"version"`
	StateUUID    string                               `json:"state_uuid"`
	MasterNode   string                               `json:"master_node"`
	Blocks       map[string]*clusterBlocks            `json:"blocks"`
	Nodes        map[string]*discoveryNode            `json:"nodes"`
	Metadata     *clusterStateMetadata                `json:"metadata"`
	RoutingTable map[string]*clusterStateRoutingTable `json:"routing_table"`
	RoutingNodes *clusterStateRoutingNode             `json:"routing_nodes"`
	Customs      map[string]interface{}               `json:"customs"`
}

type clusterBlocks struct {
	Global  map[string]*clusterBlock `json:"global"`  // id -> cluster block
	Indices map[string]*clusterBlock `json:"indices"` // index name -> cluster block
}

type clusterBlock struct {
	Description             string   `json:"description"`
	Retryable               bool     `json:"retryable"`
	DisableStatePersistence bool     `json:"disable_state_persistence"`
	Levels                  []string `json:"levels"`
}

type clusterStateMetadata struct {
	ClusterUUID  string                            `json:"cluster_uuid"`
	Templates    map[string]*indexTemplateMetaData `json:"templates"` // template name -> index template metadata
	Indices      map[string]*indexMetaData         `json:"indices"`   // index name _> meta data
	RoutingTable struct {
		Indices map[string]*indexRoutingTable `json:"indices"` // index name -> routing table
	} `json:"routing_table"`
	RoutingNodes struct {
		Unassigned []*shardRouting `json:"unassigned"`
		Nodes      []*shardRouting `json:"nodes"`
	} `json:"routing_nodes"`
	Customs map[string]interface{} `json:"customs"`
}

type discoveryNode struct {
	Name             string                 `json:"name"`              // server name, e.g. "es1"
	TransportAddress string                 `json:"transport_address"` // e.g. inet[/1.2.3.4:9300]
	Attributes       map[string]interface{} `json:"attributes"`        // e.g. { "data": true, "master": true }
}

type clusterStateRoutingTable struct {
	Indices map[string]interface{} `json:"indices"`
}

type clusterStateRoutingNode struct {
	Unassigned []*shardRouting `json:"unassigned"`
	// Node Id -> shardRouting
	Nodes map[string][]*shardRouting `json:"nodes"`
}

type indexTemplateMetaData struct {
	IndexPatterns []string               `json:"index_patterns"` // e.g. ["store-*"]
	Order         int                    `json:"order"`
	Settings      map[string]interface{} `json:"settings"` // index settings
	Mappings      map[string]interface{} `json:"mappings"` // type name -> mapping
}

type indexMetaData struct {
	State    string                 `json:"state"`
	Settings map[string]interface{} `json:"settings"`
	Mappings map[string]interface{} `json:"mappings"`
	Aliases  []string               `json:"aliases"` // e.g. [ "alias1", "alias2" ]
}

type indexRoutingTable struct {
	Shards map[string]*shardRouting `json:"shards"`
}

type shardRouting struct {
	State          string          `json:"state"`
	Primary        bool            `json:"primary"`
	Node           string          `json:"node"`
	RelocatingNode string          `json:"relocating_node"`
	Shard          int             `json:"shard"`
	Index          string          `json:"index"`
	Version        int64           `json:"version"`
	RestoreSource  *RestoreSource  `json:"restore_source"`
	AllocationId   *allocationId   `json:"allocation_id"`
	UnassignedInfo *unassignedInfo `json:"unassigned_info"`
}

type RestoreSource struct {
	Repository string `json:"repository"`
	Snapshot   string `json:"snapshot"`
	Version    string `json:"version"`
	Index      string `json:"index"`
}

type allocationId struct {
	Id           string `json:"id"`
	RelocationId string `json:"relocation_id"`
}

type unassignedInfo struct {
	Reason  string `json:"reason"`
	At      string `json:"at"`
	Details string `json:"details"`
}
<commit_msg>Fix routing_table structure in Cluster State API<commit_after>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

import (
	"context"
	"fmt"
	"net/url"
	"strings"

	"github.com/olivere/elastic/uritemplates"
)

// ClusterStateService allows to get a comprehensive state information of the whole cluster.
//
// See https://www.elastic.co/guide/en/elasticsearch/reference/6.2/cluster-state.html
// for details.
type ClusterStateService struct {
	client            *Client
	pretty            bool
	indices           []string
	metrics           []string
	allowNoIndices    *bool
	expandWildcards   string
	flatSettings      *bool
	ignoreUnavailable *bool
	local             *bool
	masterTimeout     string
}

// NewClusterStateService creates a new ClusterStateService.
func NewClusterStateService(client *Client) *ClusterStateService {
	return &ClusterStateService{
		client:  client,
		indices: make([]string, 0),
		metrics: make([]string, 0),
	}
}

// Index is a list of index names. Use _all or an empty string to
// perform the operation on all indices.
func (s *ClusterStateService) Index(indices ...string) *ClusterStateService {
	s.indices = append(s.indices, indices...)
	return s
}

// Metric limits the information returned to the specified metric.
// It can be one of: version, master_node, nodes, routing_table, metadata,
// blocks, or customs.
func (s *ClusterStateService) Metric(metrics ...string) *ClusterStateService {
	s.metrics = append(s.metrics, metrics...)
	return s
}

// AllowNoIndices indicates whether to ignore if a wildcard indices
// expression resolves into no concrete indices.
// (This includes `_all` string or when no indices have been specified).
func (s *ClusterStateService) AllowNoIndices(allowNoIndices bool) *ClusterStateService {
	s.allowNoIndices = &allowNoIndices
	return s
}

// ExpandWildcards indicates whether to expand wildcard expression to
// concrete indices that are open, closed or both..
func (s *ClusterStateService) ExpandWildcards(expandWildcards string) *ClusterStateService {
	s.expandWildcards = expandWildcards
	return s
}

// FlatSettings, when set, returns settings in flat format (default: false).
func (s *ClusterStateService) FlatSettings(flatSettings bool) *ClusterStateService {
	s.flatSettings = &flatSettings
	return s
}

// IgnoreUnavailable indicates whether specified concrete indices should be
// ignored when unavailable (missing or closed).
func (s *ClusterStateService) IgnoreUnavailable(ignoreUnavailable bool) *ClusterStateService {
	s.ignoreUnavailable = &ignoreUnavailable
	return s
}

// Local indicates whether to return local information. When set, it does not
// retrieve the state from master node (default: false).
func (s *ClusterStateService) Local(local bool) *ClusterStateService {
	s.local = &local
	return s
}

// MasterTimeout specifies timeout for connection to master.
func (s *ClusterStateService) MasterTimeout(masterTimeout string) *ClusterStateService {
	s.masterTimeout = masterTimeout
	return s
}

// Pretty indicates that the JSON response be indented and human readable.
func (s *ClusterStateService) Pretty(pretty bool) *ClusterStateService {
	s.pretty = pretty
	return s
}

// buildURL builds the URL for the operation.
func (s *ClusterStateService) buildURL() (string, url.Values, error) {
	// Build URL
	metrics := strings.Join(s.metrics, ",")
	if metrics == "" {
		metrics = "_all"
	}
	indices := strings.Join(s.indices, ",")
	if indices == "" {
		indices = "_all"
	}
	path, err := uritemplates.Expand("/_cluster/state/{metrics}/{indices}", map[string]string{
		"metrics": metrics,
		"indices": indices,
	})
	if err != nil {
		return "", url.Values{}, err
	}

	// Add query string parameters
	params := url.Values{}
	if s.pretty {
		params.Set("pretty", "true")
	}
	if s.allowNoIndices != nil {
		params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices))
	}
	if s.expandWildcards != "" {
		params.Set("expand_wildcards", s.expandWildcards)
	}
	if s.flatSettings != nil {
		params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings))
	}
	if s.ignoreUnavailable != nil {
		params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable))
	}
	if s.local != nil {
		params.Set("local", fmt.Sprintf("%v", *s.local))
	}
	if s.masterTimeout != "" {
		params.Set("master_timeout", s.masterTimeout)
	}
	return path, params, nil
}

// Validate checks if the operation is valid.
func (s *ClusterStateService) Validate() error {
	return nil
}

// Do executes the operation.
func (s *ClusterStateService) Do(ctx context.Context) (*ClusterStateResponse, error) {
	// Check pre-conditions
	if err := s.Validate(); err != nil {
		return nil, err
	}

	// Get URL for request
	path, params, err := s.buildURL()
	if err != nil {
		return nil, err
	}

	// Get HTTP response
	res, err := s.client.PerformRequest(ctx, PerformRequestOptions{
		Method: "GET",
		Path:   path,
		Params: params,
	})
	if err != nil {
		return nil, err
	}

	// Return operation response
	ret := new(ClusterStateResponse)
	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
		return nil, err
	}
	return ret, nil
}

// ClusterStateResponse is the response of ClusterStateService.Do.
type ClusterStateResponse struct {
	ClusterName  string                    `json:"cluster_name"`
	Version      int64                     `json:"version"`
	StateUUID    string                    `json:"state_uuid"`
	MasterNode   string                    `json:"master_node"`
	Blocks       map[string]*clusterBlocks `json:"blocks"`
	Nodes        map[string]*discoveryNode `json:"nodes"`
	Metadata     *clusterStateMetadata     `json:"metadata"`
	RoutingTable *clusterStateRoutingTable `json:"routing_table"`
	RoutingNodes *clusterStateRoutingNode  `json:"routing_nodes"`
	Customs      map[string]interface{}    `json:"customs"`
}

type clusterBlocks struct {
	Global  map[string]*clusterBlock `json:"global"`  // id -> cluster block
	Indices map[string]*clusterBlock `json:"indices"` // index name -> cluster block
}

type clusterBlock struct {
	Description             string   `json:"description"`
	Retryable               bool     `json:"retryable"`
	DisableStatePersistence bool     `json:"disable_state_persistence"`
	Levels                  []string `json:"levels"`
}

type clusterStateMetadata struct {
	ClusterUUID  string                            `json:"cluster_uuid"`
	Templates    map[string]*indexTemplateMetaData `json:"templates"` // template name -> index template metadata
	Indices      map[string]*indexMetaData         `json:"indices"`   // index name _> meta data
	RoutingTable struct {
		Indices map[string]*indexRoutingTable `json:"indices"` // index name -> routing table
	} `json:"routing_table"`
	RoutingNodes struct {
		Unassigned []*shardRouting `json:"unassigned"`
		Nodes      []*shardRouting `json:"nodes"`
	} `json:"routing_nodes"`
	Customs map[string]interface{} `json:"customs"`
}

type discoveryNode struct {
	Name             string                 `json:"name"`              // server name, e.g. "es1"
	TransportAddress string                 `json:"transport_address"` // e.g. inet[/1.2.3.4:9300]
	Attributes       map[string]interface{} `json:"attributes"`        // e.g. { "data": true, "master": true }
}

type clusterStateRoutingTable struct {
	Indices map[string]interface{} `json:"indices"`
}

type clusterStateRoutingNode struct {
	Unassigned []*shardRouting `json:"unassigned"`
	// Node Id -> shardRouting
	Nodes map[string][]*shardRouting `json:"nodes"`
}

type indexTemplateMetaData struct {
	IndexPatterns []string               `json:"index_patterns"` // e.g. ["store-*"]
	Order         int                    `json:"order"`
	Settings      map[string]interface{} `json:"settings"` // index settings
	Mappings      map[string]interface{} `json:"mappings"` // type name -> mapping
}

type indexMetaData struct {
	State    string                 `json:"state"`
	Settings map[string]interface{} `json:"settings"`
	Mappings map[string]interface{} `json:"mappings"`
	Aliases  []string               `json:"aliases"` // e.g. [ "alias1", "alias2" ]
}

type indexRoutingTable struct {
	Shards map[string]*shardRouting `json:"shards"`
}

type shardRouting struct {
	State          string          `json:"state"`
	Primary        bool            `json:"primary"`
	Node           string          `json:"node"`
	RelocatingNode string          `json:"relocating_node"`
	Shard          int             `json:"shard"`
	Index          string          `json:"index"`
	Version        int64           `json:"version"`
	RestoreSource  *RestoreSource  `json:"restore_source"`
	AllocationId   *allocationId   `json:"allocation_id"`
	UnassignedInfo *unassignedInfo `json:"unassigned_info"`
}

type RestoreSource struct {
	Repository string `json:"repository"`
	Snapshot   string `json:"snapshot"`
	Version    string `json:"version"`
	Index      string `json:"index"`
}

type allocationId struct {
	Id           string `json:"id"`
	RelocationId string `json:"relocation_id"`
}

type unassignedInfo struct {
	Reason  string `json:"reason"`
	At      string `json:"at"`
	Details string `json:"details"`
}
<|endoftext|>


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

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/casaplatform/casa/cmd/casa/cmd"
	"github.com/casaplatform/casa/cmd/casa/environment"

	// These imports are to enable these "plugins". This will change once
	// plugin support is released for Go.
	_ "github.com/casaplatform/hue"
	_ "github.com/casaplatform/logger"
	_ "github.com/casaplatform/storage"

	"github.com/pkg/errors"
)

func main() {
	// Defer printing of the error, and avoid using log.Fatal or os.Exit
	// in order to allow any other deferred function to run.
	// See https://goo.gl/BLKYGv
	env := environment.Env
	env.WithOptions(environment.WithLogger(new(logLogger)))
	var err error
	defer func() {
		if err != nil {
			// Print out a stack trace
			if err, ok := err.(stackTracer); ok {
				env.Log("Casa has failed. Stack trace:")
				for _, f := range err.StackTrace() {
					fmt.Printf("%+s:%d", f, f)
				}
				os.Exit(1)
			} else {
				env.Log(err)
			}
		}
		// Do other stuff to shutdown
	}()
	err = cmd.RootCmd.Execute()
}

type stackTracer interface {
	StackTrace() errors.StackTrace
}

// A simple casa.Logger that uses std lib log package
type logLogger struct{}

func (f logLogger) Log(a ...interface{}) {
	log.Println(a...)
}
<commit_msg>Add new default services<commit_after>// Copyright © 2016 Casa Platform
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/pkg/errors"

	"github.com/casaplatform/casa/cmd/casa/cmd"
	"github.com/casaplatform/casa/cmd/casa/environment"

	// These imports are to enable these "plugins". This will change once
	// plugin support is released for Go.
	_ "github.com/casaplatform/daytime"
	_ "github.com/casaplatform/hue"
	_ "github.com/casaplatform/logger"
	_ "github.com/casaplatform/rules"
	_ "github.com/casaplatform/storage"
)

func main() {
	// Defer printing of the error, and avoid using log.Fatal or os.Exit
	// in order to allow any other deferred function to run.
	// See https://goo.gl/BLKYGv
	env := environment.Env
	env.WithOptions(environment.WithLogger(new(logLogger)))
	var err error
	defer func() {
		if err != nil {
			// Print out a stack trace
			if err, ok := err.(stackTracer); ok {
				env.Log("Casa has failed. Stack trace:")
				for _, f := range err.StackTrace() {
					fmt.Printf("%+s:%d", f, f)
				}
				os.Exit(1)
			} else {
				env.Log(err)
			}
		}
		// Do other stuff to shutdown
	}()
	err = cmd.RootCmd.Execute()
}

type stackTracer interface {
	StackTrace() errors.StackTrace
}

// A simple casa.Logger that uses std lib log package
type logLogger struct{}

func (f logLogger) Log(a ...interface{}) {
	log.Println(a...)
}
<|endoftext|>