<commit_before>package cmd

import (
	"fmt"
	"os"
	"os/exec"

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

// depsCmd represents the deps command
var depsCmd = &cobra.Command{
	Use:   "deps",
	Short: "Download and optionally update all abcweb dependencies",
	Long: `Download and optionally update all abcweb dependencies used by
your generated app or the abcweb tool by executing "go get" commands`,
	Example: "abcweb deps -u",
	// Needs to be a persistentPreRunE to override root's config.Initialize call
	// otherwise abcweb needs to be run from the abcweb project or the git rev-parse
	// will cause a fatal error.
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		viper.BindPFlags(cmd.Flags())
		return nil
	},
	RunE: depsCmdRun,
}

func init() {
	depsCmd.Flags().BoolP("update", "u", false, "Also update already installed dependencies")
	depsCmd.Flags().BoolP("verbose", "v", false, "Very noisy verbose output")
	depsCmd.Flags().BoolP("assets-only", "a", false, "Only install gulp.js dependencies")
	depsCmd.Flags().BoolP("go-only", "g", false, "Only install Go dependencies")

	RootCmd.AddCommand(depsCmd)
}

func depsCmdRun(cmd *cobra.Command, args []string) error {
	var err error

	goGetArgs := [][]string{
		{"go.uber.org/zap"},
		{"github.com/pkg/errors"},
		{"github.com/volatiletech/helpers/..."},
		{"github.com/pressly/chi/..."},
		{"github.com/goware/cors"},
		{"github.com/unrolled/render"},
		{"github.com/volatiletech/mig/..."},
		{"github.com/spf13/pflag"},
		{"github.com/spf13/cobra"},
		{"github.com/spf13/viper"},
		{"github.com/markbates/refresh"},
		{"gopkg.in/nullbio/null.v6"},
		{"-t", "github.com/vattle/sqlboiler"},
	}

	npmInstallArgs := [][]string{
		{"gulpjs/gulp.git#4.0"},
	}

	prependArgs := []string{"get"}
	if viper.GetBool("update") {
		prependArgs = append(prependArgs, "-u")
	}
	if viper.GetBool("verbose") {
		prependArgs = append(prependArgs, "-v")
	}

	for i := 0; i < len(goGetArgs); i++ {
		goGetArgs[i] = append(prependArgs, goGetArgs[i]...)
	}

	if !viper.GetBool("go-only") {
		prependArgs = []string{"install", "--global"}
		if viper.GetBool("verbose") {
			prependArgs = append(prependArgs, "--verbose")
		}

		for i := 0; i < len(npmInstallArgs); i++ {
			npmInstallArgs[i] = append(prependArgs, npmInstallArgs[i]...)
		}

		fmt.Printf("Retrieving all Nodejs dependencies using \"npm install --global\":\n\n")

		_, err = exec.LookPath("npm")
		if err != nil {
			fmt.Printf(`Error: npm could not be found in your $PATH. If you have not already installed nodejs
and npm you must do so before proceeding. Please follow the instructions at:
https://docs.npmjs.com/getting-started/installing-node

If you receive permission related errors, please apply the following fix:
https://docs.npmjs.com/getting-started/fixing-npm-permissions
`)
			os.Exit(1)
		}

		for _, npmInstallArg := range npmInstallArgs {
			fmt.Printf("%s ... ", npmInstallArg[len(npmInstallArg)-1])

			exc := exec.Command("npm", npmInstallArg...)
			out, err := exc.CombinedOutput()

			if err != nil {
				fmt.Printf("ERROR\n\n")
			} else {
				fmt.Printf("SUCCESS\n\n")
			}

			if len(out) > 0 {
				fmt.Print(string(out))
			}

			if err != nil {
				fmt.Printf("%s\n\n", err)
				fmt.Printf(`Note: If you are receiving a permission related exit status or error, please apply the following fix:
https://docs.npmjs.com/getting-started/fixing-npm-permissions
`)
				os.Exit(1)
			}
		}
	}

	if !viper.GetBool("assets-only") {
		fmt.Printf("\nRetrieving all Go dependencies using \"go get\":\n\n")

		for _, goGetArg := range goGetArgs {
			fmt.Printf("%s ... ", goGetArg[len(goGetArg)-1])

			exc := exec.Command("go", goGetArg...)
			out, err := exc.CombinedOutput()

			if err != nil {
				fmt.Printf("ERROR\n\n")
			} else {
				fmt.Printf("SUCCESS\n")
			}

			if len(out) > 0 {
				fmt.Print(string(out))
			}

			if err != nil {
				fmt.Printf("%s\n\n", err)
				os.Exit(1)
			}
		}
	}

	fmt.Printf("\nAll dependencies successfully installed.\n\n")

	return err
}
<commit_msg>Fix missing deps<commit_after>package cmd

import (
	"fmt"
	"os"
	"os/exec"

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

// depsCmd represents the deps command
var depsCmd = &cobra.Command{
	Use:   "deps",
	Short: "Download and optionally update all abcweb dependencies",
	Long: `Download and optionally update all abcweb dependencies used by
your generated app or the abcweb tool by executing "go get" commands`,
	Example: "abcweb deps -u",
	// Needs to be a persistentPreRunE to override root's config.Initialize call
	// otherwise abcweb needs to be run from the abcweb project or the git rev-parse
	// will cause a fatal error.
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		viper.BindPFlags(cmd.Flags())
		return nil
	},
	RunE: depsCmdRun,
}

func init() {
	depsCmd.Flags().BoolP("update", "u", false, "Also update already installed dependencies")
	depsCmd.Flags().BoolP("verbose", "v", false, "Very noisy verbose output")
	depsCmd.Flags().BoolP("assets-only", "a", false, "Only install gulp.js dependencies")
	depsCmd.Flags().BoolP("go-only", "g", false, "Only install Go dependencies")

	RootCmd.AddCommand(depsCmd)
}

func depsCmdRun(cmd *cobra.Command, args []string) error {
	var err error

	goGetArgs := [][]string{
		{"go.uber.org/zap"},
		{"github.com/pkg/errors"},
		{"github.com/volatiletech/helpers/..."},
		{"github.com/pressly/chi/..."},
		{"github.com/goware/cors"},
		{"github.com/unrolled/render"},
		{"github.com/volatiletech/mig/..."},
		{"github.com/spf13/pflag"},
		{"github.com/spf13/cobra"},
		{"github.com/spf13/viper"},
		{"github.com/markbates/refresh"},
		{"gopkg.in/nullbio/null.v6"},
		{"github.com/djherbis/times"},
		{"github.com/satori/go.uuid"},
		{"gopkg.in/redis.v5"},
		{"-t", "github.com/vattle/sqlboiler"},
	}

	npmInstallArgs := [][]string{
		{"gulpjs/gulp.git#4.0"},
	}

	prependArgs := []string{"get"}
	if viper.GetBool("update") {
		prependArgs = append(prependArgs, "-u")
	}
	if viper.GetBool("verbose") {
		prependArgs = append(prependArgs, "-v")
	}

	for i := 0; i < len(goGetArgs); i++ {
		goGetArgs[i] = append(prependArgs, goGetArgs[i]...)
	}

	if !viper.GetBool("go-only") {
		prependArgs = []string{"install", "--global"}
		if viper.GetBool("verbose") {
			prependArgs = append(prependArgs, "--verbose")
		}

		for i := 0; i < len(npmInstallArgs); i++ {
			npmInstallArgs[i] = append(prependArgs, npmInstallArgs[i]...)
		}

		fmt.Printf("Retrieving all Nodejs dependencies using \"npm install --global\":\n\n")

		_, err = exec.LookPath("npm")
		if err != nil {
			fmt.Printf(`Error: npm could not be found in your $PATH. If you have not already installed nodejs
and npm you must do so before proceeding. Please follow the instructions at:
https://docs.npmjs.com/getting-started/installing-node

If you receive permission related errors, please apply the following fix:
https://docs.npmjs.com/getting-started/fixing-npm-permissions
`)
			os.Exit(1)
		}

		for _, npmInstallArg := range npmInstallArgs {
			fmt.Printf("%s ... ", npmInstallArg[len(npmInstallArg)-1])

			exc := exec.Command("npm", npmInstallArg...)
			out, err := exc.CombinedOutput()

			if err != nil {
				fmt.Printf("ERROR\n\n")
			} else {
				fmt.Printf("SUCCESS\n\n")
			}

			if len(out) > 0 {
				fmt.Print(string(out))
			}

			if err != nil {
				fmt.Printf("%s\n\n", err)
				fmt.Printf(`Note: If you are receiving a permission related exit status or error, please apply the following fix:
https://docs.npmjs.com/getting-started/fixing-npm-permissions
`)
				os.Exit(1)
			}
		}
	}

	if !viper.GetBool("assets-only") {
		fmt.Printf("\nRetrieving all Go dependencies using \"go get\":\n\n")

		for _, goGetArg := range goGetArgs {
			fmt.Printf("%s ... ", goGetArg[len(goGetArg)-1])

			exc := exec.Command("go", goGetArg...)
			out, err := exc.CombinedOutput()

			if err != nil {
				fmt.Printf("ERROR\n\n")
			} else {
				fmt.Printf("SUCCESS\n")
			}

			if len(out) > 0 {
				fmt.Print(string(out))
			}

			if err != nil {
				fmt.Printf("%s\n\n", err)
				os.Exit(1)
			}
		}
	}

	fmt.Printf("\nAll dependencies successfully installed.\n\n")

	return err
}
<|endoftext|>


<commit_before>package cmd

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

	"github.com/spf13/cobra"
	"github.com/voidint/gbb/config"
)

var initCmd = &cobra.Command{
	Use:   "init",
	Short: "Help you to creating gbb.json step by step.",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		genConfigFile(confFile)
	},
}

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

func genConfigFile(destFilename string) {
	c := gather()

	b, _ := json.MarshalIndent(c, "", "    ")
	fmt.Printf("About to write to %s:\n\n%s\n\nIs this ok?[y/n] ", destFilename, string(b))
	var ok string
	fmt.Scanln(&ok)
	if ok = strings.ToLower(ok); ok == "y" {
		config.Save(c, confFile)
	}
}

func gather() *config.Config {
	fmt.Println(`This utility will walk you through creating a gbb.json file.
It only covers the most common items, and tries to guess sensible defaults.`)
	fmt.Printf("\nPress ^C at any time to quit.\n")

	c := config.Config{
		Version: Version,
		Tool:    gatherOne("tool", "go_install"),
		Package: gatherOne("package", "main"),
	}
	for {
		c.Variables = append(c.Variables, *gatherOneVar())

		var sContinue string
		fmt.Print("Do you want to continue?[y/n] ")
		fmt.Scanln(&sContinue)
		if sContinue = strings.ToLower(sContinue); sContinue == "n" {
			break
		}
	}
	return &c
}

func gatherOneVar() (v *config.Variable) {
	return &config.Variable{
		Variable: gatherOne("variable", ""),
		Value:    gatherOne("value", ""),
	}
}

func gatherOne(prompt, defaultVal string) (input string) {
	for {
		if defaultVal != "" {
			fmt.Printf("%s: (%s) ", prompt, defaultVal)
		} else {
			fmt.Printf("%s: ", prompt)
		}
		fmt.Scanln(&input) // TODO bug: 无法获取到包含空格的全部输入，如go build
		if input = strings.TrimSpace(input); input == "" {
			if defaultVal == "" {
				continue
			}
			return strings.Replace(defaultVal, "_", " ", -1)
		}
		return strings.Replace(input, "_", " ", -1) // TODO 临时举措，还原实际的空格。如，go_build ==> go build
	}
}
<commit_msg>gbb init生成gbb.json时，配置项package和variables由必选项改为可选项。<commit_after>package cmd

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

	"github.com/spf13/cobra"
	"github.com/voidint/gbb/config"
)

var initCmd = &cobra.Command{
	Use:   "init",
	Short: "Help you to creating gbb.json step by step.",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		genConfigFile(confFile)
	},
}

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

func genConfigFile(destFilename string) {
	c := gather()

	b, _ := json.MarshalIndent(c, "", "    ")
	fmt.Printf("About to write to %s:\n\n%s\n\nIs this ok?[y/n] ", destFilename, string(b))
	var ok string
	fmt.Scanln(&ok)
	if ok = strings.ToLower(ok); ok == "y" {
		config.Save(c, confFile)
	}
}

