<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/alecthomas/kingpin"
	"github.com/sirupsen/logrus"
	"github.com/versent/saml2aws/cmd/saml2aws/commands"
	"github.com/versent/saml2aws/pkg/flags"
)

var (
	// Version app version
	Version = "1.0.0"
)

// The `cmdLineList` type is used to make a `[]string` meet the requiements
// of the kingpin.Value interface
type cmdLineList []string

func (i *cmdLineList) Set(value string) error {
	*i = append(*i, value)

	return nil
}

func (i *cmdLineList) String() string {
	return ""
}

func (i *cmdLineList) IsCumulative() bool {
	return true
}

func buildCmdList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*cmdLineList)(target))
	return
}

func main() {

	app := kingpin.New("saml2aws", "A command line tool to help with SAML access to the AWS token service.")
	app.Version(Version)

	// Settings not related to commands
	verbose := app.Flag("verbose", "Enable verbose logging").Bool()
	provider := app.Flag("provider", "This flag is obsolete. See: https://github.com/Versent/saml2aws#configuring-idp-accounts").Short('i').Enum("ADFS", "ADFS2", "Ping", "JumpCloud", "Okta", "OneLogin", "PSU", "KeyCloak")

	// Common (to all commands) settings
	commonFlags := new(flags.CommonFlags)
	app.Flag("idp-account", "The name of the configured IDP account. (env: SAML2AWS_IDP_ACCOUNT)").Envar("SAML2AWS_IDP_ACCOUNT").Short('a').Default("default").StringVar(&commonFlags.IdpAccount)
	app.Flag("idp-provider", "The configured IDP provider. (env: SAML2AWS_IDP_PROVIDER)").Envar("SAML2AWS_IDP_PROVIDER").EnumVar(&commonFlags.IdpProvider, "ADFS", "ADFS2", "Ping", "JumpCloud", "Okta", "OneLogin", "PSU", "KeyCloak")
	app.Flag("mfa", "The name of the mfa. (env: SAML2AWS_MFA)").Envar("SAML2AWS_MFA").StringVar(&commonFlags.MFA)
	app.Flag("skip-verify", "Skip verification of server certificate.").Short('s').BoolVar(&commonFlags.SkipVerify)
	app.Flag("url", "The URL of the SAML IDP server used to login. (env: SAML2AWS_URL)").Envar("SAML2AWS_URL").StringVar(&commonFlags.URL)
	app.Flag("username", "The username used to login. (env: SAML2AWS_USERNAME)").Envar("SAML2AWS_USERNAME").StringVar(&commonFlags.Username)
	app.Flag("password", "The password used to login. (env: SAML2AWS_PASSWORD)").Envar("SAML2AWS_PASSWORD").StringVar(&commonFlags.Password)
	app.Flag("mfa-token", "The current MFA token (supported in Keycloak, ADFS). (env: SAML2AWS_MFA_TOKEN)").Envar("SAML2AWS_MFA_TOKEN").StringVar(&commonFlags.MFAToken)
	app.Flag("role", "The ARN of the role to assume. (env: SAML2AWS_ROLE)").Envar("SAML2AWS_ROLE").StringVar(&commonFlags.RoleArn)
	app.Flag("aws-urn", "The URN used by SAML when you login. (env: SAML2AWS_AWS_URN)").Envar("SAML2AWS_AWS_URN").StringVar(&commonFlags.AmazonWebservicesURN)
	app.Flag("skip-prompt", "Skip prompting for parameters during login.").BoolVar(&commonFlags.SkipPrompt)
	app.Flag("session-duration", "The duration of your AWS Session. (env: SAML2AWS_SESSION_DURATION)").Envar("SAML2AWS_SESSION_DURATION").IntVar(&commonFlags.SessionDuration)

	// `configure` command and settings
	cmdConfigure := app.Command("configure", "Configure a new IDP account.")
	cmdConfigure.Flag("app-id", "OneLogin app id required for SAML assertion. (env: ONELOGIN_APP_ID)").Envar("ONELOGIN_APP_ID").StringVar(&commonFlags.AppID)
	cmdConfigure.Flag("client-id", "OneLogin client id, used to generate API access token. (env: ONELOGIN_CLIENT_ID)").Envar("ONELOGIN_CLIENT_ID").StringVar(&commonFlags.ClientID)
	cmdConfigure.Flag("client-secret", "OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)").Envar("ONELOGIN_CLIENT_SECRET").StringVar(&commonFlags.ClientSecret)
	cmdConfigure.Flag("subdomain", "OneLogin subdomain of your company account. (env: ONELOGIN_SUBDOMAIN)").Envar("ONELOGIN_SUBDOMAIN").StringVar(&commonFlags.Subdomain)
	configFlags := commonFlags

	// `login` command and settings
	cmdLogin := app.Command("login", "Login to a SAML 2.0 IDP and convert the SAML assertion to an STS token.")
	loginFlags := new(flags.LoginExecFlags)
	loginFlags.CommonFlags = commonFlags
	cmdLogin.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Short('p').Envar("SAML2AWS_PROFILE").StringVar(&commonFlags.Profile)
	cmdLogin.Flag("force", "Refresh credentials even if not expired.").BoolVar(&loginFlags.Force)

	// `exec` command and settings
	cmdExec := app.Command("exec", "Exec the supplied command with env vars from STS token.")
	execFlags := new(flags.LoginExecFlags)
	execFlags.CommonFlags = commonFlags
	cmdExec.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Envar("SAML2AWS_PROFILE").Short('p').StringVar(&commonFlags.Profile)
	cmdLine := buildCmdList(cmdExec.Arg("command", "The command to execute."))

	// `list` command and settings
	cmdListRoles := app.Command("list-roles", "List available role ARNs.")
	listRolesFlags := new(flags.LoginExecFlags)
	listRolesFlags.CommonFlags = commonFlags

	// `script` command and settings
	cmdScript := app.Command("script", "Emit a script that will export environment variables.")
	scriptFlags := new(flags.LoginExecFlags)
	scriptFlags.CommonFlags = commonFlags
	cmdScript.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Envar("SAML2AWS_PROFILE").Short('p').StringVar(&commonFlags.Profile)
	var shell string
	cmdScript.
		Flag("shell", "Type of shell environment. Options include: bash, powershell, fish").
		Default("bash").
		EnumVar(&shell, "bash", "powershell", "fish")

	// Trigger the parsing of the command line inputs via kingpin
	command := kingpin.MustParse(app.Parse(os.Args[1:]))

	// will leave this here for a while during upgrade process
	if *provider != "" {
		fmt.Println("The --provider flag has been replaced with a new configure command. See https://github.com/Versent/saml2aws#adding-idp-accounts")
		os.Exit(1)
	}

	errtpl := "%v\n"
	if *verbose {
		logrus.SetLevel(logrus.DebugLevel)
		errtpl = "%+v\n"
	}

	logrus.WithField("command", command).Debug("Running")

	var err error
	switch command {
	case cmdScript.FullCommand():
		err = commands.Script(scriptFlags, shell)
	case cmdLogin.FullCommand():
		err = commands.Login(loginFlags)
	case cmdExec.FullCommand():
		err = commands.Exec(execFlags, *cmdLine)
	case cmdListRoles.FullCommand():
		err = commands.ListRoles(listRolesFlags)
	case cmdConfigure.FullCommand():
		err = commands.Configure(configFlags)
	}

	if err != nil {
		fmt.Printf(errtpl, err)
		os.Exit(1)
	}
}
<commit_msg>Set default http transport settings<commit_after>package main

import (
	"fmt"
	"os"
	"net/http"
	"crypto/tls"

	"github.com/alecthomas/kingpin"
	"github.com/sirupsen/logrus"
	"github.com/versent/saml2aws/cmd/saml2aws/commands"
	"github.com/versent/saml2aws/pkg/flags"
)

var (
	// Version app version
	Version = "1.0.0"
)

// The `cmdLineList` type is used to make a `[]string` meet the requiements
// of the kingpin.Value interface
type cmdLineList []string

func (i *cmdLineList) Set(value string) error {
	*i = append(*i, value)

	return nil
}

func (i *cmdLineList) String() string {
	return ""
}

func (i *cmdLineList) IsCumulative() bool {
	return true
}

func buildCmdList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*cmdLineList)(target))
	return
}