func gather() (c *config.Config) {
	fmt.Println(`This utility will walk you through creating a gbb.json file.
It only covers the most common items, and tries to guess sensible defaults.`)
	fmt.Printf("\nPress ^C at any time to quit.\n")

	c = new(config.Config)
	// required
	c.Version = Version
	c.Tool = gatherOne("tool", "go_install")

	var sContinue string
	fmt.Print("Do you want to continue?[y/n] ")
	fmt.Scanln(&sContinue)
	if sContinue = strings.ToLower(sContinue); sContinue == "n" {
		return c
	}

	// optional
	c.Package = gatherOne("package", "main")
	for {
		c.Variables = append(c.Variables, *gatherOneVar())

		fmt.Print("Do you want to continue?[y/n] ")
		fmt.Scanln(&sContinue)
		if sContinue = strings.ToLower(sContinue); sContinue == "n" {
			break
		}
	}
	return c
}

func gatherOneVar() (v *config.Variable) {
	return &config.Variable{
		Variable: gatherOne("variable", ""),
		Value:    gatherOne("value", ""),
	}
}

func gatherOne(prompt, defaultVal string) (input string) {
	for {
		if defaultVal != "" {
			fmt.Printf("%s: (%s) ", prompt, defaultVal)
		} else {
			fmt.Printf("%s: ", prompt)
		}
		fmt.Scanln(&input) // TODO bug: 无法获取到包含空格的全部输入，如go build
		if input = strings.TrimSpace(input); input == "" {
			if defaultVal == "" {
				continue
			}
			return strings.Replace(defaultVal, "_", " ", -1)
		}
		return strings.Replace(input, "_", " ", -1) // TODO 临时举措，还原实际的空格。如，go_build ==> go build
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"github.com/zalando-incubator/postgres-operator/pkg/controller"
	"github.com/zalando-incubator/postgres-operator/pkg/spec"
	"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil"
)

var (
	kubeConfigFile string
	outOfCluster   bool
	version        string
	config         spec.ControllerConfig
)

func init() {
	flag.StringVar(&kubeConfigFile, "kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")
	flag.BoolVar(&outOfCluster, "outofcluster", false, "Whether the operator runs in- our outside of the Kubernetes cluster.")
	flag.BoolVar(&config.NoDatabaseAccess, "nodatabaseaccess", false, "Disable all access to the database from the operator side.")
	flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API")
	flag.Parse()

	operatorNamespaceBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
	if err != nil {
		log.Fatalf("Unable to detect operator namespace from within its pod  due to %v", err)
	}

	configMapRawName := os.Getenv("CONFIG_MAP_NAME")
	if configMapRawName != "" {

		operatorNamespace := string(operatorNamespaceBytes)
		config.Namespace = operatorNamespace

		namespacedConfigMapName := operatorNamespace + "/" + configMapRawName

		log.Printf("Looking for the operator configmap at the same namespace the operator resides. Fully qualified configmap name: %v", namespacedConfigMapName)

		err := config.ConfigMapName.Decode(namespacedConfigMapName)
		if err != nil {
			log.Fatalf("incorrect config map name: %v", namespacedConfigMapName)
		}

	}

}

func main() {
	var err error

	log.SetOutput(os.Stdout)
	log.Printf("Spilo operator %s\n", version)

	sigs := make(chan os.Signal, 1)
	stop := make(chan struct{})
	signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) // Push signals into channel

	wg := &sync.WaitGroup{} // Goroutines can add themselves to this to be waited on

	config.RestConfig, err = k8sutil.RestConfig(kubeConfigFile, outOfCluster)
	if err != nil {
		log.Fatalf("couldn't get REST config: %v", err)
	}

	c := controller.NewController(&config)

	c.Run(stop, wg)

	sig := <-sigs
	log.Printf("Shutting down... %+v", sig)

	close(stop) // Tell goroutines to stop themselves
	wg.Wait()   // Wait for all to be stopped
}
<commit_msg>Add the fileWithNamespace const<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"github.com/zalando-incubator/postgres-operator/pkg/controller"
	"github.com/zalando-incubator/postgres-operator/pkg/spec"
	"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil"
)

const (
	// assumes serviceaccount secret is mounted by kubernetes
	fileWithNamespace = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
)

var (
	kubeConfigFile string
	outOfCluster   bool
	version        string
	config         spec.ControllerConfig
)

func init() {
	flag.StringVar(&kubeConfigFile, "kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")
	flag.BoolVar(&outOfCluster, "outofcluster", false, "Whether the operator runs in- our outside of the Kubernetes cluster.")
	flag.BoolVar(&config.NoDatabaseAccess, "nodatabaseaccess", false, "Disable all access to the database from the operator side.")
	flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API")
	flag.Parse()

	operatorNamespaceBytes, err := ioutil.ReadFile(fileWithNamespace)
	if err != nil {
		log.Fatalf("Unable to detect operator namespace from within its pod  due to %v", err)
	}

	configMapRawName := os.Getenv("CONFIG_MAP_NAME")
	if configMapRawName != "" {

		operatorNamespace := string(operatorNamespaceBytes)
		config.Namespace = operatorNamespace

		namespacedConfigMapName := operatorNamespace + "/" + configMapRawName

		log.Printf("Looking for the operator configmap at the same namespace the operator resides. Fully qualified configmap name: %v", namespacedConfigMapName)

		err := config.ConfigMapName.Decode(namespacedConfigMapName)
		if err != nil {
			log.Fatalf("incorrect config map name: %v", namespacedConfigMapName)
		}

	}

}

func main() {
	var err error

	log.SetOutput(os.Stdout)
	log.Printf("Spilo operator %s\n", version)

	sigs := make(chan os.Signal, 1)
	stop := make(chan struct{})
	signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) // Push signals into channel

	wg := &sync.WaitGroup{} // Goroutines can add themselves to this to be waited on

	config.RestConfig, err = k8sutil.RestConfig(kubeConfigFile, outOfCluster)
	if err != nil {
		log.Fatalf("couldn't get REST config: %v", err)
	}

	c := controller.NewController(&config)

	c.Run(stop, wg)

	sig := <-sigs
	log.Printf("Shutting down... %+v", sig)

	close(stop) // Tell goroutines to stop themselves
	wg.Wait()   // Wait for all to be stopped
}
<|endoftext|>


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

// +build !windows,!darwin

package cmd

import (
	"fmt"
	"strings"

	"github.com/tsuru/tsuru/exec"
	"golang.org/x/sys/unix"
)

func isWSL() bool {
	var u unix.Utsname
	err := unix.Uname(&u)
	if err != nil {
		fmt.Println(err)
		return false
	}
	release := strings.ToLower(string(u.Release[:]))
	return strings.Contains(release, "microsoft")
}

func open(url string) error {

	cmd := "xdg-open"
	args := []string{url}

	if isWSL() {
		cmd = "powershell.exe"
		args = []string{"-c", "start", "'"+url+"'"}
	}

	opts := exec.ExecuteOptions{
		Cmd:  cmd,
		Args: args,
	}
	return executor().Execute(opts)
}
<commit_msg>cmd: format code with gofmt<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !windows,!darwin

package cmd

import (
	"fmt"
	"strings"

	"github.com/tsuru/tsuru/exec"
	"golang.org/x/sys/unix"
)

func isWSL() bool {
	var u unix.Utsname
	err := unix.Uname(&u)
	if err != nil {
		fmt.Println(err)
		return false
	}
	release := strings.ToLower(string(u.Release[:]))
	return strings.Contains(release, "microsoft")
}

func open(url string) error {

	cmd := "xdg-open"
	args := []string{url}

	if isWSL() {
		cmd = "powershell.exe"
		args = []string{"-c", "start", "'" + url + "'"}
	}

	opts := exec.ExecuteOptions{
		Cmd:  cmd,
		Args: args,
	}
	return executor().Execute(opts)
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"log"
	"math"
	"sort"
	"time"

	"github.com/phil-mansfield/shellfish/los/geom"
	"github.com/phil-mansfield/shellfish/los/analyze"
	"github.com/phil-mansfield/shellfish/cmd/catalog"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/logging"
	"github.com/phil-mansfield/shellfish/parse"
	"github.com/phil-mansfield/shellfish/io"
	"github.com/phil-mansfield/shellfish/cmd/memo"
)

type ProfConfig struct {
	bins, order, samples int64
	rMaxMult, rMinMult float64

	pType profileType

}

type profileType int
const (
	densityProfile profileType = iota
	containedDensityProfile
	angularFractionProfile
)

var _ Mode = &ProfConfig{}

func (config *ProfConfig) ExampleConfig() string {
	return `[prof.config]

#####################
## Required Fields ##
#####################

# ProfileType determines what type of profile will be output.
# Known profile types are:
# density -          the traditional spherical densiy profile that we all
                     know and love.
# contained-densiy - a density profile which only uses particles.
# angular-fraction - the angular fraction at each radius which is contained
                     within the shell.
ProfileType = density

# Order is the order of the Penna-Dines shell fit that Shellfish uses. This
# variable only needs to be set if ProfileType is set to contained-density
# or angular-fraction.
# Order = 3

# Samples is the number of Monte Carlo samples used when calculating angular
# fraction profiles. It does not need to be set when other profiles are
# calculated.
# Samples = 50000

#####################
## Optional Fields ##
#####################

# Bins is the number of logarithmic radial bins used in a profile.
# Bins = 150

# RMaxMult is the maximum radius of the profile as a function of R_200m.
# RMaxMult = 3

# RMinMult is the minimum radius of the profile as a function of R_200m.
# RMinMult = 0.03
`
}

func (config *ProfConfig) ReadConfig(fname string) error {
	if fname == "" {
		return nil
	}

	vars := parse.NewConfigVars("prof.config")

	vars.Int(&config.bins, "Bins", 150)
	vars.Int(&config.order, "Order", 3)
	vars.Int(&config.samples, "Samples", 50 * 1000)
	vars.Float(&config.rMaxMult, "RMaxMult", 3.0)
	vars.Float(&config.rMinMult, "RMinMult", 0.03)
	var pType string
	vars.String(&pType, "ProfileType", "")

	if err := parse.ReadConfig(fname, vars); err != nil {
		return err
	}

	switch pType {
	case "":
		return fmt.Errorf("The variable 'ProfileType' was not set.")
	case "density":
		config.pType = densityProfile
	case "contained-density":
		config.pType = containedDensityProfile
	case "angular-fraction":
		config.pType = angularFractionProfile
	default:
		return fmt.Errorf("The varaiable 'ProfileType' was set to '%s'.", pType)
	}

	return config.validate()
}

func (config *ProfConfig) validate() error {
	if config.bins < 0 {
		return fmt.Errorf("The variable '%s' was set to %d.",
			"Bins", config.bins)
	} else if config.rMinMult <= 0 {
		return fmt.Errorf("The variable '%s' was set to %g.",
			"RMinMult", config.rMinMult)
	} else if config.rMaxMult <= 0 {
		return fmt.Errorf("The variable '%s' was set to %g.",
			"RMinMult", config.rMinMult)
	}
	return nil
}

func (config *ProfConfig) Run(
	flags []string, gConfig *GlobalConfig, e *env.Environment, stdin []string,
) ([]string, error) {
	if logging.Mode != logging.Nil {
		log.Println(`
####################
## shellfish tree ##
####################`,
		)
	}

	var t time.Time
	if logging.Mode == logging.Performance {
		t = time.Now()
	}

	var (
		intCols [][]int
		coords [][]float64
		shells []analyze.Shell
		err error
	)

	switch config.pType {
	case densityProfile:
		intColIdxs := []int{0, 1}
		floatColIdxs := []int{2, 3, 4, 5}

		intCols, coords, err = catalog.ParseCols(
			stdin, intColIdxs, floatColIdxs,
		)

		if err != nil {
			return nil, err
		}
	case containedDensityProfile, angularFractionProfile:
		intColIdxs := []int{0, 1}
		floatColIdxs := make([]int, 4 + config.order*config.order*2)
		for i := range floatColIdxs {
			floatColIdxs[i] += i + 2
		}

		var floatCols [][]float64
		intCols, floatCols, err = catalog.ParseCols(
			stdin, intColIdxs, floatColIdxs,
		)

		if err != nil {
			return nil, err
		}

		coords = floatCols[:4]
		coeffs := floatCols[4:]
		shells = make([]analyze.Shell, len(coords[0]))
		for i := range shells {
			coeffVec := make([]float64, len(coeffs))
			for j := range coeffVec {
				coeffVec[j] = coeffs[j][i]
			}
			order := int(config.order)
			shells[i] = analyze.PennaFunc(coeffVec, order, order, 2)
		}
	}

	if len(intCols) == 0 {
		return nil, fmt.Errorf("No input IDs.")
	}

	ids, snaps := intCols[0], intCols[1]
	snapBins, idxBins := binBySnap(snaps, ids)

	if config.pType == angularFractionProfile {
		return angularFractionMain(ids, snaps, shells, coords[3], config)
	}

	rSets := make([][]float64, len(ids))
	rhoSets := make([][]float64, len(ids))
	for i := range rSets {
		rSets[i] = make([]float64, config.bins)
		rhoSets[i] = make([]float64, config.bins)
	}

	sortedSnaps := []int{}
	for snap := range snapBins {
		sortedSnaps = append(sortedSnaps, snap)
	}
	sort.Ints(sortedSnaps)

	buf, err := getVectorBuffer(
		e.ParticleCatalog(snaps[0], 0),
		gConfig.SnapshotType, gConfig.Endianness,
	)
	if err != nil {
		return nil, err
	}

	for _, snap := range sortedSnaps {
		if snap == -1 {
			continue
		}

		idxs := idxBins[snap]
		snapCoords := [][]float64{
			make([]float64, len(idxs)), make([]float64, len(idxs)),
			make([]float64, len(idxs)), make([]float64, len(idxs)),
		}
		for i, idx := range idxs {
			snapCoords[0][i] = coords[0][idx]
			snapCoords[1][i] = coords[1][idx]
			snapCoords[2][i] = coords[2][idx]
			snapCoords[3][i] = coords[3][idx]
		}

		hds, files, err := memo.ReadHeaders(snap, buf, e)
		if err != nil {
			return nil, err
		}
		hBounds, err := boundingSpheres(snapCoords, &hds[0], e)
		if err != nil {
			return nil, err
		}
		_, intrIdxs := binSphereIntersections(hds, hBounds)

		for i := range hds {
			if len(intrIdxs[i]) == 0 {
				continue
			}

			xs, ms, _, err := buf.Read(files[i])
			if err != nil {
				return nil, err
			}

			// Waarrrgggble
			for _, j := range intrIdxs[i] {
				rhos := rhoSets[idxs[j]]
				s := hBounds[j]

				insertPoints(rhos, s, xs, ms, shells[idxs[j]], config, &hds[i])
			}

			buf.Close()
		}
	}

	for i := range rSets {
		rMax := coords[3][i]*config.rMaxMult
		rMin := coords[3][i]*config.rMinMult
		processProfile(rSets[i], rhoSets[i], rMin, rMax)
	}

	rSets = transpose(rSets)
	rhoSets = transpose(rhoSets)

	order := make([]int, len(rSets) + len(rhoSets) + 2)
	for i := range order { order[i] = i }
	lines := catalog.FormatCols(
			[][]int{ids, snaps}, append(rSets, rhoSets...), order,
	)

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot", "R [cMpc/h]", "Rho [h^2 Msun/cMpc^3]"},
		[]string{}, []int{0, 1, 2, 3},
		[]int{1, 1, int(config.bins), int(config.bins)},
	)

	if logging.Mode == logging.Performance {
		log.Printf("Time: %s", time.Since(t).String())
		log.Printf("Memory:\n%s", logging.MemString())
	}

	return append([]string{cString}, lines...), nil
}

func insertPoints(
	rhos []float64, s geom.Sphere, xs [][3]float32,
	ms []float32, shell analyze.Shell, config *ProfConfig, hd *io.Header,
) {
	lrMax := math.Log(float64(s.R) * config.rMaxMult)
	lrMin := math.Log(float64(s.R) * config.rMinMult)
	dlr := (lrMax - lrMin) / float64(config.bins)
	rMax2 := s.R * float32(config.rMaxMult)
	rMin2 := s.R * float32(config.rMinMult)
	rMax2 *= rMax2
	rMin2 *= rMin2

	x0, y0, z0 := s.C[0], s.C[1], s.C[2]
	tw2 := float32(hd.TotalWidth) / 2

	for i, vec := range xs {
		x, y, z := vec[0], vec[1], vec[2]
		dx, dy, dz := x - x0, y - y0, z - z0
		dx = wrap(dx, tw2)
		dy = wrap(dy, tw2)
		dz = wrap(dz, tw2)

		r2 := dx*dx + dy*dy + dz*dz
		if r2 <= rMin2 || r2 >= rMax2 {
			continue
		}

		if config.pType == containedDensityProfile &&
			!shell.Contains(float64(dx), float64(dy), float64(dz)) {
			continue
		}

		lr := math.Log(float64(r2)) / 2
		ir := int(((lr) - lrMin) / dlr)
		if ir == len(rhos) { ir-- }
		rhos[ir] += float64(ms[i])
	}
}

func processProfile(rs, rhos []float64, rMin, rMax float64) {
	n := len(rs)

	dlr := (math.Log(rMax) - math.Log(rMin)) / float64(n)
	lrMin := math.Log(rMin)

	for j := range rs {
		rs[j] = math.Exp(lrMin + dlr*(float64(j) + 0.5))

		rLo := math.Exp(dlr*float64(j) + lrMin)
		rHi := math.Exp(dlr*float64(j+1) + lrMin)
		dV := (rHi*rHi*rHi - rLo*rLo*rLo) * 4 * math.Pi / 3

		rhos[j] = rhos[j] / dV
	}
}

func angularFractionMain(
	ids, snaps []int, shells []analyze.Shell, rs []float64, config *ProfConfig,
) ([]string, error) {
	rCols := make([][]float64, config.bins)
	fCols := make([][]float64, config.bins)
	for i := range rCols {
		rCols[i] = make([]float64, len(ids))
		fCols[i] = make([]float64, len(ids))
	}

	for i := range shells {
		rs, fs := shells[i].AngularFractionProfile(
			int(config.samples), int(config.bins),
			rs[i] * config.rMinMult, rs[i] * config.rMaxMult,
		)

		for j := range rs {
			rCols[j][i], fCols[j][i] = rs[j], fs[j]
		}
	}

	order := make([]int, len(rCols) + len(fCols) + 2)
	for i := range order { order[i] = i }
	lines := catalog.FormatCols(
		[][]int{ids, snaps}, append(rCols, fCols...), order,
	)

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot", "R [cMpc/h]", "Volume Fraction Contained"},
		[]string{}, []int{0, 1, 2, 3},
		[]int{1, 1, int(config.bins), int(config.bins)},
	)

	return append([]string{cString}, lines...), nil
}
<commit_msg>Fixed intialization error in density profile<commit_after>package cmd

import (
	"fmt"
	"log"
	"math"
	"sort"
	"time"

	"github.com/phil-mansfield/shellfish/los/geom"
	"github.com/phil-mansfield/shellfish/los/analyze"
	"github.com/phil-mansfield/shellfish/cmd/catalog"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/logging"
	"github.com/phil-mansfield/shellfish/parse"
	"github.com/phil-mansfield/shellfish/io"
	"github.com/phil-mansfield/shellfish/cmd/memo"
)

type ProfConfig struct {
	bins, order, samples int64
	rMaxMult, rMinMult float64

	pType profileType

}

type profileType int
const (
	densityProfile profileType = iota
	containedDensityProfile
	angularFractionProfile
)

var _ Mode = &ProfConfig{}

func (config *ProfConfig) ExampleConfig() string {
	return `[prof.config]

#####################
## Required Fields ##
#####################

# ProfileType determines what type of profile will be output.
# Known profile types are:
# density -          the traditional spherical densiy profile that we all
                     know and love.
# contained-densiy - a density profile which only uses particles.
# angular-fraction - the angular fraction at each radius which is contained
                     within the shell.
ProfileType = density

# Order is the order of the Penna-Dines shell fit that Shellfish uses. This
# variable only needs to be set if ProfileType is set to contained-density
# or angular-fraction.
# Order = 3

# Samples is the number of Monte Carlo samples used when calculating angular
# fraction profiles. It does not need to be set when other profiles are
# calculated.
# Samples = 50000

#####################
## Optional Fields ##
#####################

# Bins is the number of logarithmic radial bins used in a profile.
# Bins = 150

# RMaxMult is the maximum radius of the profile as a function of R_200m.
# RMaxMult = 3

# RMinMult is the minimum radius of the profile as a function of R_200m.
# RMinMult = 0.03
`
}

func (config *ProfConfig) ReadConfig(fname string) error {
	if fname == "" {
		return nil
	}

	vars := parse.NewConfigVars("prof.config")

	vars.Int(&config.bins, "Bins", 150)
	vars.Int(&config.order, "Order", 3)
	vars.Int(&config.samples, "Samples", 50 * 1000)
	vars.Float(&config.rMaxMult, "RMaxMult", 3.0)
	vars.Float(&config.rMinMult, "RMinMult", 0.03)
	var pType string
	vars.String(&pType, "ProfileType", "")

	if err := parse.ReadConfig(fname, vars); err != nil {
		return err
	}

	switch pType {
	case "":
		return fmt.Errorf("The variable 'ProfileType' was not set.")
	case "density":
		config.pType = densityProfile
	case "contained-density":
		config.pType = containedDensityProfile
	case "angular-fraction":
		config.pType = angularFractionProfile
	default:
		return fmt.Errorf("The varaiable 'ProfileType' was set to '%s'.", pType)
	}

	return config.validate()
}

func (config *ProfConfig) validate() error {
	if config.bins < 0 {
		return fmt.Errorf("The variable '%s' was set to %d.",
			"Bins", config.bins)
	} else if config.rMinMult <= 0 {
		return fmt.Errorf("The variable '%s' was set to %g.",
			"RMinMult", config.rMinMult)
	} else if config.rMaxMult <= 0 {
		return fmt.Errorf("The variable '%s' was set to %g.",
			"RMinMult", config.rMinMult)
	}
	return nil
}