func main() {

	app := kingpin.New("saml2aws", "A command line tool to help with SAML access to the AWS token service.")
	app.Version(Version)

	// Settings not related to commands
	verbose := app.Flag("verbose", "Enable verbose logging").Bool()
	provider := app.Flag("provider", "This flag is obsolete. See: https://github.com/Versent/saml2aws#configuring-idp-accounts").Short('i').Enum("ADFS", "ADFS2", "Ping", "JumpCloud", "Okta", "OneLogin", "PSU", "KeyCloak")

	// Common (to all commands) settings
	commonFlags := new(flags.CommonFlags)
	app.Flag("idp-account", "The name of the configured IDP account. (env: SAML2AWS_IDP_ACCOUNT)").Envar("SAML2AWS_IDP_ACCOUNT").Short('a').Default("default").StringVar(&commonFlags.IdpAccount)
	app.Flag("idp-provider", "The configured IDP provider. (env: SAML2AWS_IDP_PROVIDER)").Envar("SAML2AWS_IDP_PROVIDER").EnumVar(&commonFlags.IdpProvider, "ADFS", "ADFS2", "Ping", "JumpCloud", "Okta", "OneLogin", "PSU", "KeyCloak")
	app.Flag("mfa", "The name of the mfa. (env: SAML2AWS_MFA)").Envar("SAML2AWS_MFA").StringVar(&commonFlags.MFA)
	app.Flag("skip-verify", "Skip verification of server certificate.").Short('s').BoolVar(&commonFlags.SkipVerify)
	app.Flag("url", "The URL of the SAML IDP server used to login. (env: SAML2AWS_URL)").Envar("SAML2AWS_URL").StringVar(&commonFlags.URL)
	app.Flag("username", "The username used to login. (env: SAML2AWS_USERNAME)").Envar("SAML2AWS_USERNAME").StringVar(&commonFlags.Username)
	app.Flag("password", "The password used to login. (env: SAML2AWS_PASSWORD)").Envar("SAML2AWS_PASSWORD").StringVar(&commonFlags.Password)
	app.Flag("mfa-token", "The current MFA token (supported in Keycloak, ADFS). (env: SAML2AWS_MFA_TOKEN)").Envar("SAML2AWS_MFA_TOKEN").StringVar(&commonFlags.MFAToken)
	app.Flag("role", "The ARN of the role to assume. (env: SAML2AWS_ROLE)").Envar("SAML2AWS_ROLE").StringVar(&commonFlags.RoleArn)
	app.Flag("aws-urn", "The URN used by SAML when you login. (env: SAML2AWS_AWS_URN)").Envar("SAML2AWS_AWS_URN").StringVar(&commonFlags.AmazonWebservicesURN)
	app.Flag("skip-prompt", "Skip prompting for parameters during login.").BoolVar(&commonFlags.SkipPrompt)
	app.Flag("session-duration", "The duration of your AWS Session. (env: SAML2AWS_SESSION_DURATION)").Envar("SAML2AWS_SESSION_DURATION").IntVar(&commonFlags.SessionDuration)

	// `configure` command and settings
	cmdConfigure := app.Command("configure", "Configure a new IDP account.")
	cmdConfigure.Flag("app-id", "OneLogin app id required for SAML assertion. (env: ONELOGIN_APP_ID)").Envar("ONELOGIN_APP_ID").StringVar(&commonFlags.AppID)
	cmdConfigure.Flag("client-id", "OneLogin client id, used to generate API access token. (env: ONELOGIN_CLIENT_ID)").Envar("ONELOGIN_CLIENT_ID").StringVar(&commonFlags.ClientID)
	cmdConfigure.Flag("client-secret", "OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)").Envar("ONELOGIN_CLIENT_SECRET").StringVar(&commonFlags.ClientSecret)
	cmdConfigure.Flag("subdomain", "OneLogin subdomain of your company account. (env: ONELOGIN_SUBDOMAIN)").Envar("ONELOGIN_SUBDOMAIN").StringVar(&commonFlags.Subdomain)
	configFlags := commonFlags

	// `login` command and settings
	cmdLogin := app.Command("login", "Login to a SAML 2.0 IDP and convert the SAML assertion to an STS token.")
	loginFlags := new(flags.LoginExecFlags)
	loginFlags.CommonFlags = commonFlags
	cmdLogin.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Short('p').Envar("SAML2AWS_PROFILE").StringVar(&commonFlags.Profile)
	cmdLogin.Flag("force", "Refresh credentials even if not expired.").BoolVar(&loginFlags.Force)

	// `exec` command and settings
	cmdExec := app.Command("exec", "Exec the supplied command with env vars from STS token.")
	execFlags := new(flags.LoginExecFlags)
	execFlags.CommonFlags = commonFlags
	cmdExec.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Envar("SAML2AWS_PROFILE").Short('p').StringVar(&commonFlags.Profile)
	cmdLine := buildCmdList(cmdExec.Arg("command", "The command to execute."))

	// `list` command and settings
	cmdListRoles := app.Command("list-roles", "List available role ARNs.")
	listRolesFlags := new(flags.LoginExecFlags)
	listRolesFlags.CommonFlags = commonFlags

	// `script` command and settings
	cmdScript := app.Command("script", "Emit a script that will export environment variables.")
	scriptFlags := new(flags.LoginExecFlags)
	scriptFlags.CommonFlags = commonFlags
	cmdScript.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Envar("SAML2AWS_PROFILE").Short('p').StringVar(&commonFlags.Profile)
	var shell string
	cmdScript.
		Flag("shell", "Type of shell environment. Options include: bash, powershell, fish").
		Default("bash").
		EnumVar(&shell, "bash", "powershell", "fish")

	// Trigger the parsing of the command line inputs via kingpin
	command := kingpin.MustParse(app.Parse(os.Args[1:]))

	// will leave this here for a while during upgrade process
	if *provider != "" {
		fmt.Println("The --provider flag has been replaced with a new configure command. See https://github.com/Versent/saml2aws#adding-idp-accounts")
		os.Exit(1)
	}

	errtpl := "%v\n"
	if *verbose {
		logrus.SetLevel(logrus.DebugLevel)
		errtpl = "%+v\n"
	}

	// Set the default transport settings so all http clients will pick them up.
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: commonFlags.SkipVerify,}
	http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment

	logrus.WithField("command", command).Debug("Running")

	var err error
	switch command {
	case cmdScript.FullCommand():
		err = commands.Script(scriptFlags, shell)
	case cmdLogin.FullCommand():
		err = commands.Login(loginFlags)
	case cmdExec.FullCommand():
		err = commands.Exec(execFlags, *cmdLine)
	case cmdListRoles.FullCommand():
		err = commands.ListRoles(listRolesFlags)
	case cmdConfigure.FullCommand():
		err = commands.Configure(configFlags)
	}

	if err != nil {
		fmt.Printf(errtpl, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/moov-io/ach"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"time"
)

var (
	fPath      = flag.String("fPath", "", "File Path")
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
)

// main creates an ACH File with 4 batches of SEC Code PPD.
// Each batch contains an EntryAddendaCount of 2500.
func main() {
	flag.Parse()

	path := filepath.Join(*fPath, time.Now().UTC().Format("200601021504")+".ach")
	write(path)
}

func write(path string) {
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	f, err := os.Create(path)
	if err != nil {
		fmt.Printf("%T: %s", err, err)
	}

	// To create a file
	fh := ach.NewFileHeader()
	fh.ImmediateDestination = "231380104"
	fh.ImmediateOrigin = "121042882"
	fh.FileCreationDate = time.Now()
	fh.ImmediateDestinationName = "Citadel"
	fh.ImmediateOriginName = "Wells Fargo"
	file := ach.NewFile()
	file.SetHeader(fh)

	// Create 4 Batches of SEC Code PPD
	for i := 0; i < 4; i++ {
		bh := ach.NewBatchHeader()
		bh.ServiceClassCode = 200
		bh.CompanyName = "Wells Fargo"
		bh.CompanyIdentification = "121042882"
		bh.StandardEntryClassCode = "PPD"
		bh.CompanyEntryDescription = "Trans. Description"
		bh.EffectiveEntryDate = time.Now().AddDate(0, 0, 1)
		bh.ODFIIdentification = "121042882"

		batch, _ := ach.NewBatch(bh)

		// Create Entry
		entrySeq := 0
		for i := 0; i < 1250; i++ {
			entrySeq = entrySeq + 1

			entryEntrySeq := ach.NewEntryDetail()
			entryEntrySeq.TransactionCode = 22
			entryEntrySeq.SetRDFI("231380104")
			entryEntrySeq.DFIAccountNumber = "81967038518"
			entryEntrySeq.Amount = 100000
			//entryEntrySeq.IndividualName = randomdata.FullName(randomdata.RandomGender)
			entryEntrySeq.IndividualName = "Steven Tander"
			entryEntrySeq.SetTraceNumber(bh.ODFIIdentification, entrySeq)
			//entryEntrySeq.IdentificationNumber = "#" + randomdata.RandStringRunes(13) + "#"
			entryEntrySeq.IdentificationNumber = "#83738AB#"
			entryEntrySeq.Category = ach.CategoryForward

			// Add addenda record for an entry
			addendaEntrySeq := ach.NewAddenda05()
			addendaEntrySeq.PaymentRelatedInformation = "bonus pay for amazing work on #OSS"
			entryEntrySeq.AddAddenda(addendaEntrySeq)

			// Add entries
			batch.AddEntry(entryEntrySeq)

		}

		// Create the batch.
		if err := batch.Create(); err != nil {
			fmt.Printf("%T: %s", err, err)
		}

		// Add batch to the file
		file.AddBatch(batch)
	}

	// Create the file
	if err := file.Create(); err != nil {
		fmt.Printf("%T: %s", err, err)
	}

	// Write to a file
	w := ach.NewWriter(f)
	if err := w.Write(file); err != nil {
		fmt.Printf("%T: %s", err, err)
	}
	w.Flush()
	if err := f.Close(); err != nil {
		fmt.Println(err.Error())
	}
}
<commit_msg>cmd/writeACH: add -json to output JSON instead of plaintext ACH file<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/moov-io/ach"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"time"
)

var (
	fPath      = flag.String("fPath", "", "File Path")
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

	// output formats
	flagJson = flag.Bool("json", false, "Output file in json")
)

// main creates an ACH File with 4 batches of SEC Code PPD.
// Each batch contains an EntryAddendaCount of 2500.
func main() {
	flag.Parse()

	filename := time.Now().UTC().Format("200601021504")
	if *flagJson {
		filename += ".json"
	} else {
		filename += ".ach"
	}

	path := filepath.Join(*fPath, filename)
	write(path)
}