func (config *ProfConfig) Run(
	flags []string, gConfig *GlobalConfig, e *env.Environment, stdin []string,
) ([]string, error) {
	if logging.Mode != logging.Nil {
		log.Println(`
####################
## shellfish tree ##
####################`,
		)
	}

	var t time.Time
	if logging.Mode == logging.Performance {
		t = time.Now()
	}

	var (
		intCols [][]int
		coords [][]float64
		shells []analyze.Shell
		err error
	)

	switch config.pType {
	case densityProfile:
		intColIdxs := []int{0, 1}
		floatColIdxs := []int{2, 3, 4, 5}

		intCols, coords, err = catalog.ParseCols(
			stdin, intColIdxs, floatColIdxs,
		)

		if err != nil {
			return nil, err
		}

		shells = make([]analyze.Shell, len(coords[0]))
	case containedDensityProfile, angularFractionProfile:
		intColIdxs := []int{0, 1}
		floatColIdxs := make([]int, 4 + config.order*config.order*2)
		for i := range floatColIdxs {
			floatColIdxs[i] += i + 2
		}

		var floatCols [][]float64
		intCols, floatCols, err = catalog.ParseCols(
			stdin, intColIdxs, floatColIdxs,
		)

		if err != nil {
			return nil, err
		}

		coords = floatCols[:4]
		coeffs := floatCols[4:]
		shells = make([]analyze.Shell, len(coords[0]))
		for i := range shells {
			coeffVec := make([]float64, len(coeffs))
			for j := range coeffVec {
				coeffVec[j] = coeffs[j][i]
			}
			order := int(config.order)
			shells[i] = analyze.PennaFunc(coeffVec, order, order, 2)
		}
	}

	if len(intCols) == 0 {
		return nil, fmt.Errorf("No input IDs.")
	}

	ids, snaps := intCols[0], intCols[1]
	snapBins, idxBins := binBySnap(snaps, ids)

	if config.pType == angularFractionProfile {
		return angularFractionMain(ids, snaps, shells, coords[3], config)
	}

	rSets := make([][]float64, len(ids))
	rhoSets := make([][]float64, len(ids))
	for i := range rSets {
		rSets[i] = make([]float64, config.bins)
		rhoSets[i] = make([]float64, config.bins)
	}

	sortedSnaps := []int{}
	for snap := range snapBins {
		sortedSnaps = append(sortedSnaps, snap)
	}
	sort.Ints(sortedSnaps)

	buf, err := getVectorBuffer(
		e.ParticleCatalog(snaps[0], 0),
		gConfig.SnapshotType, gConfig.Endianness,
	)
	if err != nil {
		return nil, err
	}

	for _, snap := range sortedSnaps {
		if snap == -1 {
			continue
		}

		idxs := idxBins[snap]
		snapCoords := [][]float64{
			make([]float64, len(idxs)), make([]float64, len(idxs)),
			make([]float64, len(idxs)), make([]float64, len(idxs)),
		}
		for i, idx := range idxs {
			snapCoords[0][i] = coords[0][idx]
			snapCoords[1][i] = coords[1][idx]
			snapCoords[2][i] = coords[2][idx]
			snapCoords[3][i] = coords[3][idx]
		}

		hds, files, err := memo.ReadHeaders(snap, buf, e)
		if err != nil {
			return nil, err
		}
		hBounds, err := boundingSpheres(snapCoords, &hds[0], e)
		if err != nil {
			return nil, err
		}
		_, intrIdxs := binSphereIntersections(hds, hBounds)

		for i := range hds {
			if len(intrIdxs[i]) == 0 {
				continue
			}

			xs, ms, _, err := buf.Read(files[i])
			if err != nil {
				return nil, err
			}

			// Waarrrgggble
			for _, j := range intrIdxs[i] {
				rhos := rhoSets[idxs[j]]
				s := hBounds[j]

				insertPoints(rhos, s, xs, ms, shells[idxs[j]], config, &hds[i])
			}

			buf.Close()
		}
	}

	for i := range rSets {
		rMax := coords[3][i]*config.rMaxMult
		rMin := coords[3][i]*config.rMinMult
		processProfile(rSets[i], rhoSets[i], rMin, rMax)
	}

	rSets = transpose(rSets)
	rhoSets = transpose(rhoSets)

	order := make([]int, len(rSets) + len(rhoSets) + 2)
	for i := range order { order[i] = i }
	lines := catalog.FormatCols(
			[][]int{ids, snaps}, append(rSets, rhoSets...), order,
	)

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot", "R [cMpc/h]", "Rho [h^2 Msun/cMpc^3]"},
		[]string{}, []int{0, 1, 2, 3},
		[]int{1, 1, int(config.bins), int(config.bins)},
	)

	if logging.Mode == logging.Performance {
		log.Printf("Time: %s", time.Since(t).String())
		log.Printf("Memory:\n%s", logging.MemString())
	}

	return append([]string{cString}, lines...), nil
}

func insertPoints(
	rhos []float64, s geom.Sphere, xs [][3]float32,
	ms []float32, shell analyze.Shell, config *ProfConfig, hd *io.Header,
) {
	lrMax := math.Log(float64(s.R) * config.rMaxMult)
	lrMin := math.Log(float64(s.R) * config.rMinMult)
	dlr := (lrMax - lrMin) / float64(config.bins)
	rMax2 := s.R * float32(config.rMaxMult)
	rMin2 := s.R * float32(config.rMinMult)
	rMax2 *= rMax2
	rMin2 *= rMin2

	x0, y0, z0 := s.C[0], s.C[1], s.C[2]
	tw2 := float32(hd.TotalWidth) / 2

	for i, vec := range xs {
		x, y, z := vec[0], vec[1], vec[2]
		dx, dy, dz := x - x0, y - y0, z - z0
		dx = wrap(dx, tw2)
		dy = wrap(dy, tw2)
		dz = wrap(dz, tw2)

		r2 := dx*dx + dy*dy + dz*dz
		if r2 <= rMin2 || r2 >= rMax2 {
			continue
		}

		if config.pType == containedDensityProfile &&
			!shell.Contains(float64(dx), float64(dy), float64(dz)) {
			continue
		}

		lr := math.Log(float64(r2)) / 2
		ir := int(((lr) - lrMin) / dlr)
		if ir == len(rhos) { ir-- }
		rhos[ir] += float64(ms[i])
	}
}

func processProfile(rs, rhos []float64, rMin, rMax float64) {
	n := len(rs)

	dlr := (math.Log(rMax) - math.Log(rMin)) / float64(n)
	lrMin := math.Log(rMin)

	for j := range rs {
		rs[j] = math.Exp(lrMin + dlr*(float64(j) + 0.5))

		rLo := math.Exp(dlr*float64(j) + lrMin)
		rHi := math.Exp(dlr*float64(j+1) + lrMin)
		dV := (rHi*rHi*rHi - rLo*rLo*rLo) * 4 * math.Pi / 3

		rhos[j] = rhos[j] / dV
	}
}

func angularFractionMain(
	ids, snaps []int, shells []analyze.Shell, rs []float64, config *ProfConfig,
) ([]string, error) {
	rCols := make([][]float64, config.bins)
	fCols := make([][]float64, config.bins)
	for i := range rCols {
		rCols[i] = make([]float64, len(ids))
		fCols[i] = make([]float64, len(ids))
	}

	for i := range shells {
		rs, fs := shells[i].AngularFractionProfile(
			int(config.samples), int(config.bins),
			rs[i] * config.rMinMult, rs[i] * config.rMaxMult,
		)

		for j := range rs {
			rCols[j][i], fCols[j][i] = rs[j], fs[j]
		}
	}

	order := make([]int, len(rCols) + len(fCols) + 2)
	for i := range order { order[i] = i }
	lines := catalog.FormatCols(
		[][]int{ids, snaps}, append(rCols, fCols...), order,
	)

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot", "R [cMpc/h]", "Volume Fraction Contained"},
		[]string{}, []int{0, 1, 2, 3},
		[]int{1, 1, int(config.bins), int(config.bins)},
	)

	return append([]string{cString}, lines...), nil
}
<|endoftext|>


<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package index

import (
	"reflect"
	"strings"
	"testing"
)

func stringToPath(s string) Path {
	return stringSliceToPath(strings.Split(s, PathSeparator))
}

func stringSliceToPath(s []string) Path {
	p := make(Path, len(s))
	for i, x := range s {
		p[i] = Key(x)
	}
	return p
}

func TestPathEqual(t *testing.T) {
	tests := []struct {
		p, q  Path
		equal bool
	}{
		{
			Path(nil), Path(nil),
			true,
		},
		{
			Path([]Key{}), Path([]Key{}),
			true,
		},
		{
			stringToPath("a"), stringToPath("a"),
			true,
		},
		{
			stringToPath("a:b"), stringToPath("a"),
			false,
		},
		{
			Path(nil), stringToPath("a"),
			false,
		},
	}

	for ii, tt := range tests {
		if tt.p.Equal(tt.q) != tt.equal {
			t.Errorf("[%d] (%#v).Equal(%#v) = %v, expected %v", ii, tt.p, tt.q, !tt.equal, tt.equal)
		}
	}
}

func TestPathContains(t *testing.T) {
	tests := []struct {
		p, q     Path
		contains bool
	}{
		{
			Path(nil), Path(nil),
			false,
		},
		{
			Path([]Key{}), Path([]Key{}),
			false,
		},
		{
			NewPath("a"), NewPath("a"),
			true,
		},
		{
			NewPath("a:b"), NewPath("a"),
			false,
		},
		{
			Path(nil), NewPath("a"),
			false,
		},
		{
			NewPath("a:b"), NewPath("a:b:c"),
			true,
		},
	}

	for ii, tt := range tests {
		if tt.p.Contains(tt.q) != tt.contains {
			t.Errorf("[%d] (%#v).Contains(%#v) = %v, expected %v", ii, tt.p, tt.q, !tt.contains, tt.contains)
		}
	}
}

func TestOrderedIntersection(t *testing.T) {
	tests := []struct {
		in  [][]Path
		out []Path
	}{
		{
			in:  nil,
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B")},
			},
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B"), stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A"), stringToPath("B")},
				{stringToPath("B"), stringToPath("A")},
				{stringToPath("A"), stringToPath("B"), stringToPath("C")},
				{stringToPath("C"), stringToPath("A"), stringToPath("B"), stringToPath("B")},
			},
			out: []Path{stringToPath("B"), stringToPath("A")},
		},
	}

	for ii, tt := range tests {
		got := OrderedIntersection(tt.in...)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected: %#v", ii, got, tt.out)
		}
	}
}

func TestUnion(t *testing.T) {
	tests := []struct {
		in  [][]Path
		out []Path
	}{
		{
			in:  nil,
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B")},
			},
			out: []Path{stringToPath("A"), stringToPath("B")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B"), stringToPath("A")},
			},
			out: []Path{stringToPath("A"), stringToPath("B")},
		},

		{
			in: [][]Path{
				{stringToPath("A"), stringToPath("B")},
				{stringToPath("B"), stringToPath("A")},
				{stringToPath("A"), stringToPath("B"), stringToPath("C")},
				{stringToPath("C"), stringToPath("A"), stringToPath("B"), stringToPath("B")},
			},
			out: []Path{stringToPath("A"), stringToPath("B"), stringToPath("C")},
		},
	}

	for ii, tt := range tests {
		got := Union(tt.in...)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected: %#v", ii, got, tt.out)
		}
	}
}

func TestIndexOfPath(t *testing.T) {
	tests := []struct {
		haystack []Path
		needle   Path
		idx      int
	}{
		{
			[]Path{},
			Path{},
			-1,
		},
		{
			[]Path{
				Path{"Root"},
			},
			Path{"Root"},
			0,
		}, {
			[]Path{
				Path{"Root"}, Path{"Root", "One"},
			},
			Path{"Root", "One"},
			1,
		},
	}

	for ii, tt := range tests {
		i := IndexOfPath(tt.haystack, tt.needle)
		if i != tt.idx {
			t.Errorf("[%d] IndexOfPath(%v, %v) = %d, expected %d", ii, tt.haystack, tt.needle, i, tt.idx)
		}
	}
}

func TestPathFromJSONInterface(t *testing.T) {
	tests := []struct {
		in  interface{}
		out Path
	}{
		{
			interface{}(nil),
			Path(nil),
		},

		{
			[]interface{}{nil},
			Path(nil),
		},

		{
			[]interface{}{""},
			Path{""},
		},
	}

	for ii, tt := range tests {
		got, _ := PathFromJSONInterface(tt.in)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got: %#v, expected %#v", ii, got, tt.out)
		}
	}
}
<commit_msg>Added more tests cases for path methods.<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package index

import (
	"reflect"
	"strings"
	"testing"
)

func stringToPath(s string) Path {
	return stringSliceToPath(strings.Split(s, PathSeparator))
}

func stringSliceToPath(s []string) Path {
	p := make(Path, len(s))
	for i, x := range s {
		p[i] = Key(x)
	}
	return p
}

func TestPathEqual(t *testing.T) {
	tests := []struct {
		p, q  Path
		equal bool
	}{
		{
			Path(nil), Path(nil),
			true,
		},
		{
			Path([]Key{}), Path([]Key{}),
			true,
		},
		{
			stringToPath("a"), stringToPath("a"),
			true,
		},
		{
			stringToPath("a:b"), stringToPath("a"),
			false,
		},
		{
			stringToPath("a:b"), stringToPath("a:c"),
			false,
		},
		{
			Path(nil), stringToPath("a"),
			false,
		},
	}

	for ii, tt := range tests {
		if tt.p.Equal(tt.q) != tt.equal {
			t.Errorf("[%d] (%#v).Equal(%#v) = %v, expected %v", ii, tt.p, tt.q, !tt.equal, tt.equal)
		}
	}
}

func TestPathContains(t *testing.T) {
	tests := []struct {
		p, q     Path
		contains bool
	}{
		{
			Path(nil), Path(nil),
			false,
		},
		{
			Path([]Key{}), Path([]Key{}),
			false,
		},
		{
			NewPath("a"), NewPath("a"),
			true,
		},
		{
			NewPath("a:b"), NewPath("a"),
			false,
		},
		{
			NewPath("a:b"), NewPath("a:c"),
			false,
		},
		{
			Path(nil), NewPath("a"),
			false,
		},
		{
			NewPath("a:b"), NewPath("a:b:c"),
			true,
		},
	}

	for ii, tt := range tests {
		if tt.p.Contains(tt.q) != tt.contains {
			t.Errorf("[%d] (%#v).Contains(%#v) = %v, expected %v", ii, tt.p, tt.q, !tt.contains, tt.contains)
		}
	}
}

func TestOrderedIntersection(t *testing.T) {
	tests := []struct {
		in  [][]Path
		out []Path
	}{
		{
			in:  nil,
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B")},
			},
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B"), stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A"), stringToPath("B")},
				{stringToPath("B"), stringToPath("A")},
				{stringToPath("A"), stringToPath("B"), stringToPath("C")},
				{stringToPath("C"), stringToPath("A"), stringToPath("B"), stringToPath("B")},
			},
			out: []Path{stringToPath("B"), stringToPath("A")},
		},
	}

	for ii, tt := range tests {
		got := OrderedIntersection(tt.in...)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected: %#v", ii, got, tt.out)
		}
	}
}

func TestUnion(t *testing.T) {
	tests := []struct {
		in  [][]Path
		out []Path
	}{
		{
			in:  nil,
			out: []Path{},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
			},
			out: []Path{stringToPath("A")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B")},
			},
			out: []Path{stringToPath("A"), stringToPath("B")},
		},

		{
			in: [][]Path{
				{stringToPath("A")},
				{stringToPath("B"), stringToPath("A")},
			},
			out: []Path{stringToPath("A"), stringToPath("B")},
		},

		{
			in: [][]Path{
				{stringToPath("A"), stringToPath("B")},
				{stringToPath("B"), stringToPath("A")},
				{stringToPath("A"), stringToPath("B"), stringToPath("C")},
				{stringToPath("C"), stringToPath("A"), stringToPath("B"), stringToPath("B")},
			},
			out: []Path{stringToPath("A"), stringToPath("B"), stringToPath("C")},
		},
	}

	for ii, tt := range tests {
		got := Union(tt.in...)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected: %#v", ii, got, tt.out)
		}
	}
}

func TestIndexOfPath(t *testing.T) {
	tests := []struct {
		haystack []Path
		needle   Path
		idx      int
	}{
		{
			[]Path{},
			Path{},
			-1,
		},
		{
			[]Path{
				Path{"Root"},
			},
			Path{"Root"},
			0,
		}, {
			[]Path{
				Path{"Root"}, Path{"Root", "One"},
			},
			Path{"Root", "One"},
			1,
		},
	}

	for ii, tt := range tests {
		i := IndexOfPath(tt.haystack, tt.needle)
		if i != tt.idx {
			t.Errorf("[%d] IndexOfPath(%v, %v) = %d, expected %d", ii, tt.haystack, tt.needle, i, tt.idx)
		}
	}
}

func TestPathFromJSONInterface(t *testing.T) {
	tests := []struct {
		in  interface{}
		out Path
	}{
		{
			interface{}(nil),
			Path(nil),
		},

		{
			[]interface{}{nil},
			Path(nil),
		},

		{
			[]interface{}{""},
			Path{""},
		},
	}

	for ii, tt := range tests {
		got, _ := PathFromJSONInterface(tt.in)
		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got: %#v, expected %#v", ii, got, tt.out)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package cmd

import (
	"fmt"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/spf13/cobra"
)

// Logrus hooks

// Hook for erroring and exit out on warning
type errorOnWarningHook struct{}

func (errorOnWarningHook) Levels() []log.Level {
	return []log.Level{log.WarnLevel}
}

func (errorOnWarningHook) Fire(entry *log.Entry) error {
	log.Fatalln(entry.Message)
	return nil
}

// TODO: comment
var (
	GlobalBundle           string
	GlobalProvider         string
	GlobalVerbose          bool
	GlobalSuppressWarnings bool
	GlobalErrorOnWarning   bool
	GlobalFiles            []string
)

// RootCmd root level flags and commands
var RootCmd = &cobra.Command{
	Use:   "kompose",
	Short: "A tool helping Docker Compose users move to Kubernetes",
	Long:  `Kompose is a tool to help users who are familiar with docker-compose move to Kubernetes.`,
	// PersitentPreRun will be "inherited" by all children and ran before *every* command unless
	// the child has overridden the functionality. This functionality was implemented to check / modify
	// all global flag calls regardless of app call.
	PersistentPreRun: func(cmd *cobra.Command, args []string) {

		// Add extra logging when verbosity is passed
		if GlobalVerbose {
			log.SetLevel(log.DebugLevel)
		}

		// Disable the timestamp (Kompose is too fast!)
		formatter := new(log.TextFormatter)
		formatter.DisableTimestamp = true
		formatter.ForceColors = true
		log.SetFormatter(formatter)

		// Set the appropriate suppress warnings and error on warning flags
		if GlobalSuppressWarnings {
			log.SetLevel(log.ErrorLevel)
		} else if GlobalErrorOnWarning {
			hook := errorOnWarningHook{}
			log.AddHook(hook)
		}

		// Error out of the user has not chosen Kubernetes or OpenShift
		provider := strings.ToLower(GlobalProvider)
		if provider != "kubernetes" && provider != "openshift" {
			log.Fatalf("%s is an unsupported provider. Supported providers are: 'kubernetes', 'openshift'.", GlobalProvider)
		}

	},
}

// Execute TODO: comment
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	RootCmd.PersistentFlags().BoolVarP(&GlobalVerbose, "verbose", "v", false, "verbose output")
	RootCmd.PersistentFlags().BoolVar(&GlobalSuppressWarnings, "suppress-warnings", false, "Suppress all warnings")
	RootCmd.PersistentFlags().BoolVar(&GlobalErrorOnWarning, "error-on-warning", false, "Treat any warning as an error")
	RootCmd.PersistentFlags().StringArrayVarP(&GlobalFiles, "file", "f", []string{}, "Specify an alternative compose file")
	RootCmd.PersistentFlags().StringVarP(&GlobalBundle, "bundle", "b", "", "Specify a Distributed Application GlobalBundle (DAB) file")
	RootCmd.PersistentFlags().StringVar(&GlobalProvider, "provider", "kubernetes", "Specify a provider. Kubernetes or OpenShift.")
}
<commit_msg>Fix the DAB spelling error<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package cmd

import (
	"fmt"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/spf13/cobra"
)

// Logrus hooks

// Hook for erroring and exit out on warning
type errorOnWarningHook struct{}

func (errorOnWarningHook) Levels() []log.Level {
	return []log.Level{log.WarnLevel}
}

func (errorOnWarningHook) Fire(entry *log.Entry) error {
	log.Fatalln(entry.Message)
	return nil
}

// TODO: comment
var (
	GlobalBundle           string
	GlobalProvider         string
	GlobalVerbose          bool
	GlobalSuppressWarnings bool
	GlobalErrorOnWarning   bool
	GlobalFiles            []string
)

// RootCmd root level flags and commands
var RootCmd = &cobra.Command{
	Use:   "kompose",
	Short: "A tool helping Docker Compose users move to Kubernetes",
	Long:  `Kompose is a tool to help users who are familiar with docker-compose move to Kubernetes.`,
	// PersitentPreRun will be "inherited" by all children and ran before *every* command unless
	// the child has overridden the functionality. This functionality was implemented to check / modify
	// all global flag calls regardless of app call.
	PersistentPreRun: func(cmd *cobra.Command, args []string) {

		// Add extra logging when verbosity is passed
		if GlobalVerbose {
			log.SetLevel(log.DebugLevel)
		}

		// Disable the timestamp (Kompose is too fast!)
		formatter := new(log.TextFormatter)
		formatter.DisableTimestamp = true
		formatter.ForceColors = true
		log.SetFormatter(formatter)

		// Set the appropriate suppress warnings and error on warning flags
		if GlobalSuppressWarnings {
			log.SetLevel(log.ErrorLevel)
		} else if GlobalErrorOnWarning {
			hook := errorOnWarningHook{}
			log.AddHook(hook)
		}

		// Error out of the user has not chosen Kubernetes or OpenShift
		provider := strings.ToLower(GlobalProvider)
		if provider != "kubernetes" && provider != "openshift" {
			log.Fatalf("%s is an unsupported provider. Supported providers are: 'kubernetes', 'openshift'.", GlobalProvider)
		}

	},
}

// Execute TODO: comment
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	RootCmd.PersistentFlags().BoolVarP(&GlobalVerbose, "verbose", "v", false, "verbose output")
	RootCmd.PersistentFlags().BoolVar(&GlobalSuppressWarnings, "suppress-warnings", false, "Suppress all warnings")
	RootCmd.PersistentFlags().BoolVar(&GlobalErrorOnWarning, "error-on-warning", false, "Treat any warning as an error")
	RootCmd.PersistentFlags().StringArrayVarP(&GlobalFiles, "file", "f", []string{}, "Specify an alternative compose file")
	RootCmd.PersistentFlags().StringVarP(&GlobalBundle, "bundle", "b", "", "Specify a Distributed Application Bundle (DAB) file")
	RootCmd.PersistentFlags().StringVar(&GlobalProvider, "provider", "kubernetes", "Specify a provider. Kubernetes or OpenShift.")
}
<|endoftext|>


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

package cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/aws/aws-sdk-go/service/lambda"
	// "github.com/fatih/color"
	"os"
	"path/filepath"

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

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "aegis",
	Short: "Deploy RESTful serverless APIs ",
	Long:  `A tool to deploy a RESTful serverless API using AWS Lambda and API Gateway with a Lambda Proxy and an API Gateway ANY request.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	//	Run: func(cmd *cobra.Command, args []string) { },
}

// deploymentConfig holds the AWS Lambda configuration
type deploymentConfig struct {
	App struct {
		Name           string
		KeepBuildFiles bool
		BuildFileName  string
	}
	AWS struct {
		Region          string
		Profile         string
		AccessKeyID     string
		SecretAccessKey string
	}
	Lambda struct {
		Wrapper              string
		Runtime              string
		Handler              string
		FunctionName         string
		Alias                string
		Description          string
		MemorySize           int64
		Role                 string
		Timeout              int64
		SourceZip            string
		EnvironmentVariables map[string]*string
		KMSKeyArn            string
		VPC                  struct {
			SecurityGroups []string
			Subnets        []string
		}
		TraceMode string
	}
	API struct {
		Name             string
		Description      string
		Cache            bool
		CacheSize        string
		Stages           map[string]deploymentStage
		BinaryMediaTypes []*string
	}
}

// deploymentStage defines an API Gateway stage and holds configuration options for it
type deploymentStage struct {
	Name        string
	Description string
	Variables   map[string]*string
	Cache       bool
	CacheSize   string
}

// task defines options for a CloudWatch event rule (scheduled task)
type task struct {
	Schedule    string          `json:"schedule"`
	Input       json.RawMessage `json:"input"`
	Disabled    bool            `json:"disabled"`
	Description string          `json:"description"`
	Name        string          `json:"-"` // Do not allow names to be set by JSON files (for now)
}

// cfg holds the Aegis configuration for the Lambda function, API Gateway settings, etc.
var cfg deploymentConfig

// awsCfg holds the AWS configuration and credentials
var awsCfg aws.Config

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(InitConfig)
	RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "aegis", "config file (default is aegis.yaml)")

	// AWS options & credentials
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.Region, "region", "r", "us-east-1", "AWS Region to use")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.AccessKeyID, "keyId", "k", "", "AWS Access Key ID")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.SecretAccessKey, "secretKey", "s", "", "AWS Secret Access Key")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.Profile, "profile", "p", "default", "AWS Credentials Profile to use")
}

// InitConfig reads in config file and ENV variables if set.
func InitConfig() {
	viper.SetConfigName("aegis") // name of config file (without extension)
	viper.AddConfigPath(".")
	// viper.AddConfigPath("$HOME")  // adding home directory as first search path
	viper.AutomaticEnv() // read in environment variables that match

	// Default config values
	viper.SetDefault("aws.region", "us-east-1")
	// viper.SetDefault("aws.profile", "default") // set by defaults on flags
	// Default Lambda config values
	viper.SetDefault("lambda.functionName", "aegis_example")
	viper.SetDefault("lambda.runtime", lambda.RuntimeGo1X)
	// Aegis will build a Go binary named aegis_app ... This shouldn't need to change.
	viper.SetDefault("lambda.handler", "aegis_app")
	viper.SetDefault("lambda.alias", "current")
	// In megabytes
	viper.SetDefault("lambda.memorySize", int64(128))
	// In seconds
	viper.SetDefault("lambda.timeout", int64(3))
	// No suitable default for this
	// viper.SetDefault("lambda.role", "arn:aws:iam::account-id:role/lambda_basic_execution")
	// Set a default function name
	fName := "aegis_function"
	// Use the current directory name by default
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		// Prepend aegis_
		if dir != "/" && dir != "" {
			dirParts := strings.Split(dir, "/")
			dir = dirParts[len(dirParts)-1]
			var buffer bytes.Buffer
			buffer.WriteString("aegis_")
			buffer.WriteString(dir)
			fName = buffer.String()
			buffer.Reset()
		}
	}
	viper.SetDefault("lambda.functionName", fName)
	// Enable XRay by default, see: https://docs.aws.amazon.com/sdk-for-go/api/service/lambda/#TracingConfig
	viper.SetDefault("lambda.traceMode", "Active")
	// Default API Gateway config values
	viper.SetDefault("api.name", "Aegis API")
	viper.SetDefault("api.description", "")
	viper.SetDefault("api.cache", false)
	viper.SetDefault("api.binaryMediaTypes", "*/*")
	// For valid values, see: https://godoc.org/github.com/aws/aws-sdk-go/service/apigateway#pkg-constants
	viper.SetDefault("api.cacheSize", apigateway.CacheClusterSize05)

	// Default API stage (does not use caching, that comes with an additional cost)
	viper.SetDefault("api.stages", map[string]deploymentStage{
		"prod": deploymentStage{
			Name:        "prod",
			Description: "production stage",
			Cache:       false, // no cache by default
			// CacheSize:   apigateway.CacheClusterSize05, // never needed because above is false and empty value caught in deployment
		},
	})

	// By default do not keep the build files (clean up)
	viper.SetDefault("app.keepBuildFiles", false)
	// Just in case the temporary zip file that gets built creates a conflict, it can be adjusted. However, this is the default.
	viper.SetDefault("app.buildFileName", "aegis_function.zip")

	// If a config file is found, read it in.
	err = viper.ReadInConfig()
	if err == nil {
		// TODO verbose?
		// fmt.Println("Using config file:", viper.ConfigFileUsed())
	} else {
		// Not strictly required given defaults? This prevents other commands such as `init` from working.
		// fmt.Printf("%v %v\n", color.YellowString("Warning:"), "Could not find aegis config file.")
		// os.Exit(-1)
	}

	_ = viper.Unmarshal(&cfg)
	// if err != nil {
	// 	fmt.Println("Could parse aegis config file.")
	// 	os.Exit(-1)
	// }

	// Initialize AWS config
	awsCfg = aws.Config{
		Region: aws.String(cfg.AWS.Region),
	}
}

// SetAwsCfg will set awsCfg values using an aws.Config struct
func SetAwsCfg(config aws.Config) {
	awsCfg = config
}
<commit_msg>remove duplicate default value<commit_after>// Copyright © 2016 Tom Maiaroto <tom@shift8creative.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/aws/aws-sdk-go/service/lambda"
	// "github.com/fatih/color"
	"os"
	"path/filepath"

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

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "aegis",
	Short: "Deploy RESTful serverless APIs ",
	Long:  `A tool to deploy a RESTful serverless API using AWS Lambda and API Gateway with a Lambda Proxy and an API Gateway ANY request.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	//	Run: func(cmd *cobra.Command, args []string) { },
}

// deploymentConfig holds the AWS Lambda configuration
type deploymentConfig struct {
	App struct {
		Name           string
		KeepBuildFiles bool
		BuildFileName  string
	}
	AWS struct {
		Region          string
		Profile         string
		AccessKeyID     string
		SecretAccessKey string
	}
	Lambda struct {
		Wrapper              string
		Runtime              string
		Handler              string
		FunctionName         string
		Alias                string
		Description          string
		MemorySize           int64
		Role                 string
		Timeout              int64
		SourceZip            string
		EnvironmentVariables map[string]*string
		KMSKeyArn            string
		VPC                  struct {
			SecurityGroups []string
			Subnets        []string
		}
		TraceMode string
	}
	API struct {
		Name             string
		Description      string
		Cache            bool
		CacheSize        string
		Stages           map[string]deploymentStage
		BinaryMediaTypes []*string
	}
}

// deploymentStage defines an API Gateway stage and holds configuration options for it
type deploymentStage struct {
	Name        string
	Description string
	Variables   map[string]*string
	Cache       bool
	CacheSize   string
}

// task defines options for a CloudWatch event rule (scheduled task)
type task struct {
	Schedule    string          `json:"schedule"`
	Input       json.RawMessage `json:"input"`
	Disabled    bool            `json:"disabled"`
	Description string          `json:"description"`
	Name        string          `json:"-"` // Do not allow names to be set by JSON files (for now)
}

// cfg holds the Aegis configuration for the Lambda function, API Gateway settings, etc.
var cfg deploymentConfig

// awsCfg holds the AWS configuration and credentials
var awsCfg aws.Config

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(InitConfig)
	RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "aegis", "config file (default is aegis.yaml)")

	// AWS options & credentials
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.Region, "region", "r", "us-east-1", "AWS Region to use")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.AccessKeyID, "keyId", "k", "", "AWS Access Key ID")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.SecretAccessKey, "secretKey", "s", "", "AWS Secret Access Key")
	RootCmd.PersistentFlags().StringVarP(&cfg.AWS.Profile, "profile", "p", "default", "AWS Credentials Profile to use")
}

// InitConfig reads in config file and ENV variables if set.
func InitConfig() {
	viper.SetConfigName("aegis") // name of config file (without extension)
	viper.AddConfigPath(".")
	// viper.AddConfigPath("$HOME")  // adding home directory as first search path
	viper.AutomaticEnv() // read in environment variables that match

	// Default config values
	viper.SetDefault("aws.region", "us-east-1")
	// viper.SetDefault("aws.profile", "default") // set by defaults on flags
	// Default Lambda config values
	viper.SetDefault("lambda.runtime", lambda.RuntimeGo1X)
	// Aegis will build a Go binary named aegis_app ... This shouldn't need to change.
	viper.SetDefault("lambda.handler", "aegis_app")
	viper.SetDefault("lambda.alias", "current")
	// In megabytes
	viper.SetDefault("lambda.memorySize", int64(128))
	// In seconds
	viper.SetDefault("lambda.timeout", int64(3))
	// No suitable default for this
	// viper.SetDefault("lambda.role", "arn:aws:iam::account-id:role/lambda_basic_execution")
	// Set a default function name
	fName := "aegis_function"
	// Use the current directory name by default
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		// Prepend aegis_
		if dir != "/" && dir != "" {
			dirParts := strings.Split(dir, "/")
			dir = dirParts[len(dirParts)-1]
			var buffer bytes.Buffer
			buffer.WriteString("aegis_")
			buffer.WriteString(dir)
			fName = buffer.String()
			buffer.Reset()
		}
	}
	viper.SetDefault("lambda.functionName", fName)
	// Enable XRay by default, see: https://docs.aws.amazon.com/sdk-for-go/api/service/lambda/#TracingConfig
	viper.SetDefault("lambda.traceMode", "Active")
	// Default API Gateway config values
	viper.SetDefault("api.name", "Aegis API")
	viper.SetDefault("api.description", "")
	viper.SetDefault("api.cache", false)
	viper.SetDefault("api.binaryMediaTypes", "*/*")
	// For valid values, see: https://godoc.org/github.com/aws/aws-sdk-go/service/apigateway#pkg-constants
	viper.SetDefault("api.cacheSize", apigateway.CacheClusterSize05)

	// Default API stage (does not use caching, that comes with an additional cost)
	viper.SetDefault("api.stages", map[string]deploymentStage{
		"prod": deploymentStage{
			Name:        "prod",
			Description: "production stage",
			Cache:       false, // no cache by default
			// CacheSize:   apigateway.CacheClusterSize05, // never needed because above is false and empty value caught in deployment
		},
	})

	// By default do not keep the build files (clean up)
	viper.SetDefault("app.keepBuildFiles", false)
	// Just in case the temporary zip file that gets built creates a conflict, it can be adjusted. However, this is the default.
	viper.SetDefault("app.buildFileName", "aegis_function.zip")

	// If a config file is found, read it in.
	err = viper.ReadInConfig()
	if err == nil {
		// TODO verbose?
		// fmt.Println("Using config file:", viper.ConfigFileUsed())
	} else {
		// Not strictly required given defaults? This prevents other commands such as `init` from working.
		// fmt.Printf("%v %v\n", color.YellowString("Warning:"), "Could not find aegis config file.")
		// os.Exit(-1)
	}

	_ = viper.Unmarshal(&cfg)
	// if err != nil {
	// 	fmt.Println("Could parse aegis config file.")
	// 	os.Exit(-1)
	// }

	// Initialize AWS config
	awsCfg = aws.Config{
		Region: aws.String(cfg.AWS.Region),
	}
}

// SetAwsCfg will set awsCfg values using an aws.Config struct
func SetAwsCfg(config aws.Config) {
	awsCfg = config
}
<|endoftext|>


<commit_before>package cmd

import (
	"gitlab.com/littledot/mockhiato/lib"

	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "mockhiato",
	Short: "A mocking framework for Go",
	Long:  `A mocking framework for Go.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	// Run: func(cmd *cobra.Command, args []string) {
	// 	spew.Dump(viper.AllSettings())
	// },
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		log.Fatal(err)
	}
}

func init() {
	cobra.OnInitialize(initConfig)
	// Here you will define your flags and configuration settings.
	// Cobra supports Persistent Flags, which, if defined here,
	// will be global for your application.
	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is mockhiato.yaml)")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.PersistentFlags().BoolP("Verbose", "v", false, "Make some noise!")
}

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

	viper.SetConfigName("mockhiato") // name of config file (without extension)
	viper.AddConfigPath(".")

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		log.Infof("Configuring mockhiato with %s", viper.ConfigFileUsed())
	}
}

func getConfig(cmd *cobra.Command) lib.Config {
	if err := viper.BindPFlags(cmd.Flags()); err != nil {
		panic(err)
	}
	config := lib.Config{}
	if err := viper.Unmarshal(&config); err != nil {
		panic(err)
	}
	log.Infof("Configs: %#v", config)
	return config
}
<commit_msg>Respect -v flag.<commit_after>package cmd

import (
	"gitlab.com/littledot/mockhiato/lib"

	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "mockhiato",
	Short: "A mocking framework for Go",
	Long:  `A mocking framework for Go.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	// Run: func(cmd *cobra.Command, args []string) {
	// 	spew.Dump(viper.AllSettings())
	// },
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		log.Fatal(err)
	}
}

func init() {
	cobra.OnInitialize(initConfig)
	// Here you will define your flags and configuration settings.
	// Cobra supports Persistent Flags, which, if defined here,
	// will be global for your application.
	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is mockhiato.yaml)")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.PersistentFlags().BoolP("Verbose", "v", false, "Make some noise!")
}

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

	viper.SetConfigName("mockhiato") // name of config file (without extension)
	viper.AddConfigPath(".")

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		log.Infof("Configuring mockhiato with %s", viper.ConfigFileUsed())
	}
}