func write(path string) {
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	f, err := os.Create(path)
	if err != nil {
		fmt.Printf("%T: %s", err, err)
	}

	// To create a file
	fh := ach.NewFileHeader()
	fh.ImmediateDestination = "231380104"
	fh.ImmediateOrigin = "121042882"
	fh.FileCreationDate = time.Now()
	fh.ImmediateDestinationName = "Citadel"
	fh.ImmediateOriginName = "Wells Fargo"
	file := ach.NewFile()
	file.SetHeader(fh)

	// Create 4 Batches of SEC Code PPD
	for i := 0; i < 4; i++ {
		bh := ach.NewBatchHeader()
		bh.ServiceClassCode = 200
		bh.CompanyName = "Wells Fargo"
		bh.CompanyIdentification = "121042882"
		bh.StandardEntryClassCode = "PPD"
		bh.CompanyEntryDescription = "Trans. Description"
		bh.EffectiveEntryDate = time.Now().AddDate(0, 0, 1)
		bh.ODFIIdentification = "121042882"

		batch, _ := ach.NewBatch(bh)

		// Create Entry
		entrySeq := 0
		for i := 0; i < 1250; i++ {
			entrySeq = entrySeq + 1

			entryEntrySeq := ach.NewEntryDetail()
			entryEntrySeq.TransactionCode = 22
			entryEntrySeq.SetRDFI("231380104")
			entryEntrySeq.DFIAccountNumber = "81967038518"
			entryEntrySeq.Amount = 100000
			//entryEntrySeq.IndividualName = randomdata.FullName(randomdata.RandomGender)
			entryEntrySeq.IndividualName = "Steven Tander"
			entryEntrySeq.SetTraceNumber(bh.ODFIIdentification, entrySeq)
			//entryEntrySeq.IdentificationNumber = "#" + randomdata.RandStringRunes(13) + "#"
			entryEntrySeq.IdentificationNumber = "#83738AB#"
			entryEntrySeq.Category = ach.CategoryForward

			// Add addenda record for an entry
			addendaEntrySeq := ach.NewAddenda05()
			addendaEntrySeq.PaymentRelatedInformation = "bonus pay for amazing work on #OSS"
			entryEntrySeq.AddAddenda(addendaEntrySeq)

			// Add entries
			batch.AddEntry(entryEntrySeq)

		}

		// Create the batch.
		if err := batch.Create(); err != nil {
			fmt.Printf("%T: %s", err, err)
		}

		// Add batch to the file
		file.AddBatch(batch)
	}

	// Create the file
	if err := file.Create(); err != nil {
		fmt.Printf("%T: %s", err, err)
	}

	// Write to a file
	if *flagJson {
		// Write in JSON format
		if err := json.NewEncoder(f).Encode(file); err != nil {
			fmt.Printf("%T: %s", err, err)
		}
	} else {
		// Write in ACH plain text format
		w := ach.NewWriter(f)
		if err := w.Write(file); err != nil {
			fmt.Printf("%T: %s", err, err)
		}
		w.Flush()
	}

	if err := f.Close(); err != nil {
		fmt.Println(err.Error())
	}

	fmt.Printf("Wrote %s\n", path)
}
<|endoftext|>


<commit_before>package cmd

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/digitalocean/vulcan/config/zookeeper"
	pconfig "github.com/prometheus/prometheus/config"
	"github.com/samuel/go-zookeeper/zk"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	// ErrNoScrapeConfig is when the provided config omits or has a zero list of scrape configs
	ErrNoScrapeConfig = errors.New("no scrape config found")
	// ErrMultipleScrapeConfig is when the provided config has more than one scrape configs
	ErrMultipleScrapeConfig = errors.New("multiple scrape configs found")
	// ErrNoArgs is when the command line expected an arg but none was provided
	ErrNoArgs = errors.New("no args")
	// ErrMultipleArgs is when the command line expected one arge but multiple were provided
	ErrMultipleArgs = errors.New("multiple arguments in single argument command")
)

// Job returns an instantiated job subcommand
func Job() *cobra.Command {
	job := &cobra.Command{
		Use:   "job",
		Short: "job (set/delete/list) allows the operator to configure vulcan jobs",
	}

	job.PersistentFlags().String("zk-servers", "", "comma-separated list of zookeeper servers")
	job.PersistentFlags().String("zk-root", "/vulcan", "zookeeper root namespace")

	set := &cobra.Command{
		Use:   "set",
		Short: "set reads a job yaml description from stdin and sets it in zookeeper",
		RunE: func(cmd *cobra.Command, args []string) error {
			log.SetLevel(log.DebugLevel)
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			b, err := ioutil.ReadAll(os.Stdin)
			if err != nil {
				return err
			}
			c, err := pconfig.Load(string(b))
			if err != nil {
				return err
			}
			if len(c.ScrapeConfigs) == 0 {
				return ErrNoScrapeConfig
			}
			if len(c.ScrapeConfigs) > 1 {
				return ErrMultipleScrapeConfig
			}
			sc := c.ScrapeConfigs[0]
			name := sc.JobName

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			err = s.Set(name, b)
			if err != nil {
				return err
			}
			return nil
		},
	}

	list := &cobra.Command{
		Use:   "list",
		Short: "list jobs",
		RunE: func(cmd *cobra.Command, args []string) error {
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			names, err := s.List()
			if err != nil {
				return err
			}
			for _, name := range names {
				fmt.Println(name)
			}
			return nil
		},
	}

	delete := &cobra.Command{
		Use:   "delete",
		Short: "deletes a sigle job",
		RunE: func(cmd *cobra.Command, args []string) error {
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			if len(args) == 0 {
				return ErrNoArgs
			}
			if len(args) > 1 {
				return ErrMultipleArgs
			}

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			err = s.Delete(args[0])
			if err != nil {
				return err
			}
			return nil
		},
	}

	job.AddCommand(set)
	job.AddCommand(list)
	job.AddCommand(delete)

	return job
}
<commit_msg>job: adds get subcommand<commit_after>package cmd

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/digitalocean/vulcan/config/zookeeper"
	pconfig "github.com/prometheus/prometheus/config"
	"github.com/samuel/go-zookeeper/zk"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	// ErrNoScrapeConfig is when the provided config omits or has a zero list of scrape configs
	ErrNoScrapeConfig = errors.New("no scrape config found")
	// ErrMultipleScrapeConfig is when the provided config has more than one scrape configs
	ErrMultipleScrapeConfig = errors.New("multiple scrape configs found")
	// ErrNoArgs is when the command line expected an arg but none was provided
	ErrNoArgs = errors.New("no args")
	// ErrMultipleArgs is when the command line expected one arge but multiple were provided
	ErrMultipleArgs = errors.New("multiple arguments in single argument command")
)

// Job returns an instantiated job subcommand
func Job() *cobra.Command {
	job := &cobra.Command{
		Use:   "job",
		Short: "job (set/delete/list/get) allows the operator to configure vulcan jobs",
	}

	job.PersistentFlags().String("zk-servers", "", "comma-separated list of zookeeper servers")
	job.PersistentFlags().String("zk-root", "/vulcan", "zookeeper root namespace")

	set := &cobra.Command{
		Use:   "set",
		Short: "set reads a job yaml description from stdin and sets it in zookeeper",
		RunE: func(cmd *cobra.Command, args []string) error {
			log.SetLevel(log.DebugLevel)
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			b, err := ioutil.ReadAll(os.Stdin)
			if err != nil {
				return err
			}
			c, err := pconfig.Load(string(b))
			if err != nil {
				return err
			}
			if len(c.ScrapeConfigs) == 0 {
				return ErrNoScrapeConfig
			}
			if len(c.ScrapeConfigs) > 1 {
				return ErrMultipleScrapeConfig
			}
			sc := c.ScrapeConfigs[0]
			name := sc.JobName

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			err = s.Set(name, b)
			if err != nil {
				return err
			}
			return nil
		},
	}

	list := &cobra.Command{
		Use:   "list",
		Short: "list jobs",
		RunE: func(cmd *cobra.Command, args []string) error {
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			names, err := s.List()
			if err != nil {
				return err
			}
			for _, name := range names {
				fmt.Println(name)
			}
			return nil
		},
	}

	delete := &cobra.Command{
		Use:   "delete",
		Short: "deletes a sigle job",
		RunE: func(cmd *cobra.Command, args []string) error {
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			if len(args) == 0 {
				return ErrNoArgs
			}
			if len(args) > 1 {
				return ErrMultipleArgs
			}

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			err = s.Delete(args[0])
			if err != nil {
				return err
			}
			return nil
		},
	}

	get := &cobra.Command{
		Use:   "get",
		Short: "gets a sigle job",
		RunE: func(cmd *cobra.Command, args []string) error {
			// bind pflags to viper so they are settable by env variables
			cmd.Flags().VisitAll(func(f *pflag.Flag) {
				viper.BindPFlag(f.Name, f)
			})

			if len(args) == 0 {
				return ErrNoArgs
			}
			if len(args) > 1 {
				return ErrMultipleArgs
			}

			client, _, err := zk.Connect(strings.Split(viper.GetString("zk-servers"), ","), time.Second*2)
			if err != nil {
				return err
			}
			s, err := zookeeper.NewStore(&zookeeper.Config{
				Root:   viper.GetString("zk-root"),
				Client: client,
			})
			if err != nil {
				return err
			}

			b, err := s.Get(args[0])
			if err != nil {
				return err
			}
			_, err = io.Copy(os.Stdout, bytes.NewReader(b))
			if err != nil {
				return err
			}
			return nil
		},
	}

	job.AddCommand(set)
	job.AddCommand(list)
	job.AddCommand(delete)
	job.AddCommand(get)

	return job
}
<|endoftext|>


<commit_before>package cmd_runner

import (
	"fmt"

	"github.com/centurylinkcloud/clc-go-cli/auth"
	"github.com/centurylinkcloud/clc-go-cli/command_loader"
	"github.com/centurylinkcloud/clc-go-cli/commands"
	"github.com/centurylinkcloud/clc-go-cli/config"
	"github.com/centurylinkcloud/clc-go-cli/formatter_provider"
	"github.com/centurylinkcloud/clc-go-cli/model_adjuster"
	"github.com/centurylinkcloud/clc-go-cli/model_loader"
	"github.com/centurylinkcloud/clc-go-cli/model_validator"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/options"
	"github.com/centurylinkcloud/clc-go-cli/parser"
	"github.com/centurylinkcloud/clc-go-cli/state"
)