func getConfig(cmd *cobra.Command) lib.Config {
	if err := viper.BindPFlags(cmd.Flags()); err != nil {
		panic(err)
	}
	config := lib.Config{}
	if err := viper.Unmarshal(&config); err != nil {
		panic(err)
	}
	if config.Verbose {
		log.SetLevel(log.DebugLevel)
	}
	log.Debugf("Configs: %#v", config)
	return config
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"

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

// gometalinter がそうしろって。。。
const windows string = "windows"

// 終了ステータスコード。
const (
	exitOK int = iota
	exitNG
)

// RootCmd represents the base command when called without any subcommands.
var RootCmd = &cobra.Command{
	Use: "gored",
}

func init() {
	RootCmd.PersistentFlags().StringVarP(&cfgFilePath,
		"config-file", "f",
		func() (defaultCfgFilePath string) {
			var configDir string
			if runtime.GOOS == windows {
				configDir = filepath.Join(os.Getenv("APPDATA"), "gored")
			} else {
				configDir = filepath.Join(os.Getenv("HOME"), ".config", "gored")
			}
			return filepath.Join(configDir, "config.yml")
		}(),
		"path to the config file")
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() int {
	viper.SetConfigFile(cfgFilePath)
	if err := viper.ReadInConfig(); err != nil {
		fmt.Fprintf(os.Stderr, "failed in reading config file: %s", err)
		return exitNG
	}
	if err := viper.Unmarshal(&cfg); err != nil {
		fmt.Fprintf(os.Stderr, "failed in setting config parameters: %s", err)
		return exitNG
	}
	for _, param := range []string{"Endpoint", "Apikey", "Trackers", "Priorities"} {
		if !viper.IsSet(param) {
			fmt.Fprintf(os.Stdout, "failed in reading config parameter: %s must be specified", param)
			return exitNG
		}
	}
	if err := RootCmd.Execute(); err != nil {
		return exitNG
	}
	return exitOK
}
<commit_msg>Fix a variable name<commit_after>package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"

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

// gometalinter がそうしろって。。。
const windows string = "windows"

// 終了ステータスコード。
const (
	exitOK int = iota
	exitNG
)

// RootCmd represents the base command when called without any subcommands.
var RootCmd = &cobra.Command{
	Use: "gored",
}

func init() {
	RootCmd.PersistentFlags().StringVarP(&cfgFilePath,
		"config-file", "f",
		func() (defaultCfgFilePath string) {
			var cfgDir string
			if runtime.GOOS == windows {
				cfgDir = filepath.Join(os.Getenv("APPDATA"), "gored")
			} else {
				cfgDir = filepath.Join(os.Getenv("HOME"), ".config", "gored")
			}
			return filepath.Join(cfgDir, "config.yml")
		}(),
		"path to the config file")
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() int {
	viper.SetConfigFile(cfgFilePath)
	if err := viper.ReadInConfig(); err != nil {
		fmt.Fprintf(os.Stderr, "failed in reading config file: %s", err)
		return exitNG
	}
	if err := viper.Unmarshal(&cfg); err != nil {
		fmt.Fprintf(os.Stderr, "failed in setting config parameters: %s", err)
		return exitNG
	}
	for _, param := range []string{"Endpoint", "Apikey", "Trackers", "Priorities"} {
		if !viper.IsSet(param) {
			fmt.Fprintf(os.Stdout, "failed in reading config parameter: %s must be specified", param)
			return exitNG
		}
	}
	if err := RootCmd.Execute(); err != nil {
		return exitNG
	}
	return exitOK
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/dtan4/valec/aws"
	"github.com/dtan4/valec/lib"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

var (
	yamlExtRegexp = regexp.MustCompile(`\.[yY][aA]?[mM][lL]$`)
)

// syncCmd represents the sync command
var syncCmd = &cobra.Command{
	Use:   "sync CONFIGDIR [NAMESPACE]",
	Short: "Synchronize secrets between local file and DynamoDB",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return errors.New("Please specify config file.")
		}
		dirname := args[0]

		files, err := ioutil.ReadDir(dirname)
		if err != nil {
			return errors.Wrapf(err, "Failed to read directory. dirname=%s", dirname)
		}

		for _, file := range files {
			if strings.HasPrefix(file.Name(), ".") || !yamlExtRegexp.Match([]byte(file.Name())) {
				continue
			}

			filename := filepath.Join(dirname, file.Name())

			if err := syncFile(filename); err != nil {
				return errors.Wrapf(err, "Failed to synchronize configs. filename=%s", filename)
			}
		}

		return nil
	},
}

func syncFile(filename string) error {
	namespace := yamlExtRegexp.ReplaceAllString(filepath.Base(filename), "")
	fmt.Println(namespace)

	srcConfigs, err := lib.LoadConfigYAML(filename)
	if err != nil {
		return errors.Wrapf(err, "Failed to load configs. filename=%s", filename)
	}

	dstConfigs, err := aws.DynamoDB().ListConfigs(tableName, namespace)
	if err != nil {
		return errors.Wrapf(err, "Failed to retrieve configs. namespace=%s", namespace)
	}

	added, deleted := lib.CompareConfigList(srcConfigs, dstConfigs)
	red := color.New(color.FgRed)
	green := color.New(color.FgGreen)

	if len(deleted) > 0 {
		fmt.Printf("%  d configs of %s namespace will be deleted.\n", len(deleted), namespace)
		for _, config := range deleted {
			if noColor {
				fmt.Printf("    - %s\n", config.Key)
			} else {
				red.Printf("    - %s\n", config.Key)
			}
		}

		if !dryRun {
			if err := aws.DynamoDB().Delete(tableName, namespace, deleted); err != nil {
				return errors.Wrapf(err, "Failed to delete configs. namespace=%s", namespace)
			}

			fmt.Printf("  %d configs of %s namespace were successfully deleted.\n", len(deleted), namespace)
		}
	} else {
		fmt.Println("  No config will be deleted.")
	}

	if len(added) > 0 {
		fmt.Printf("  %d configs of %s namespace will be added.\n", len(added), namespace)
		for _, config := range added {
			if noColor {
				fmt.Printf("    + %s\n", config.Key)
			} else {
				green.Printf("    + %s\n", config.Key)
			}
		}

		if !dryRun {
			if err := aws.DynamoDB().Insert(tableName, namespace, added); err != nil {
				return errors.Wrapf(err, "Failed to insert configs. namespace=%s", namespace)
			}

			fmt.Printf("  %d configs of %s namespace were successfully added.\n", len(added), namespace)
		}
	} else {
		fmt.Println("  No config will be added.")
	}

	return nil
}

func init() {
	RootCmd.AddCommand(syncCmd)

	syncCmd.Flags().BoolVar(&dryRun, "dry-run", false, "Dry run")
}
<commit_msg>Modify sync command error message<commit_after>package cmd

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/dtan4/valec/aws"
	"github.com/dtan4/valec/lib"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

var (
	yamlExtRegexp = regexp.MustCompile(`\.[yY][aA]?[mM][lL]$`)
)

// syncCmd represents the sync command
var syncCmd = &cobra.Command{
	Use:   "sync CONFIGDIR [NAMESPACE]",
	Short: "Synchronize secrets between local file and DynamoDB",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return errors.New("Please specify config directory.")
		}
		dirname := args[0]

		files, err := ioutil.ReadDir(dirname)
		if err != nil {
			return errors.Wrapf(err, "Failed to read directory. dirname=%s", dirname)
		}

		for _, file := range files {
			if strings.HasPrefix(file.Name(), ".") || !yamlExtRegexp.Match([]byte(file.Name())) {
				continue
			}

			filename := filepath.Join(dirname, file.Name())

			if err := syncFile(filename); err != nil {
				return errors.Wrapf(err, "Failed to synchronize configs. filename=%s", filename)
			}
		}

		return nil
	},
}

func syncFile(filename string) error {
	namespace := yamlExtRegexp.ReplaceAllString(filepath.Base(filename), "")
	fmt.Println(namespace)

	srcConfigs, err := lib.LoadConfigYAML(filename)
	if err != nil {
		return errors.Wrapf(err, "Failed to load configs. filename=%s", filename)
	}

	dstConfigs, err := aws.DynamoDB().ListConfigs(tableName, namespace)
	if err != nil {
		return errors.Wrapf(err, "Failed to retrieve configs. namespace=%s", namespace)
	}

	added, deleted := lib.CompareConfigList(srcConfigs, dstConfigs)
	red := color.New(color.FgRed)
	green := color.New(color.FgGreen)

	if len(deleted) > 0 {
		fmt.Printf("%  d configs of %s namespace will be deleted.\n", len(deleted), namespace)
		for _, config := range deleted {
			if noColor {
				fmt.Printf("    - %s\n", config.Key)
			} else {
				red.Printf("    - %s\n", config.Key)
			}
		}

		if !dryRun {
			if err := aws.DynamoDB().Delete(tableName, namespace, deleted); err != nil {
				return errors.Wrapf(err, "Failed to delete configs. namespace=%s", namespace)
			}

			fmt.Printf("  %d configs of %s namespace were successfully deleted.\n", len(deleted), namespace)
		}
	} else {
		fmt.Println("  No config will be deleted.")
	}

	if len(added) > 0 {
		fmt.Printf("  %d configs of %s namespace will be added.\n", len(added), namespace)
		for _, config := range added {
			if noColor {
				fmt.Printf("    + %s\n", config.Key)
			} else {
				green.Printf("    + %s\n", config.Key)
			}
		}

		if !dryRun {
			if err := aws.DynamoDB().Insert(tableName, namespace, added); err != nil {
				return errors.Wrapf(err, "Failed to insert configs. namespace=%s", namespace)
			}

			fmt.Printf("  %d configs of %s namespace were successfully added.\n", len(added), namespace)
		}
	} else {
		fmt.Println("  No config will be added.")
	}

	return nil
}

func init() {
	RootCmd.AddCommand(syncCmd)

	syncCmd.Flags().BoolVar(&dryRun, "dry-run", false, "Dry run")
}
<|endoftext|>


<commit_before>package cmd

import (
	"io/ioutil"
	"log"
	"path"
	"time"

	"github.com/phil-mansfield/shellfish/cmd/catalog"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/logging"
	"github.com/phil-mansfield/shellfish/los/tree"
)

type TreeConfig struct {
}

var _ Mode = &TreeConfig{}

func (config *TreeConfig) ExampleConfig() string { return "" }

func (config *TreeConfig) ReadConfig(fname string) error { return nil }

func (config *TreeConfig) validate() error { return nil }

func (config *TreeConfig) Run(
	flags []string, gConfig *GlobalConfig, e *env.Environment, stdin []string,
) ([]string, error) {
	if logging.Mode != logging.Nil {
		log.Println(`
####################
## shellfish tree ##
####################`,
		)
	}
	var t time.Time
	if logging.Mode == logging.Performance {
		t = time.Now()
	}

	intCols, _, err := catalog.ParseCols(stdin, []int{0, 1}, []int{})
	if err != nil {
		return nil, err
	}
	inputIDs := intCols[0]

	trees, err := treeFiles(gConfig)
	if err != nil {
		return nil, err
	}

	idSets, snapSets, err := tree.HaloHistories(
		trees, inputIDs, e.SnapOffset(),
	)
	if err != nil {
		return nil, err
	}

	ids, snaps := []int{}, []int{}
	for i := range idSets {
		ids = append(ids, idSets[i]...)
		snaps = append(snaps, snapSets[i]...)
		// Sentinels:
		if i != len(idSets)-1 {
			ids = append(ids, -1)
			snaps = append(snaps, -1)
		}
	}

	lines := catalog.FormatCols(
		[][]int{ids, snaps}, [][]float64{}, []int{0, 1},
	)
	fLines := []string{}
	for i := range lines {
		if snaps[i] <= int(gConfig.SnapMin) &&
			snaps[i] >= int(gConfig.SnapMax) {

			fLines = append(fLines, lines[i])
		}
	}

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot"}, []string{}, []int{0, 1}, []int{1, 1},
	)

	if logging.Mode == logging.Performance {
		log.Printf("Time: %s", time.Since(t).String())
		log.Printf("Memory:\n%s", logging.MemString())
	}

	return append([]string{cString}, fLines...), nil
}

func treeFiles(gConfig *GlobalConfig) ([]string, error) {
	infos, err := ioutil.ReadDir(gConfig.TreeDir)
	if err != nil {
		return nil, err
	}

	names := []string{}
	for _, info := range infos {
		name := info.Name()
		n := len(name)
		// This is pretty hacky.
		if n > 4 && name[:5] == "tree_" && name[n-4:] == ".dat" {
			names = append(names, path.Join(gConfig.TreeDir, name))
		}
	}
	return names, nil
}
<commit_msg>Fixed bug in containment particle filtering.<commit_after>package cmd

import (
	"io/ioutil"
	"log"
	"path"
	"time"

	"github.com/phil-mansfield/shellfish/cmd/catalog"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/logging"
	"github.com/phil-mansfield/shellfish/los/tree"
	"github.com/phil-mansfield/shellfish/parse"
)

type TreeConfig struct {
	selectSnaps []int64
}

var _ Mode = &TreeConfig{}

func (config *TreeConfig) ExampleConfig() string {
	return `[tree.config]

#####################
## Optional Fields ##
#####################

# SelectSnaps is a list of all the snapshots which halo IDs should be
# output at. If not set, IDs will be output at all snapshots.
#
# SelectSnaps = 36, 47, 64, 77, 87, 100`
}

func (config *TreeConfig) ReadConfig(fname string) error {
	if fname == "" {
		return nil
	}

	vars := parse.NewConfigVars("stats.config")
	vars.Ints(&config.selectSnaps, "SelectSnaps", []int64{})

	if err := parse.ReadConfig(fname, vars); err != nil {
		return err
	}

	return nil
}

func (config *TreeConfig) validate() error { return nil }

func (config *TreeConfig) Run(
	flags []string, gConfig *GlobalConfig, e *env.Environment, stdin []string,
) ([]string, error) {
	if logging.Mode != logging.Nil {
		log.Println(`
####################
## shellfish tree ##
####################`,
		)
	}
	var t time.Time
	if logging.Mode == logging.Performance {
		t = time.Now()
	}

	intCols, _, err := catalog.ParseCols(stdin, []int{0, 1}, []int{})
	if err != nil {
		return nil, err
	}
	inputIDs := intCols[0]

	trees, err := treeFiles(gConfig)
	if err != nil {
		return nil, err
	}

	idSets, snapSets, err := tree.HaloHistories(
		trees, inputIDs, e.SnapOffset(),
	)
	if err != nil {
		return nil, err
	}

	ids, snaps := []int{}, []int{}
	for i := range idSets {
		ids = append(ids, idSets[i]...)
		snaps = append(snaps, snapSets[i]...)
		// Sentinels:
		if i != len(idSets)-1 {
			ids = append(ids, -1)
			snaps = append(snaps, -1)
		}
	}

	lines := catalog.FormatCols(
		[][]int{ids, snaps}, [][]float64{}, []int{0, 1},
	)
	fLines := []string{}
	for i := range lines {
		if snaps[i] <= int(gConfig.SnapMin) &&
			snaps[i] >= int(gConfig.SnapMax) {

			if len(config.selectSnaps) > 0 {
				for _, snap := range config.selectSnaps {
					if int(snap) == snaps[i] {
						fLines = append(fLines, lines[i])
					}
				}
			} else {
				fLines = append(fLines, lines[i])
			}
		}
	}

	cString := catalog.CommentString(
		[]string{"ID", "Snapshot"}, []string{}, []int{0, 1}, []int{1, 1},
	)

	if logging.Mode == logging.Performance {
		log.Printf("Time: %s", time.Since(t).String())
		log.Printf("Memory:\n%s", logging.MemString())
	}

	return append([]string{cString}, fLines...), nil
}

func treeFiles(gConfig *GlobalConfig) ([]string, error) {
	infos, err := ioutil.ReadDir(gConfig.TreeDir)
	if err != nil {
		return nil, err
	}

	names := []string{}
	for _, info := range infos {
		name := info.Name()
		n := len(name)
		// This is pretty hacky.
		if n > 4 && name[:5] == "tree_" && name[n-4:] == ".dat" {
			names = append(names, path.Join(gConfig.TreeDir, name))
		}
	}
	return names, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/aquasecurity/kube-bench/check"
	"github.com/fatih/color"
	"github.com/golang/glog"
)

var (
	// Print colors
	colors = map[check.State]*color.Color{
		check.PASS: color.New(color.FgGreen),
		check.FAIL: color.New(color.FgRed),
		check.WARN: color.New(color.FgYellow),
		check.INFO: color.New(color.FgBlue),
	}
)

func printlnWarn(msg string) {
	fmt.Fprintf(os.Stderr, "[%s] %s\n",
		colors[check.WARN].Sprintf("%s", check.WARN),
		msg,
	)
}

func sprintlnWarn(msg string) string {
	return fmt.Sprintf("[%s] %s",
		colors[check.WARN].Sprintf("%s", check.WARN),
		msg,
	)
}

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

func continueWithError(err error, msg string) string {
	if err != nil {
		glog.V(1).Info(err)
	}

	if msg != "" {
		fmt.Fprintf(os.Stderr, "%s\n", msg)
	}

	return ""
}

func cleanIDs(list string) []string {
	list = strings.Trim(list, ",")
	ids := strings.Split(list, ",")

	for _, id := range ids {
		id = strings.Trim(id, " ")
	}

	return ids
}

func verifyConf(confPath ...string) {
	var missing string

	for _, c := range confPath {
		if _, err := os.Stat(c); err != nil && os.IsNotExist(err) {
			continueWithError(err, "")
			missing += c + ", "
		}
	}

	if len(missing) > 0 {
		missing = strings.Trim(missing, ", ")
		printlnWarn(fmt.Sprintf("Missing kubernetes config files: %s", missing))
	}

}

func verifyBin(binPath ...string) {
	var binSlice []string
	var bin string
	var missing string
	var notRunning string

	// Construct proc name for ps(1)
	for _, b := range binPath {
		_, err := exec.LookPath(b)
		bin = bin + "," + b
		binSlice = append(binSlice, b)
		if err != nil {
			missing += b + ", "
			continueWithError(err, "")
		}
	}
	bin = strings.Trim(bin, ",")

	cmd := exec.Command("ps", "-C", bin, "-o", "cmd", "--no-headers")
	out, err := cmd.Output()
	if err != nil {
		continueWithError(fmt.Errorf("%s: %s", cmd.Args, err), "")
	}

	for _, b := range binSlice {
		matched := strings.Contains(string(out), b)

		if !matched {
			notRunning += b + ", "
		}
	}

	if len(missing) > 0 {
		missing = strings.Trim(missing, ", ")
		printlnWarn(fmt.Sprintf("Missing kubernetes binaries: %s", missing))
	}

	if len(notRunning) > 0 {
		notRunning = strings.Trim(notRunning, ", ")
		printlnWarn(fmt.Sprintf("Kubernetes binaries not running: %s", notRunning))
	}
}

func verifyKubeVersion(major string, minor string) {
	// These executables might not be on the user's path.

	_, err := exec.LookPath("kubectl")
	if err != nil {
		continueWithError(err, sprintlnWarn("Kubernetes version check skipped"))
		return
	}

	cmd := exec.Command("kubectl", "version")
	out, err := cmd.Output()
	if err != nil {
		s := fmt.Sprintf("Kubernetes version check skipped with error %v", err)
		continueWithError(err, sprintlnWarn(s))
		return
	}

	msg := checkVersion("Client", string(out), major, minor)
	if msg != "" {
		continueWithError(fmt.Errorf(msg), msg)
	}

	msg = checkVersion("Server", string(out), major, minor)
	if msg != "" {
		continueWithError(fmt.Errorf(msg), msg)
	}
}

var regexVersionMajor = regexp.MustCompile("Major:\"([0-9]+)\"")
var regexVersionMinor = regexp.MustCompile("Minor:\"([0-9]+)\"")

func checkVersion(x string, s string, expMajor string, expMinor string) string {
	regexVersion, err := regexp.Compile(x + " Version: version.Info{(.*)}")
	if err != nil {
		return fmt.Sprintf("Error checking Kubernetes version: %v", err)
	}

	ss := regexVersion.FindString(s)
	major := versionMatch(regexVersionMajor, ss)
	minor := versionMatch(regexVersionMinor, ss)
	if major == "" || minor == "" {
		return fmt.Sprintf("Couldn't find %s version from kubectl output '%s'", x, s)
	}

	if major != expMajor || minor != expMinor {
		return fmt.Sprintf("Unexpected %s version %s.%s", x, major, minor)
	}

	return ""
}

func versionMatch(r *regexp.Regexp, s string) string {
	match := r.FindStringSubmatch(s)
	if len(match) < 2 {
		return ""
	}
	return match[1]
}
<commit_msg>We don’t care whether the binaries are in our path or not, just whether they are running<commit_after>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/aquasecurity/kube-bench/check"
	"github.com/fatih/color"
	"github.com/golang/glog"
)

var (
	// Print colors
	colors = map[check.State]*color.Color{
		check.PASS: color.New(color.FgGreen),
		check.FAIL: color.New(color.FgRed),
		check.WARN: color.New(color.FgYellow),
		check.INFO: color.New(color.FgBlue),
	}
)

func printlnWarn(msg string) {
	fmt.Fprintf(os.Stderr, "[%s] %s\n",
		colors[check.WARN].Sprintf("%s", check.WARN),
		msg,
	)
}

func sprintlnWarn(msg string) string {
	return fmt.Sprintf("[%s] %s",
		colors[check.WARN].Sprintf("%s", check.WARN),
		msg,
	)
}

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

func continueWithError(err error, msg string) string {
	if err != nil {
		glog.V(1).Info(err)
	}

	if msg != "" {
		fmt.Fprintf(os.Stderr, "%s\n", msg)
	}

	return ""
}

func cleanIDs(list string) []string {
	list = strings.Trim(list, ",")
	ids := strings.Split(list, ",")

	for _, id := range ids {
		id = strings.Trim(id, " ")
	}

	return ids
}

func verifyConf(confPath ...string) {
	var missing string

	for _, c := range confPath {
		if _, err := os.Stat(c); err != nil && os.IsNotExist(err) {
			continueWithError(err, "")
			missing += c + ", "
		}
	}

	if len(missing) > 0 {
		missing = strings.Trim(missing, ", ")
		printlnWarn(fmt.Sprintf("Missing kubernetes config files: %s", missing))
	}

}

func verifyBin(binPath ...string) {
	var binSlice []string
	var bin string
	var missing string
	var notRunning string

	// Construct proc name for ps(1)
	for _, b := range binPath {
		_, err := exec.LookPath(b)
		bin = bin + "," + b
		binSlice = append(binSlice, b)
		if err != nil {
			missing += b + ", "
			continueWithError(err, "")
		}
	}
	bin = strings.Trim(bin, ",")

	cmd := exec.Command("ps", "-C", bin, "-o", "cmd", "--no-headers")
	out, err := cmd.Output()
	if err != nil {
		continueWithError(fmt.Errorf("%s: %s", cmd.Args, err), "")
	}

	for _, b := range binSlice {
		matched := strings.Contains(string(out), b)

		if !matched {
			notRunning += b + ", "
		}
	}

	if len(notRunning) > 0 {
		notRunning = strings.Trim(notRunning, ", ")
		printlnWarn(fmt.Sprintf("Kubernetes binaries not running: %s", notRunning))
	}
}

func verifyKubeVersion(major string, minor string) {
	// These executables might not be on the user's path.

	_, err := exec.LookPath("kubectl")
	if err != nil {
		continueWithError(err, sprintlnWarn("Kubernetes version check skipped"))
		return
	}

	cmd := exec.Command("kubectl", "version")
	out, err := cmd.Output()
	if err != nil {
		s := fmt.Sprintf("Kubernetes version check skipped with error %v", err)
		continueWithError(err, sprintlnWarn(s))
		return
	}

	msg := checkVersion("Client", string(out), major, minor)
	if msg != "" {
		continueWithError(fmt.Errorf(msg), msg)
	}

	msg = checkVersion("Server", string(out), major, minor)
	if msg != "" {
		continueWithError(fmt.Errorf(msg), msg)
	}
}

var regexVersionMajor = regexp.MustCompile("Major:\"([0-9]+)\"")
var regexVersionMinor = regexp.MustCompile("Minor:\"([0-9]+)\"")

func checkVersion(x string, s string, expMajor string, expMinor string) string {
	regexVersion, err := regexp.Compile(x + " Version: version.Info{(.*)}")
	if err != nil {
		return fmt.Sprintf("Error checking Kubernetes version: %v", err)
	}

	ss := regexVersion.FindString(s)
	major := versionMatch(regexVersionMajor, ss)
	minor := versionMatch(regexVersionMinor, ss)
	if major == "" || minor == "" {
		return fmt.Sprintf("Couldn't find %s version from kubectl output '%s'", x, s)
	}

	if major != expMajor || minor != expMinor {
		return fmt.Sprintf("Unexpected %s version %s.%s", x, major, minor)
	}

	return ""
}

func versionMatch(r *regexp.Regexp, s string) string {
	match := r.FindStringSubmatch(s)
	if len(match) < 2 {
		return ""
	}
	return match[1]
}
<|endoftext|>