func Run(args []string) string {
	if len(args) == 0 {
		return help()
	}
	if len(args) == 1 && args[0] == "--help" {
		return help()
	}
	cmdArg := ""
	optionArgs := args[1:]
	if len(args) >= 2 {
		cmdArg = args[1]
		optionArgs = args[2:]
	}
	resource, err := command_loader.LoadResource(args[0])
	if err != nil {
		return err.Error()
	}
	cmd, err := command_loader.LoadCommand(resource, cmdArg)
	if err != nil {
		if cmdArg == "--help" {
			return command_loader.GetCommandsWithDescriptions(resource)
		}
		return err.Error()
	}
	if cmd.Command() == "" {
		optionArgs = args[1:]
	}
	parsedArgs, err := parser.ParseArguments(optionArgs)
	if err != nil {
		return err.Error()
	}
	yes, filename, err := options.AreToBeTakenFromFile(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if yes {
		parsedArgs, err = state.ArgumentsFromJSON(filename)
		if err != nil {
			return err.Error()
		}
	}
	yes, err = options.AreToBeSaved(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if yes {
		output, err := state.ArgumentsToJSON(parsedArgs, cmd.InputModel())
		if err != nil {
			return err.Error()
		}
		return output
	}
	options, err := options.ExtractFrom(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if options.Help {
		return cmd.ShowHelp()
	}
	conf, err := config.LoadConfig()
	if err != nil {
		return err.Error()
	}
	if cmd.Resource() == "login" {
		return cmd.(*commands.Login).Login(options, conf)
	}
	err = model_loader.LoadModel(parsedArgs, cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	datacenter.ApplyDefault(cmd.InputModel(), conf)
	err = model_validator.ValidateModel(cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	err = model_adjuster.ApplyDefaultBehaviour(cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	if cmd.IsOffline() {
		res, err := cmd.ExecuteOffline()
		if err != nil {
			return err.Error()
		}
		return res
	}
	cn, err := auth.AuthenticateCommand(options, conf)
	if err != nil {
		return err.Error()
	}
	err = model_adjuster.InferID(cmd.InputModel(), cn)
	if err != nil {
		return err.Error()
	}
	err = cmd.Execute(cn)
	if err != nil {
		return err.Error()
	}
	err = state.SaveLastResult(cmd.OutputModel())
	if err != nil {
		return err.Error()
	}
	f, err := formatter_provider.GetOutputFormatter(options, conf)
	if err != nil {
		return err.Error()
	}
	outputModel := cmd.OutputModel()
	if messagePtr, ok := outputModel.(*string); ok {
		return *messagePtr
	}
	detyped, err := parser.ConvertToMapOrSlice(outputModel)
	if err != nil {
		return err.Error()
	}
	if options.Filter != "" {
		filtered, err := parser.ParseFilter(detyped, options.Filter)
		if err != nil {
			return err.Error()
		} else if filtered == nil {
			return "No results found for the given filter."
		} else {
			detyped = filtered
		}
	}
	if options.Query != "" {
		queried, err := parser.ParseQuery(detyped, options.Query)
		if err != nil {
			return err.Error()
		} else if queried == nil {
			return "No results found for the given query."
		} else {
			detyped = queried
		}
	}
	output, err := f.FormatOutput(detyped)
	if err != nil {
		return err.Error()
	}
	return output
}

func help() string {
	res := `Usage: clc <resource> [<command>] [options and parameters]

clc <resource> --help
    get a list of all available commands for the given
    resource if any or to get a direct resource description
clc <resource> <command> --help
    get a command description and a list of all available
    parameters for the given command

Available resources:

`
	resources := command_loader.GetResources()
	for _, rsr := range resources {
		res += fmt.Sprintf("\t%v\n", rsr)
	}
	return res
}
<commit_msg>Show available resources sorted<commit_after>package cmd_runner

import (
	"fmt"
	"sort"

	"github.com/centurylinkcloud/clc-go-cli/auth"
	"github.com/centurylinkcloud/clc-go-cli/command_loader"
	"github.com/centurylinkcloud/clc-go-cli/commands"
	"github.com/centurylinkcloud/clc-go-cli/config"
	"github.com/centurylinkcloud/clc-go-cli/formatter_provider"
	"github.com/centurylinkcloud/clc-go-cli/model_adjuster"
	"github.com/centurylinkcloud/clc-go-cli/model_loader"
	"github.com/centurylinkcloud/clc-go-cli/model_validator"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/options"
	"github.com/centurylinkcloud/clc-go-cli/parser"
	"github.com/centurylinkcloud/clc-go-cli/state"
)

func Run(args []string) string {
	if len(args) == 0 {
		return help()
	}
	if len(args) == 1 && args[0] == "--help" {
		return help()
	}
	cmdArg := ""
	optionArgs := args[1:]
	if len(args) >= 2 {
		cmdArg = args[1]
		optionArgs = args[2:]
	}
	resource, err := command_loader.LoadResource(args[0])
	if err != nil {
		return err.Error()
	}
	cmd, err := command_loader.LoadCommand(resource, cmdArg)
	if err != nil {
		if cmdArg == "--help" {
			return command_loader.GetCommandsWithDescriptions(resource)
		}
		return err.Error()
	}
	if cmd.Command() == "" {
		optionArgs = args[1:]
	}
	parsedArgs, err := parser.ParseArguments(optionArgs)
	if err != nil {
		return err.Error()
	}
	yes, filename, err := options.AreToBeTakenFromFile(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if yes {
		parsedArgs, err = state.ArgumentsFromJSON(filename)
		if err != nil {
			return err.Error()
		}
	}
	yes, err = options.AreToBeSaved(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if yes {
		output, err := state.ArgumentsToJSON(parsedArgs, cmd.InputModel())
		if err != nil {
			return err.Error()
		}
		return output
	}
	options, err := options.ExtractFrom(parsedArgs)
	if err != nil {
		return err.Error()
	}
	if options.Help {
		return cmd.ShowHelp()
	}
	conf, err := config.LoadConfig()
	if err != nil {
		return err.Error()
	}
	if cmd.Resource() == "login" {
		return cmd.(*commands.Login).Login(options, conf)
	}
	err = model_loader.LoadModel(parsedArgs, cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	datacenter.ApplyDefault(cmd.InputModel(), conf)
	err = model_validator.ValidateModel(cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	err = model_adjuster.ApplyDefaultBehaviour(cmd.InputModel())
	if err != nil {
		return err.Error()
	}
	if cmd.IsOffline() {
		res, err := cmd.ExecuteOffline()
		if err != nil {
			return err.Error()
		}
		return res
	}
	cn, err := auth.AuthenticateCommand(options, conf)
	if err != nil {
		return err.Error()
	}
	err = model_adjuster.InferID(cmd.InputModel(), cn)
	if err != nil {
		return err.Error()
	}
	err = cmd.Execute(cn)
	if err != nil {
		return err.Error()
	}
	err = state.SaveLastResult(cmd.OutputModel())
	if err != nil {
		return err.Error()
	}
	f, err := formatter_provider.GetOutputFormatter(options, conf)
	if err != nil {
		return err.Error()
	}
	outputModel := cmd.OutputModel()
	if messagePtr, ok := outputModel.(*string); ok {
		return *messagePtr
	}
	detyped, err := parser.ConvertToMapOrSlice(outputModel)
	if err != nil {
		return err.Error()
	}
	if options.Filter != "" {
		filtered, err := parser.ParseFilter(detyped, options.Filter)
		if err != nil {
			return err.Error()
		} else if filtered == nil {
			return "No results found for the given filter."
		} else {
			detyped = filtered
		}
	}
	if options.Query != "" {
		queried, err := parser.ParseQuery(detyped, options.Query)
		if err != nil {
			return err.Error()
		} else if queried == nil {
			return "No results found for the given query."
		} else {
			detyped = queried
		}
	}
	output, err := f.FormatOutput(detyped)
	if err != nil {
		return err.Error()
	}
	return output
}

func help() string {
	res := `Usage: clc <resource> [<command>] [options and parameters]

clc <resource> --help
    get a list of all available commands for the given
    resource if any or to get a direct resource description
clc <resource> <command> --help
    get a command description and a list of all available
    parameters for the given command

Available resources:

`
	resources := command_loader.GetResources()
	sort.Strings(resources)
	for _, rsr := range resources {
		res += fmt.Sprintf("\t%v\n", rsr)
	}
	return res
}
<|endoftext|>


<commit_before>// Copyright © 2017 The VirusTotal CLI 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 (
	"encoding/base64"
	"github.com/VirusTotal/vt-cli/utils"
	"github.com/spf13/cobra"
)

var urlCmdHelp = `Get information about one or more URLs.

This command receives one or more URLs and returns information about them. URL
hashes as returned in the "object_id" field are also accepted. The information
about each URL is returned in the same order as the URLs are passed to the
command.

If the command receives a single hypen (-) the URLs are read from the standard
input, one per line.
`

var urlCmdExample = `  vt url https://www.virustotal.com
  vt url f1177df4692356280844e1d5af67cc4a9eccecf77aa61c229d483b7082c70a8e
  cat list_of_urls | vt url -`

// NewURLCmd returns a new instance of the 'url' command.
func NewURLCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "url [url]...",
		Short:   "Get information about URLs",
		Long:    urlCmdHelp,
		Example: urlCmdExample,
		Args:    cobra.MinimumNArgs(1),

		RunE: func(cmd *cobra.Command, args []string) error {
			p, err := NewPrinter(cmd)
			if err != nil {
				return err
			}
			r := utils.NewMappedStringReader(
				utils.StringReaderFromCmdArgs(args),
				func (url string) string {
					return base64.RawURLEncoding.EncodeToString([]byte(url))
				})
			return p.GetAndPrintObjects("urls/%s", r, nil)
		},
	}

	addRelationshipCmds(cmd, "urls", "url", "[url]")

	addThreadsFlag(cmd.Flags())
	addIncludeExcludeFlags(cmd.Flags())
	addIDOnlyFlag(cmd.Flags())

	return cmd
}
<commit_msg>The `vt url` command now accepts URL identifiers as returned by the API.<commit_after>// Copyright © 2017 The VirusTotal CLI 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 (
	"encoding/base64"
	"github.com/VirusTotal/vt-cli/utils"
	"github.com/spf13/cobra"
	"regexp"
)

var urlCmdHelp = `Get information about one or more URLs.

This command receives one or more URLs and returns information about them. URL
hashes as returned in the "object_id" field are also accepted. The information
about each URL is returned in the same order as the URLs are passed to the
command.

If the command receives a single hypen (-) the URLs are read from the standard
input, one per line.
`

var urlCmdExample = `  vt url https://www.virustotal.com
  vt url f1177df4692356280844e1d5af67cc4a9eccecf77aa61c229d483b7082c70a8e
  cat list_of_urls | vt url -`

// Regular expressions used for validating a URL identifier.
var urlID = regexp.MustCompile(`[0-9a-fA-F]{64}`)

// NewURLCmd returns a new instance of the 'url' command.
func NewURLCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "url [url]...",
		Short:   "Get information about URLs",
		Long:    urlCmdHelp,
		Example: urlCmdExample,
		Args:    cobra.MinimumNArgs(1),

		RunE: func(cmd *cobra.Command, args []string) error {
			p, err := NewPrinter(cmd)
			if err != nil {
				return err
			}
			r := utils.NewMappedStringReader(
				utils.StringReaderFromCmdArgs(args),
				func (url string) string {
					if urlID.MatchString(url) {
						// The user provided a URL identifier as returned by
						// VirusTotal's API, which consists in the URL's SHA-256.
						// In that case use the identifier as is.
						return url
					}
					// If the user provides an actual URL, it needs to be
					// encoded as base64 before being used.
					return base64.RawURLEncoding.EncodeToString([]byte(url))
				})
			return p.GetAndPrintObjects("urls/%s", r, nil)
		},
	}

	addRelationshipCmds(cmd, "urls", "url", "[url]")

	addThreadsFlag(cmd.Flags())
	addIncludeExcludeFlags(cmd.Flags())
	addIDOnlyFlag(cmd.Flags())

	return cmd
}
<|endoftext|>


<commit_before>// Basic data structures for Go.
package main

import (
	"fmt"
)

// Letters for quick lookup.
// These are the letters marked on top of the board.  "I" is
// always left out, likely to avoid confusion with "1".
const BoardLetters = "ABCDEFGHJKLMNOPQRST"
const ColorChars = "CBW"

// Here it would be nice if the type system allows us to say
// "integer with one of these value: 0, 1, 2.
type Stone int

const (
	// Stone colors. Used for board state.
	Empty = 0 // No stone here.
	Black = 1
	White = 2

	// Moves. These correspond to board state making it easy to
	// translate between the two. (A capture will clear that position on
	// the board.)
	Capture    = 0
	PlaceBlack = 1
	PlaceWhite = 2
)

// Position where a stone can be placed.
type Pos struct {
	X int // Left to right, 0-18 (marked as 1-19 on board.)
	Y int // Bottom to top, 0-18 (ABCDEFGHJKLMNOPQRST.)
}

// A move. (Place or capture stone.)
type Move struct {
	Action Stone // (Hmm, this looks a bit weird here.)
	Pos
}

func (move Move) String() string {
	// Todo: check if values are out of range?
	color := ColorChars[move.Action]
	letter := BoardLetters[move.X]
	number := move.Y + 1

	return fmt.Sprintf("%c%c%d", color, letter, number)
}

// The board is just a cache of moves. We can recompute the board from
// the moves.
type Game struct {
	Size  int
	Moves []Move
	// Here we should have a stack (or slice) of boards so that we have
	// a history of previous board states.
	Board map[Pos]Stone

	// + We need to keep score somehow. (Number of captured stones for
	// each player.)
}

func (game *Game) AddMove(move Move) {
	game.Moves = append(game.Moves, move)
	game.Board[move.Pos] = move.Action
}

func (game *Game) AddMoves(moves []Move) {
	for _, move := range moves {
		fmt.Println(move)
		game.AddMove(move)
	}
}

func (game *Game) PrintBoard() {
	stoneChars := ".BW"

	fmt.Println("   " + BoardLetters)

	for y := game.Size; y >= 0; y-- {
		line := ""
		for x := 0; x < game.Size; x++ {
			line += fmt.Sprintf("%c", stoneChars[game.Board[Pos{x, y}]])
		}
		fmt.Printf("%2d %s\n", y+1, line)
	}
}

func NewGame(size int) Game {
	return Game{Size: size, Board: make(map[Pos]Stone)}
}

func main() {
	game := NewGame(19)
	moves := []Move{{PlaceBlack, Pos{0, 0}}, {PlaceWhite, Pos{1, 6}}}
	game.AddMoves(moves)

	game.PrintBoard()

	// fmt.Println(game.Board[Pos{}])
	// fmt.Println(game.Board[Pos{1, 1}])

	// fmt.Println(moves)
}
<commit_msg>Switched from Size to BoardSize for clarity.<commit_after>// Basic data structures for Go.
package main

import (
	"fmt"
	"regexp"
)

// Letters for quick lookup.
// These are the letters marked on top of the board.  "I" is
// always left out, likely to avoid confusion with "1".
const BoardLetters = "ABCDEFGHJKLMNOPQRST"
const ColorChars = "CBW"

// Here it would be nice if the type system allows us to say
// "integer with one of these value: 0, 1, 2.
type Stone int

const (
	// Stone colors. Used for board state.
	Empty = 0 // No stone here.
	Black = 1
	White = 2

	// Moves. These correspond to board state making it easy to
	// translate between the two. (A capture will clear that position on
	// the board.)
	Capture    = 0
	PlaceBlack = 1
	PlaceWhite = 2
)

// Position where a stone can be placed.
type Pos struct {
	X int // Left to right, 0-18 (marked as 1-19 on board.)
	Y int // Bottom to top, 0-18 (ABCDEFGHJKLMNOPQRST.)
}

// A move. (Place or capture stone.)
type Move struct {
	Action Stone // (Hmm, this looks a bit weird here.)
	Pos
}

func (move Move) String() string {
	// Todo: check if values are out of range?
	color := ColorChars[move.Action]
	letter := BoardLetters[move.X]
	number := move.Y + 1

	return fmt.Sprintf("%c%c%d", color, letter, number)
}

// The board is just a cache of moves. We can recompute the board from
// the moves.
type Game struct {
	BoardSize int
	Board     map[Pos]Stone
	Moves     []Move
	// Here we should have a stack (or slice) of boards so that we have
	// a history of previous board states.

	// + We need to keep score somehow. (Number of captured stones for
	// each player.)
}

func (game *Game) AddMove(move Move) {
	game.Moves = append(game.Moves, move)
	game.Board[move.Pos] = move.Action
}

func (game *Game) AddMoves(moves []Move) {
	for _, move := range moves {
		fmt.Println(move)
		game.AddMove(move)
	}
}

func (game *Game) PrintBoard() {
	stoneChars := ".BW"

	fmt.Println("   " + BoardLetters)

	for y := game.BoardSize; y >= 0; y-- {
		line := ""
		for x := 0; x < game.BoardSize; x++ {
			line += fmt.Sprintf("%c", stoneChars[game.Board[Pos{x, y}]])
		}
		fmt.Printf("%2d %s\n", y+1, line)
	}
}

func NewGame(boardSize int) Game {
	return Game{
		BoardSize: boardSize,
		Board:     make(map[Pos]Stone),
	}
}

func main() {
	game := NewGame(19)
	moves := []Move{{PlaceBlack, Pos{0, 0}}, {PlaceWhite, Pos{1, 6}}}
	game.AddMoves(moves)

	game.PrintBoard()

	// fmt.Println(game.Board[Pos{}])
	// fmt.Println(game.Board[Pos{1, 1}])

	// fmt.Println(moves)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"
)

// global command line parameters
var runs *int
var cpus0 *string
var cpus1 *string
var threads *string

func main() {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 = flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 = flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()
	for i := 0; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == 2 {
			// no
			*measurement += "# "
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == 2 {
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	cmd0 := exec.Command("/bin/sh", "-c", cPair[0])
	cmd1 := exec.Command("/bin/sh", "-c", cPair[1])

	env := os.Environ()
	cmd0.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus0, "OMP_NUM_THREADS="+*threads)
	cmd1.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus1, "OMP_NUM_THREADS="+*threads)

	outfile0, err := os.Create(fmt.Sprintf("%v-0.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile0.Close()
	outfile1, err := os.Create(fmt.Sprintf("%v-1.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile1.Close()

	cmd0.Stdout = outfile0
	cmd1.Stdout = outfile1

	var measurements [2]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, 2)

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(2)

	go runCmdMinTimes(cmd0, *runs, &wg, &measurements[0], done, errs)
	go runCmdMinTimes(cmd1, *runs, &wg, &measurements[1], done, errs)

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}
<commit_msg>Added basic online analysis.<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus0 *string
var cpus1 *string
var threads *string

func main() {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 = flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 = flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()

	var runtime []float64

	for i := 0; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == 2 {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == 2 {
			mean, err := stats.Mean(runtime)
			if err != nil {
				mean = -1.0
			}
			stddev, err := stats.StandardDeviation(runtime)
			if err != nil {
				stddev = -1.0
			}

			fmt.Printf("%v \t %9.2f avg. runtime \t %1.6f std. dev.\n", cmd.Args, mean, stddev)
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	cmd0 := exec.Command("/bin/sh", "-c", cPair[0])
	cmd1 := exec.Command("/bin/sh", "-c", cPair[1])

	env := os.Environ()
	cmd0.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus0, "OMP_NUM_THREADS="+*threads)
	cmd1.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus1, "OMP_NUM_THREADS="+*threads)

	outfile0, err := os.Create(fmt.Sprintf("%v-0.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile0.Close()
	outfile1, err := os.Create(fmt.Sprintf("%v-1.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile1.Close()

	cmd0.Stdout = outfile0
	cmd1.Stdout = outfile1

	var measurements [2]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, 2)

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(2)

	go runCmdMinTimes(cmd0, *runs, &wg, &measurements[0], done, errs)
	go runCmdMinTimes(cmd1, *runs, &wg, &measurements[1], done, errs)

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}
<|endoftext|>


<commit_before>package orchestrators

import (
	"encoding/json"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	log "github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v2"
	"golang.org/x/net/websocket"

	"github.com/camptocamp/bivac/handler"
	"github.com/camptocamp/bivac/volume"
)

// CattleOrchestrator implements a container orchestrator for Cattle
type CattleOrchestrator struct {
	Handler *handler.Bivac
	Client  *client.RancherClient
}

// NewCattleOrchestrator creates a Cattle client
func NewCattleOrchestrator(c *handler.Bivac) (o *CattleOrchestrator) {
	var err error
	o = &CattleOrchestrator{
		Handler: c,
	}

	o.Client, err = client.NewRancherClient(&client.ClientOpts{
		Url:       o.Handler.Config.Cattle.URL,
		AccessKey: o.Handler.Config.Cattle.AccessKey,
		SecretKey: o.Handler.Config.Cattle.SecretKey,
	})
	if err != nil {
		log.Errorf("failed to create a new Rancher client: %s", err)
	}

	return
}

// GetName returns the orchestrator name
func (*CattleOrchestrator) GetName() string {
	return "Cattle"
}

// GetHandler returns the Orchestrator's handler
func (o *CattleOrchestrator) GetHandler() *handler.Bivac {
	return o.Handler
}

// GetVolumes returns the Cattle volumes
func (o *CattleOrchestrator) GetVolumes() (volumes []*volume.Volume, err error) {
	c := o.Handler

	vs, err := o.Client.Volume.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})
	if err != nil {
		log.Errorf("failed to list volumes: %s", err)
	}

	var mountpoint string
	for _, v := range vs.Data {
		if len(v.Mounts) < 1 {
			mountpoint = "/data"
		} else {
			mountpoint = v.Mounts[0].Path
		}

		var hostID, hostname string
		var spc *client.StoragePoolCollection
		err := o.rawAPICall("GET", v.Links["storagePools"], &spc)
		if err != nil {
			log.Errorf("failed to retrieve storage pool from volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data) == 0 {
			log.Errorf("no storage pool for the volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data[0].HostIds) == 0 {
			log.Errorf("no host for the volume %s: %s", v.Name, err)
			continue
		}

		hostID = spc.Data[0].HostIds[0]

		h, err := o.Client.Host.ById(hostID)
		if err != nil {
			log.Errorf("failed to retrieve host from id %s: %s", hostID, err)
			hostname = ""
		} else {
			hostname = h.Hostname
		}

		nv := &volume.Volume{
			Config:     &volume.Config{},
			Mountpoint: mountpoint,
			Name:       v.Name,
			HostBind:   hostID,
			Hostname:   hostname,
		}

		v := volume.NewVolume(nv, c.Config, hostname)
		if b, r, s := o.blacklistedVolume(v); b {
			log.WithFields(log.Fields{
				"volume": v.Name,
				"reason": r,
				"source": s,
			}).Info("Ignoring volume")
			continue
		}
		volumes = append(volumes, v)
	}
	return
}

func createWorkerName() string {
	var letter = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
	b := make([]rune, 10)
	for i := range b {
		b[i] = letter[rand.Intn(len(letter))]
	}
	return "bivac-worker-" + string(b)
}

// LaunchContainer starts a containe using the Cattle orchestrator
func (o *CattleOrchestrator) LaunchContainer(image string, env map[string]string, cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	environment := make(map[string]interface{}, len(env))
	for envKey, envVal := range env {
		environment[envKey] = envVal
	}

	var hostbind string
	if len(volumes) > 0 {
		hostbind = volumes[0].HostBind
	} else {
		hostbind = ""
	}

	cvs := []string{}
	for _, v := range volumes {
		cvs = append(cvs, v.Name+":"+v.Mountpoint)
	}

	container, err := o.Client.Container.Create(&client.Container{
		Name:        createWorkerName(),
		HostId:      hostbind,
		ImageUuid:   "docker:" + image,
		Command:     cmd,
		Environment: environment,
		RestartPolicy: &client.RestartPolicy{
			MaximumRetryCount: 1,
			Name:              "on-failure",
		},
		DataVolumes: cvs,
	})
	if err != nil {
		log.Errorf("failed to create worker container: %s", err)
		return
	}

	defer o.DeleteWorker(container)

	stopped := false
	terminated := false
	for !terminated {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}

		// This workaround is awful but it's the only way to know if the container failed.
		if container.State == "stopped" {
			if container.StartCount == 1 {
				if stopped == false {
					stopped = true
					time.Sleep(5 * time.Second)
				} else {
					terminated = true
					state = 0
				}
			} else {
				state = 1
				terminated = true
			}
		}
	}

	var hostAccess *client.HostAccess
	err = o.rawAPICall("POST", container.Links["self"]+"/?action=logs", &hostAccess)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}

	re := regexp.MustCompile(`(?m)[0-9]{2,} [ZT\-\:\.0-9]+ (.*)`)
	for _, line := range re.FindAllStringSubmatch(string(data[:n]), -1) {
		stdout = strings.Join([]string{stdout, line[1]}, "\n")
	}

	log.WithFields(log.Fields{
		"container": container.Id,
		"volumes":   strings.Join(cvs[:], ","),
		"cmd":       strings.Join(cmd[:], " "),
	}).Debug(stdout)
	return
}

// DeleteWorker deletes a worker
func (o *CattleOrchestrator) DeleteWorker(container *client.Container) {
	err := o.Client.Container.Delete(container)
	if err != nil {
		log.Errorf("failed to delete worker: %s", err)
	}
	removed := false
	for !removed {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}
		if container.Removed != "" {
			removed = true
		}
	}
	return
}

// GetMountedVolumes returns mounted volumes
func (o *CattleOrchestrator) GetMountedVolumes() (containers []*volume.MountedVolumes, err error) {
	c, err := o.Client.Container.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})

	if err != nil {
		log.Errorf("failed to list containers: %s", err)
	}

	for _, container := range c.Data {
		mv := &volume.MountedVolumes{
			ContainerID: container.Id,
			Volumes:     make(map[string]string),
		}
		for _, mount := range container.Mounts {
			mv.Volumes[mount.VolumeName] = mount.Path
		}
		containers = append(containers, mv)
	}
	return
}

// ContainerExec executes a command in a container
func (o *CattleOrchestrator) ContainerExec(mountedVolumes *volume.MountedVolumes, command []string) (err error) {

	container, err := o.Client.Container.ById(mountedVolumes.ContainerID)
	if err != nil {
		log.Errorf("failed to retrieve container: %s", err)
		return
	}

	hostAccess, err := o.Client.Container.ActionExecute(container, &client.ContainerExec{
		AttachStdin:  false,
		AttachStdout: true,
		Command:      command,
		Tty:          false,
	})
	if err != nil {
		log.Errorf("failed to prepare command execution in container: %s", err)
		return
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	log.WithFields(log.Fields{
		"container": mountedVolumes.ContainerID,
		"cmd":       strings.Join(command[:], " "),
	}).Debug(string(data[:n]))
	return
}

func (o *CattleOrchestrator) blacklistedVolume(vol *volume.Volume) (bool, string, string) {
	if utf8.RuneCountInString(vol.Name) == 64 || utf8.RuneCountInString(vol.Name) == 0 {
		return true, "unnamed", ""
	}

	if strings.Contains(vol.Name, "/") {
		return true, "blacklisted", "path"
	}

	list := o.Handler.Config.VolumesBlacklist
	sort.Strings(list)
	i := sort.SearchStrings(list, vol.Name)
	if i < len(list) && list[i] == vol.Name {
		return true, "blacklisted", "blacklist config"
	}

	if vol.Config.Ignore {
		return true, "blacklisted", "volume config"
	}

	return false, "", ""
}

func (o *CattleOrchestrator) rawAPICall(method, endpoint string, object interface{}) (err error) {
	// TODO: Use go-rancher.
	// It was impossible to use it, maybe a problem in go-rancher or a lack of documentation.
	clientHTTP := &http.Client{}
	v := url.Values{}
	req, err := http.NewRequest(method, endpoint, strings.NewReader(v.Encode()))
	req.SetBasicAuth(o.Handler.Config.Cattle.AccessKey, o.Handler.Config.Cattle.SecretKey)
	resp, err := clientHTTP.Do(req)
	if err != nil {
		log.Errorf("failed to execute POST request: %s", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}
	err = json.Unmarshal(body, object)
	if err != nil {
		log.Errorf("failed to unmarshal: %s", err)
	}
	return
}

func detectCattle() bool {
	_, err := net.LookupHost("rancher-metadata")
	if err != nil {
		return false
	}
	return true
}
<commit_msg>Cattle orchestrator: fix node selector<commit_after>package orchestrators

import (
	"encoding/json"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	log "github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v2"
	"golang.org/x/net/websocket"

	"github.com/camptocamp/bivac/handler"
	"github.com/camptocamp/bivac/volume"
)

// CattleOrchestrator implements a container orchestrator for Cattle
type CattleOrchestrator struct {
	Handler *handler.Bivac
	Client  *client.RancherClient
}

// NewCattleOrchestrator creates a Cattle client
func NewCattleOrchestrator(c *handler.Bivac) (o *CattleOrchestrator) {
	var err error
	o = &CattleOrchestrator{
		Handler: c,
	}

	o.Client, err = client.NewRancherClient(&client.ClientOpts{
		Url:       o.Handler.Config.Cattle.URL,
		AccessKey: o.Handler.Config.Cattle.AccessKey,
		SecretKey: o.Handler.Config.Cattle.SecretKey,
	})
	if err != nil {
		log.Errorf("failed to create a new Rancher client: %s", err)
	}

	return
}

// GetName returns the orchestrator name
func (*CattleOrchestrator) GetName() string {
	return "Cattle"
}

// GetHandler returns the Orchestrator's handler
func (o *CattleOrchestrator) GetHandler() *handler.Bivac {
	return o.Handler
}

// GetVolumes returns the Cattle volumes
func (o *CattleOrchestrator) GetVolumes() (volumes []*volume.Volume, err error) {
	c := o.Handler

	vs, err := o.Client.Volume.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})
	if err != nil {
		log.Errorf("failed to list volumes: %s", err)
	}

	var mountpoint string
	for _, v := range vs.Data {
		if len(v.Mounts) < 1 {
			mountpoint = "/data"
		} else {
			mountpoint = v.Mounts[0].Path
		}

		var hostID, hostname string
		var spc *client.StoragePoolCollection
		err := o.rawAPICall("GET", v.Links["storagePools"], &spc)
		if err != nil {
			log.Errorf("failed to retrieve storage pool from volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data) == 0 {
			log.Errorf("no storage pool for the volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data[0].HostIds) == 0 {
			log.Errorf("no host for the volume %s: %s", v.Name, err)
			continue
		}

		hostID = spc.Data[0].HostIds[0]

		h, err := o.Client.Host.ById(hostID)
		if err != nil {
			log.Errorf("failed to retrieve host from id %s: %s", hostID, err)
			hostname = ""
		} else {
			hostname = h.Hostname
		}

		nv := &volume.Volume{
			Config:     &volume.Config{},
			Mountpoint: mountpoint,
			Name:       v.Name,
			HostBind:   hostID,
			Hostname:   hostname,
		}

		v := volume.NewVolume(nv, c.Config, hostname)
		if b, r, s := o.blacklistedVolume(v); b {
			log.WithFields(log.Fields{
				"volume": v.Name,
				"reason": r,
				"source": s,
			}).Info("Ignoring volume")
			continue
		}
		volumes = append(volumes, v)
	}
	return
}

func createWorkerName() string {
	var letter = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
	b := make([]rune, 10)
	for i := range b {
		b[i] = letter[rand.Intn(len(letter))]
	}
	return "bivac-worker-" + string(b)
}

// LaunchContainer starts a containe using the Cattle orchestrator
func (o *CattleOrchestrator) LaunchContainer(image string, env map[string]string, cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	environment := make(map[string]interface{}, len(env))
	for envKey, envVal := range env {
		environment[envKey] = envVal
	}

	var hostbind string
	if len(volumes) > 0 {
		hostbind = volumes[0].HostBind
	} else {
		hostbind = ""
	}

	cvs := []string{}
	for _, v := range volumes {
		cvs = append(cvs, v.Name+":"+v.Mountpoint)
	}

	container, err := o.Client.Container.Create(&client.Container{
		Name:            createWorkerName(),
		RequestedHostId: hostbind,
		ImageUuid:       "docker:" + image,
		Command:         cmd,
		Environment:     environment,
		RestartPolicy: &client.RestartPolicy{
			MaximumRetryCount: 1,
			Name:              "on-failure",
		},
		DataVolumes: cvs,
	})
	if err != nil {
		log.Errorf("failed to create worker container: %s", err)
		return
	}

	defer o.DeleteWorker(container)

	stopped := false
	terminated := false
	for !terminated {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}

		// This workaround is awful but it's the only way to know if the container failed.
		if container.State == "stopped" {
			if container.StartCount == 1 {
				if stopped == false {
					stopped = true
					time.Sleep(5 * time.Second)
				} else {
					terminated = true
					state = 0
				}
			} else {
				state = 1
				terminated = true
			}
		}
	}

	var hostAccess *client.HostAccess
	err = o.rawAPICall("POST", container.Links["self"]+"/?action=logs", &hostAccess)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}

	re := regexp.MustCompile(`(?m)[0-9]{2,} [ZT\-\:\.0-9]+ (.*)`)
	for _, line := range re.FindAllStringSubmatch(string(data[:n]), -1) {
		stdout = strings.Join([]string{stdout, line[1]}, "\n")
	}

	log.WithFields(log.Fields{
		"container": container.Id,
		"volumes":   strings.Join(cvs[:], ","),
		"cmd":       strings.Join(cmd[:], " "),
	}).Debug(stdout)
	return
}

// DeleteWorker deletes a worker
func (o *CattleOrchestrator) DeleteWorker(container *client.Container) {
	err := o.Client.Container.Delete(container)
	if err != nil {
		log.Errorf("failed to delete worker: %s", err)
	}
	removed := false
	for !removed {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}
		if container.Removed != "" {
			removed = true
		}
	}
	return
}

// GetMountedVolumes returns mounted volumes
func (o *CattleOrchestrator) GetMountedVolumes() (containers []*volume.MountedVolumes, err error) {
	c, err := o.Client.Container.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})

	if err != nil {
		log.Errorf("failed to list containers: %s", err)
	}

	for _, container := range c.Data {
		mv := &volume.MountedVolumes{
			ContainerID: container.Id,
			Volumes:     make(map[string]string),
		}
		for _, mount := range container.Mounts {
			mv.Volumes[mount.VolumeName] = mount.Path
		}
		containers = append(containers, mv)
	}
	return
}

// ContainerExec executes a command in a container
func (o *CattleOrchestrator) ContainerExec(mountedVolumes *volume.MountedVolumes, command []string) (err error) {

	container, err := o.Client.Container.ById(mountedVolumes.ContainerID)
	if err != nil {
		log.Errorf("failed to retrieve container: %s", err)
		return
	}

	hostAccess, err := o.Client.Container.ActionExecute(container, &client.ContainerExec{
		AttachStdin:  false,
		AttachStdout: true,
		Command:      command,
		Tty:          false,
	})
	if err != nil {
		log.Errorf("failed to prepare command execution in container: %s", err)
		return
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	log.WithFields(log.Fields{
		"container": mountedVolumes.ContainerID,
		"cmd":       strings.Join(command[:], " "),
	}).Debug(string(data[:n]))
	return
}

func (o *CattleOrchestrator) blacklistedVolume(vol *volume.Volume) (bool, string, string) {
	if utf8.RuneCountInString(vol.Name) == 64 || utf8.RuneCountInString(vol.Name) == 0 {
		return true, "unnamed", ""
	}

	if strings.Contains(vol.Name, "/") {
		return true, "blacklisted", "path"
	}

	list := o.Handler.Config.VolumesBlacklist
	sort.Strings(list)
	i := sort.SearchStrings(list, vol.Name)
	if i < len(list) && list[i] == vol.Name {
		return true, "blacklisted", "blacklist config"
	}

	if vol.Config.Ignore {
		return true, "blacklisted", "volume config"
	}

	return false, "", ""
}

func (o *CattleOrchestrator) rawAPICall(method, endpoint string, object interface{}) (err error) {
	// TODO: Use go-rancher.
	// It was impossible to use it, maybe a problem in go-rancher or a lack of documentation.
	clientHTTP := &http.Client{}
	v := url.Values{}
	req, err := http.NewRequest(method, endpoint, strings.NewReader(v.Encode()))
	req.SetBasicAuth(o.Handler.Config.Cattle.AccessKey, o.Handler.Config.Cattle.SecretKey)
	resp, err := clientHTTP.Do(req)
	if err != nil {
		log.Errorf("failed to execute POST request: %s", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}
	err = json.Unmarshal(body, object)
	if err != nil {
		log.Errorf("failed to unmarshal: %s", err)
	}
	return
}

func detectCattle() bool {
	_, err := net.LookupHost("rancher-metadata")
	if err != nil {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright ©2012 The bíogo.graph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package graph

import (
	"math"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

func FastRandMinCut(g *Undirected, iter int) (c []Edge, w float64) {
	ka := newKarger(g)
	ka.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		ka.fastRandMinCut()
		if ka.w < w {
			w = ka.w
			c = ka.c
		}
	}

	return c, w
}

func (ka *karger) fastRandMinCut() {
	if ka.order <= 6 {
		ka.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(ka.order)/sqrt2 + 1))

	sub := []*karger{ka, ka.clone()}
	for _, ks := range sub {
		ks.randContract(t)
		ks.fastRandMinCut()
	}

	if sub[0].w < sub[1].w {
		*ka = *sub[0]
		return
	}
	*ka = *sub[1]
}

// parallelised within the recursion tree

func FastRandMinCutPar(g *Undirected, iter, threads int) (c []Edge, w float64) {
	k := newKarger(g)
	k.split = threads
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCutPar()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return c, w
}

func (ka *karger) fastRandMinCutPar() {
	if ka.order <= 6 {
		ka.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(ka.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if ka.count < ka.split {
		wg = &sync.WaitGroup{}
	}
	ka.count++

	sub := []*karger{ka, ka.clone()}
	for _, ks := range sub {
		if wg != nil {
			wg.Add(1)
			go func(ks *karger) {
				defer wg.Done()
				ks.randContract(t)
				ks.fastRandMinCutPar()
			}(ks)
		} else {
			ks.randContract(t)
			ks.fastRandMinCutPar()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[0].w < sub[1].w {
		*ka = *sub[0]
		return
	}
	*ka = *sub[1]
}

type karger struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []Edge
	w     float64

	count int
	split int
}

type super struct {
	label int
	nodes []int
}

func newKarger(g *Undirected) *karger {
	return &karger{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (ka *karger) init() {
	ka.order = ka.g.Order()
	for i := range ka.ind {
		ka.ind[i].label = -1
		ka.ind[i].nodes = nil
	}
	for _, n := range ka.g.Nodes() {
		id := n.ID()
		ka.ind[id].label = id
	}
	for i, e := range ka.g.Edges() {
		ka.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	ka.sel.Init()
}

func (ka *karger) clone() *karger {
	c := karger{
		g:     ka.g,
		ind:   make([]super, ka.g.NextNodeID()),
		sel:   make(Selector, ka.g.Size()),
		order: ka.order,
		count: ka.count,
	}

	copy(c.sel, ka.sel)
	for i, n := range ka.ind {
		s := &c.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}

	return &c
}

func (ka *karger) randContract(k int) {
	for ka.order > k {
		id, err := ka.sel.Select()
		if err != nil {
			break
		}

		e := ka.g.Edge(id)
		if ka.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := ka.ind[hid].label, ka.ind[tid].label
		if len(ka.ind[hl].nodes) < len(ka.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if ka.ind[hl].nodes == nil {
			ka.ind[hl].nodes = []int{hid}
		}
		if ka.ind[tl].nodes == nil {
			ka.ind[hl].nodes = append(ka.ind[hl].nodes, tid)
		} else {
			ka.ind[hl].nodes = append(ka.ind[hl].nodes, ka.ind[tl].nodes...)
			ka.ind[tl].nodes = nil
		}
		for _, i := range ka.ind[hl].nodes {
			ka.ind[i].label = ka.ind[hid].label
		}

		ka.order--
	}
}

func (ka *karger) randCompact(k int) {
	ka.randContract(k)
	ka.c, ka.w = []Edge{}, 0
	for _, e := range ka.g.Edges() {
		if ka.loop(e) {
			continue
		}
		ka.c = append(ka.c, e)
		ka.w += e.Weight()
	}
}

func (ka *karger) loop(e Edge) bool {
	return ka.ind[e.Head().ID()].label == ka.ind[e.Tail().ID()].label
}
<commit_msg>Remove unnecessary assignments<commit_after>// Copyright ©2012 The bíogo.graph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package graph

import (
	"math"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

func FastRandMinCut(g *Undirected, iter int) (c []Edge, w float64) {
	ka := newKarger(g)
	ka.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		ka.fastRandMinCut()
		if ka.w < w {
			w = ka.w
			c = ka.c
		}
	}

	return c, w
}

func (ka *karger) fastRandMinCut() {
	if ka.order <= 6 {
		ka.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(ka.order)/sqrt2 + 1))

	sub := []*karger{ka, ka.clone()}
	for _, ks := range sub {
		ks.randContract(t)
		ks.fastRandMinCut()
	}

	if sub[1].w < sub[0].w {
		*ka = *sub[1]
	}
}

// parallelised within the recursion tree

func FastRandMinCutPar(g *Undirected, iter, threads int) (c []Edge, w float64) {
	k := newKarger(g)
	k.split = threads
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCutPar()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return c, w
}

func (ka *karger) fastRandMinCutPar() {
	if ka.order <= 6 {
		ka.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(ka.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if ka.count < ka.split {
		wg = &sync.WaitGroup{}
	}
	ka.count++

	sub := []*karger{ka, ka.clone()}
	for _, ks := range sub {
		if wg != nil {
			wg.Add(1)
			go func(ks *karger) {
				defer wg.Done()
				ks.randContract(t)
				ks.fastRandMinCutPar()
			}(ks)
		} else {
			ks.randContract(t)
			ks.fastRandMinCutPar()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[1].w < sub[0].w {
		*ka = *sub[1]
	}
}

type karger struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []Edge
	w     float64

	count int
	split int
}

type super struct {
	label int
	nodes []int
}

func newKarger(g *Undirected) *karger {
	return &karger{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (ka *karger) init() {
	ka.order = ka.g.Order()
	for i := range ka.ind {
		ka.ind[i].label = -1
		ka.ind[i].nodes = nil
	}
	for _, n := range ka.g.Nodes() {
		id := n.ID()
		ka.ind[id].label = id
	}
	for i, e := range ka.g.Edges() {
		ka.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	ka.sel.Init()
}

func (ka *karger) clone() *karger {
	c := karger{
		g:     ka.g,
		ind:   make([]super, ka.g.NextNodeID()),
		sel:   make(Selector, ka.g.Size()),
		order: ka.order,
		count: ka.count,
	}

	copy(c.sel, ka.sel)
	for i, n := range ka.ind {
		s := &c.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}

	return &c
}

func (ka *karger) randContract(k int) {
	for ka.order > k {
		id, err := ka.sel.Select()
		if err != nil {
			break
		}

		e := ka.g.Edge(id)
		if ka.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := ka.ind[hid].label, ka.ind[tid].label
		if len(ka.ind[hl].nodes) < len(ka.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if ka.ind[hl].nodes == nil {
			ka.ind[hl].nodes = []int{hid}
		}
		if ka.ind[tl].nodes == nil {
			ka.ind[hl].nodes = append(ka.ind[hl].nodes, tid)
		} else {
			ka.ind[hl].nodes = append(ka.ind[hl].nodes, ka.ind[tl].nodes...)
			ka.ind[tl].nodes = nil
		}
		for _, i := range ka.ind[hl].nodes {
			ka.ind[i].label = ka.ind[hid].label
		}

		ka.order--
	}
}

func (ka *karger) randCompact(k int) {
	ka.randContract(k)
	ka.c, ka.w = []Edge{}, 0
	for _, e := range ka.g.Edges() {
		if ka.loop(e) {
			continue
		}
		ka.c = append(ka.c, e)
		ka.w += e.Weight()
	}
}

func (ka *karger) loop(e Edge) bool {
	return ka.ind[e.Head().ID()].label == ka.ind[e.Tail().ID()].label
}
<|endoftext|>


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

package e2e

import (
	"errors"
	"fmt"
	"net"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/test/e2e/framework"
)

var _ = framework.KubeDescribe("Static Egress creation", func() {
	f := framework.NewDefaultFramework("egress")
	var cs kubernetes.Interface
	BeforeEach(func() {
		cs = f.ClientSet
	})

	It("Should create valid static egress route [Egress] [Zalando]", func() {
		ips, err := net.LookupIP("readmyip.appspot.com")
		Expect(err).NotTo(HaveOccurred())

		knownCIDRs := []string{"216.58.192.0/19", "172.217.0.0/16"}
		nets := make([]*net.IPNet, 0, len(knownCIDRs))
		for _, cidr := range knownCIDRs {
			// ignore error since we know the input
			_, ipNet, _ := net.ParseCIDR(cidr)
			nets = append(nets, ipNet)
		}

		if !ipsInCIDRs(ips, nets) {
			Expect(fmt.Errorf("IPs %s of 'readmyip.appspot.com' are not in expected ranges: %s", ips, nets)).NotTo(HaveOccurred())
		}

		configmapName := "egress-test"
		ns := f.Namespace.Name

		labels := map[string]string{
			"egress": "static",
		}

		data := map[string]string{}

		for i, cidr := range knownCIDRs {
			data[fmt.Sprintf("readmyip.appspot.com-%d", i)] = cidr
		}

		// create Pod which finds out if it's public IP changes
		By("Creating a ping POD in namespace " + ns + " we are waiting for NAT gateway created and routes are populated")
		pingPod := createPingPod("ping", ns)
		defer func() {
			By("deleting the pod")
			defer GinkgoRecover()
			cs.CoreV1().Pods(ns).Delete(pingPod.Name, metav1.NewDeleteOptions(0))
			// don't care about POD deletion, because it should exit by itself
		}()
		_, err = cs.CoreV1().Pods(ns).Create(pingPod)
		Expect(err).NotTo(HaveOccurred())
		framework.ExpectNoError(f.WaitForPodRunning(pingPod.Name))

		// ConfigMap
		By("Creating configmap " + configmapName + " in namespace " + ns)
		cmap := createConfigMap(configmapName, ns, labels, data)
		defer func() {
			By("deleting the configmap")
			defer GinkgoRecover()
			err2 := cs.CoreV1().ConfigMaps(ns).Delete(cmap.Name, metav1.NewDeleteOptions(0))
			Expect(err2).NotTo(HaveOccurred())
		}()
		_, err = cs.CoreV1().ConfigMaps(ns).Create(cmap)
		Expect(err).NotTo(HaveOccurred())

		// wait for egress route and NAT GWs ready and POD exit code 0 vs 2
		Eventually(func() error {
			return containerExitStatus(cs, ns, pingPod.Name)
		}, 10 * time.Minute, 10 * time.Second).ShouldNot(HaveOccurred())
	})
})

func containerExitStatus(cs kubernetes.Interface, namespace string, pingPodName string) error {
	p, err := cs.CoreV1().Pods(namespace).Get(pingPodName, metav1.GetOptions{})
	if err != nil {
		return err
	}

	if p.Status.ContainerStatuses[0].State.Terminated == nil {
		return errors.New("container not terminated yet")
	}

	switch n := p.Status.ContainerStatuses[0].State.Terminated.ExitCode; n {
	case 0:
		return nil
	default:
		return fmt.Errorf("unexpected exit status: %d", n)
	}
}

func ipsInCIDRs(ips []net.IP, cidrs []*net.IPNet) bool {
	for _, ip := range ips {
		for _, cidr := range cidrs {
			if cidr.Contains(ip) {
				return true
			}
		}
	}
	return false
}
<commit_msg>Remove egress tests for now<commit_after><|endoftext|>


<commit_before>package main

import (
	"os"
	"fmt"
)

var Config = struct {
	ProposeBuiltins bool "propose-builtins"
}{
	false,
}

func parseAsync(file string, done chan *ModuleCache) {
	go func() {
		m := NewModuleCache("__this__", file)
		m.updateCache()
		done <- m
	}()
}

func main() {
	done := make(chan *ModuleCache)
	for _, arg := range os.Args[1:] {
		parseAsync(arg, done)
	}
	for _, _ = range os.Args[1:] {
		d := <-done
		fmt.Printf("%s was parsed successfully\n", d.filename)
		fmt.Printf("\t%d main declaration(s)\n", len(d.main.Children))
		fmt.Printf("\t%d foreign module(s)\n", len(d.others))
	}
	fmt.Printf("Total number of packages: %d\nOK\n", len(os.Args[1:]))
}
<commit_msg>Fix 'test'.<commit_after>package main

import (
	"os"
	"fmt"
	"sync"
	"runtime"
)

var Config = struct {
	ProposeBuiltins bool "propose-builtins"
	DenyModuleRenames bool "deny-module-renames"
	LibPath string "lib-path"
}{
	false,
	false,
	"",
}

var btSync sync.Mutex

func printBacktrace(err interface{}) {
	btSync.Lock()
	defer btSync.Unlock()
	fmt.Printf("panic: %v\n", err)
	i := 2
	for {
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		f := runtime.FuncForPC(pc)
		fmt.Printf("%d(%s): %s:%d\n", i-1, f.Name(), file, line)
		i++
	}
	fmt.Println("")
}

func parseAsync(file string, done chan *ModuleCache) {
	go func() {
		m := NewModuleCache(file)
		m.updateCache()
		done <- m
	}()
}

func main() {
	done := make(chan *ModuleCache)
	for _, arg := range os.Args[1:] {
		parseAsync(arg, done)
	}
	for _, _ = range os.Args[1:] {
		d := <-done
		fmt.Printf("%s was parsed successfully\n", d.name)
		fmt.Printf("\t%d main declaration(s)\n", len(d.main.Children))
		fmt.Printf("\t%d foreign module(s)\n", len(d.others))
	}
	fmt.Printf("Total number of packages: %d\nOK\n", len(os.Args[1:]))
}
<|endoftext|>