<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/mgurov/hiptee/pkg"
	"github.com/mgurov/hiptee/pkg/hip"
	"github.com/mgurov/hiptee/pkg/std"
	"github.com/spf13/viper"
	"io"
	"log"
	"os"
)

const mainName = "hiptee"

var commit string
var version string

func main() {

	var hipchatToken string
	var hipchatRoom string
	var hipchatPollPrefix string

	var config string
	showVersionAndExit := flag.Bool("version", false, "show version and exit")
	flag.StringVar(&config, "config", "", "config file. Defaults to HIPTEE_CONFIG environmental variable. Json of contents {\"token\":<token>,\"room\":<room>} expected.")
	flag.StringVar(&hipchatToken, "token", "", "hipchat token to send notice with. Defaults to HIPCHAT_TOKEN environmental variable.")
	flag.StringVar(&hipchatRoom, "room", "", "hipchat room to send notice to. Defaults to HIPCHAT_ROOM environmental variable.")
	flag.StringVar(&hipchatPollPrefix, "poll", "", "if not empty, the hipchat room will be polled for the messages starting with this prefix and the remainder of the line will be sent to the stdin of the command in the exec mode")
	flag.Parse()

	if *showVersionAndExit {
		fmt.Println(mainName, "version", version, "commit", commit)
		return
	}

	viper.BindFlagValue("hipchat.token", stdFlagAdaptorValue{name: "token", value: &hipchatToken})
	viper.BindFlagValue("hipchat.room", stdFlagAdaptorValue{name: "room", value: &hipchatRoom})
	viper.BindFlagValue("hipchat.poll_prefix", stdFlagAdaptorValue{name: "room", value: &hipchatPollPrefix})

	viper.BindEnv("hipchat.token", "HIPCHAT_TOKEN")
	viper.BindEnv("hipchat.room", "HIPCHAT_ROOM")
	viper.BindEnv("hipchat.poll_prefix", "HIPCHAT_POLL_PREFIX")
	readViperConfig(config)

	if hipchatToken = viper.GetString("hipchat.token"); "" == hipchatToken {
		exitUsageIfEmpty(hipchatToken, "Hipchat token missing")
	}

	if hipchatRoom = viper.GetString("hipchat.room"); "" == hipchatRoom {
		exitUsageIfEmpty(hipchatRoom, "Hipchat room missing")
	}

	hipchatPollPrefix = viper.GetString("hipchat.poll_prefix")

	hc, err := hip.NewHipchatRoomPrinter(hipchatToken, hipchatRoom)
	if err != nil {
		log.Fatal("Error establishing hipchat printing ->"+hipchatToken+"<- ", err)
	}

	hipchatAndStdout := pkg.Compose(hc, &std.StdOutPrinter{})

	if len(os.Args) <= 1 {
		//classic tee from stdin

		if hipchatPollPrefix != "" {
			exitUsageIfEmpty("", "don't know what to do with the hipchat polled messages in the tee mode")
		}

		scanner := bufio.NewScanner(os.Stdin)
		for scanner.Scan() {
			hipchatAndStdout.Out(scanner.Text())
		}
		hipchatAndStdout.Done(nil)
	} else {
		var inCommandsReader io.Reader

		if hipchatPollPrefix != "" {
			inCommandsReader, err = hip.NewHipchatRoomReader(hipchatToken, hipchatRoom, hipchatPollPrefix)
			if nil != err {
				log.Fatal("Error establishing hipchat polling ", err)
			}
		}

		command := flag.Arg(0)
		params := flag.Args()[1:]
		if err := pkg.Execute(command, params, hipchatAndStdout, inCommandsReader); nil != err {
			os.Exit(1)
		}
	}
}

func readViperConfig(explicitConfigFile string) {
	if "" != explicitConfigFile {
		viper.SetConfigFile(explicitConfigFile)
	} else {
		viper.SetConfigName(mainName)
		viper.AddConfigPath("$HOME")
		viper.AddConfigPath(".")
	}

	err := viper.ReadInConfig()
	if err == nil {
		return
	}

	_, configNotFound := err.(viper.ConfigFileNotFoundError)

	if configNotFound && "" == explicitConfigFile {
		//config may be missing unless explicitly pointed to
		return
	}

	println("Could not read config file:", err.Error())
	os.Exit(1)
}

type stdFlagAdaptorValue struct {
	name  string
	value *string
}

func (f stdFlagAdaptorValue) HasChanged() bool    { return "" != *f.value }
func (f stdFlagAdaptorValue) Name() string        { return f.name }
func (f stdFlagAdaptorValue) ValueString() string { return *f.value }
func (f stdFlagAdaptorValue) ValueType() string   { return "string" }

func exitUsageIfEmpty(value, message string) {
	if value == "" {
		println(message)
		flag.Usage()
		os.Exit(1)
	}
}
<commit_msg>must for viper bindings<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/mgurov/hiptee/pkg"
	"github.com/mgurov/hiptee/pkg/hip"
	"github.com/mgurov/hiptee/pkg/std"
	"github.com/spf13/viper"
	"io"
	"log"
	"os"
)

const mainName = "hiptee"

var commit string
var version string

func main() {

	var hipchatToken string
	var hipchatRoom string
	var hipchatPollPrefix string

	var config string
	showVersionAndExit := flag.Bool("version", false, "show version and exit")
	flag.StringVar(&config, "config", "", "config file. Defaults to HIPTEE_CONFIG environmental variable. Json of contents {\"token\":<token>,\"room\":<room>} expected.")
	flag.StringVar(&hipchatToken, "token", "", "hipchat token to send notice with. Defaults to HIPCHAT_TOKEN environmental variable.")
	flag.StringVar(&hipchatRoom, "room", "", "hipchat room to send notice to. Defaults to HIPCHAT_ROOM environmental variable.")
	flag.StringVar(&hipchatPollPrefix, "poll", "", "if not empty, the hipchat room will be polled for the messages starting with this prefix and the remainder of the line will be sent to the stdin of the command in the exec mode")
	flag.Parse()

	if *showVersionAndExit {
		fmt.Println(mainName, "version", version, "commit", commit)
		return
	}

	must(viper.BindFlagValue("hipchat.token", stdFlagAdaptorValue{name: "token", value: &hipchatToken}))
	must(viper.BindFlagValue("hipchat.room", stdFlagAdaptorValue{name: "room", value: &hipchatRoom}))
	must(viper.BindFlagValue("hipchat.poll_prefix", stdFlagAdaptorValue{name: "room", value: &hipchatPollPrefix}))

	must(viper.BindEnv("hipchat.token", "HIPCHAT_TOKEN"))
	must(viper.BindEnv("hipchat.room", "HIPCHAT_ROOM"))
	must(viper.BindEnv("hipchat.poll_prefix", "HIPCHAT_POLL_PREFIX"))
	readViperConfig(config)

	if hipchatToken = viper.GetString("hipchat.token"); "" == hipchatToken {
		exitUsageIfEmpty(hipchatToken, "Hipchat token missing")
	}

	if hipchatRoom = viper.GetString("hipchat.room"); "" == hipchatRoom {
		exitUsageIfEmpty(hipchatRoom, "Hipchat room missing")
	}

	hipchatPollPrefix = viper.GetString("hipchat.poll_prefix")

	hc, err := hip.NewHipchatRoomPrinter(hipchatToken, hipchatRoom)
	if err != nil {
		log.Fatal("Error establishing hipchat printing ->"+hipchatToken+"<- ", err)
	}

	hipchatAndStdout := pkg.Compose(hc, &std.StdOutPrinter{})

	if len(os.Args) <= 1 {
		//classic tee from stdin

		if hipchatPollPrefix != "" {
			exitUsageIfEmpty("", "don't know what to do with the hipchat polled messages in the tee mode")
		}

		scanner := bufio.NewScanner(os.Stdin)
		for scanner.Scan() {
			hipchatAndStdout.Out(scanner.Text())
		}
		hipchatAndStdout.Done(nil)
	} else {
		var inCommandsReader io.Reader

		if hipchatPollPrefix != "" {
			inCommandsReader, err = hip.NewHipchatRoomReader(hipchatToken, hipchatRoom, hipchatPollPrefix)
			if nil != err {
				log.Fatal("Error establishing hipchat polling ", err)
			}
		}

		command := flag.Arg(0)
		params := flag.Args()[1:]
		if err := pkg.Execute(command, params, hipchatAndStdout, inCommandsReader); nil != err {
			os.Exit(1)
		}
	}
}

func must(err error) {
	if nil != err {
		log.Fatal(err)
	}
}

func readViperConfig(explicitConfigFile string) {
	if "" != explicitConfigFile {
		viper.SetConfigFile(explicitConfigFile)
	} else {
		viper.SetConfigName(mainName)
		viper.AddConfigPath("$HOME")
		viper.AddConfigPath(".")
	}

	err := viper.ReadInConfig()
	if err == nil {
		return
	}

	_, configNotFound := err.(viper.ConfigFileNotFoundError)

	if configNotFound && "" == explicitConfigFile {
		//config may be missing unless explicitly pointed to
		return
	}

	println("Could not read config file:", err.Error())
	os.Exit(1)
}

type stdFlagAdaptorValue struct {
	name  string
	value *string
}

func (f stdFlagAdaptorValue) HasChanged() bool    { return "" != *f.value }
func (f stdFlagAdaptorValue) Name() string        { return f.name }
func (f stdFlagAdaptorValue) ValueString() string { return *f.value }
func (f stdFlagAdaptorValue) ValueType() string   { return "string" }

func exitUsageIfEmpty(value, message string) {
	if value == "" {
		println(message)
		flag.Usage()
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package main

import (
	"errors"

	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/cmd/envcmd"
	"launchpad.net/juju-core/juju"
)

// ExposeCommand is responsible exposing services.
type ExposeCommand struct {
	envcmd.EnvCommandBase
	ServiceName string
}

func (c *ExposeCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "expose",
		Args:    "<service>",
		Purpose: "expose a service",
	}
}

func (c *ExposeCommand) Init(args []string) error {
	err := c.EnvCommandBase.Init()
	if err != nil {
		return err
	}
	if len(args) == 0 {
		return errors.New("no service name specified")
	}
	c.ServiceName = args[0]
	return cmd.CheckEmpty(args[1:])
}

// Run changes the juju-managed firewall to expose any
// ports that were also explicitly marked by units as open.
func (c *ExposeCommand) Run(_ *cmd.Context) error {
	client, err := juju.NewAPIClientFromName(c.EnvName)
	if err != nil {
		return err
	}
	defer client.Close()
	return client.ServiceExpose(c.ServiceName)
}
<commit_msg>help text for expose command<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package main

import (
	"errors"

	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/cmd/envcmd"
	"launchpad.net/juju-core/juju"
)

// ExposeCommand is responsible exposing services.
type ExposeCommand struct {
	envcmd.EnvCommandBase
	ServiceName string
}

var jujuExposeHelp = `
Adjusts firewall rules and similar security mechanisms of the provider, to
allow the service to be accessed on its public address.

`

func (c *ExposeCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "expose",
		Args:    "<service>",
		Purpose: "expose a service",
		Doc: jujuExposeHelp,
	}
}

func (c *ExposeCommand) Init(args []string) error {
	err := c.EnvCommandBase.Init()
	if err != nil {
		return err
	}
	if len(args) == 0 {
		return errors.New("no service name specified")
	}
	c.ServiceName = args[0]
	return cmd.CheckEmpty(args[1:])
}

// Run changes the juju-managed firewall to expose any
// ports that were also explicitly marked by units as open.
func (c *ExposeCommand) Run(_ *cmd.Context) error {
	client, err := juju.NewAPIClientFromName(c.EnvName)
	if err != nil {
		return err
	}
	defer client.Close()
	return client.ServiceExpose(c.ServiceName)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/url"
	"os"
	"runtime/pprof"
	"time"

	"github.com/prometheus/common/config"
	"github.com/prometheus/common/version"
	"gopkg.in/alecthomas/kingpin.v2"

	_ "github.com/grafana/loki/pkg/build"
	"github.com/grafana/loki/pkg/logcli/client"
	"github.com/grafana/loki/pkg/logcli/labelquery"
	"github.com/grafana/loki/pkg/logcli/output"
	"github.com/grafana/loki/pkg/logcli/query"
	"github.com/grafana/loki/pkg/logcli/seriesquery"
)

var (
	app        = kingpin.New("logcli", "A command-line for loki.").Version(version.Print("logcli"))
	quiet      = app.Flag("quiet", "Suppress query metadata").Default("false").Short('q').Bool()
	statistics = app.Flag("stats", "Show query statistics").Default("false").Bool()
	outputMode = app.Flag("output", "Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp.").Default("default").Short('o').Enum("default", "raw", "jsonl")
	timezone   = app.Flag("timezone", "Specify the timezone to use when formatting output timestamps [Local, UTC]").Default("Local").Short('z').Enum("Local", "UTC")
	cpuProfile = app.Flag("cpuprofile", "Specify the location for writing a CPU profile.").Default("").String()
	memProfile = app.Flag("memprofile", "Specify the location for writing a memory profile.").Default("").String()

	queryClient = newQueryClient(app)

	queryCmd = app.Command("query", `Run a LogQL query.

The "query" command is useful for querying for logs. Logs can be
returned in a few output modes:

	raw: log line
	default: log timestamp + log labels + log line
	jsonl: JSON response from Loki API of log line

The output of the log can be specified with the "-o" flag, for
example, "-o raw" for the raw output format.

The "query" command will output extra information about the query
and its results, such as the API URL, set of common labels, and set
of excluded labels. This extra information can be suppressed with the
--quiet flag.

While "query" does support metrics queries, its output contains multiple
data points between the start and end query time. This output is used to
build graphs, like what is seen in the Grafana Explore graph view. If
you are querying metrics and just want the most recent data point
(like what is seen in the Grafana Explore table view), then you should use
the "instant-query" command instead.`)
	rangeQuery = newQuery(false, queryCmd)
	tail       = queryCmd.Flag("tail", "Tail the logs").Short('t').Default("false").Bool()
	delayFor   = queryCmd.Flag("delay-for", "Delay in tailing by number of seconds to accumulate logs for re-ordering").Default("0").Int()

	instantQueryCmd = app.Command("instant-query", `Run an instant LogQL query.

The "instant-query" command is useful for evaluating a metric query for
a single point in time. This is equivalent to the Grafana Explore table
view; if you want a metrics query that is used to build a Grafana graph,
you should use the "query" command instead.

This command does not produce useful output when querying for log lines;
you should always use the "query" command when you are running log queries.

For more information about log queries and metric queries, refer to the
LogQL documentation:

https://github.com/grafana/loki/blob/master/docs/logql.md`)
	instantQuery = newQuery(true, instantQueryCmd)

	labelsCmd   = app.Command("labels", "Find values for a given label.")
	labelsQuery = newLabelQuery(labelsCmd)

	seriesCmd = app.Command("series", `Run series query.

The "series" command will take the provided label matcher
and return all the log streams found in the time window.

It is possible to send an empty label matcher '{}' to return all streams.

Use the --analyze-labels flag to get a summary of the labels found in all streams.
This is helpful to find high cardinality labels.
`)
	seriesQuery = newSeriesQuery(seriesCmd)
)

func main() {
	log.SetOutput(os.Stderr)

	cmd := kingpin.MustParse(app.Parse(os.Args[1:]))

	if cpuProfile != nil && *cpuProfile != "" {
		cpuFile, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		defer cpuFile.Close()
		if err := pprof.StartCPUProfile(cpuFile); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
	}

	if memProfile != nil && *memProfile != "" {
		memFile, err := os.Create(*memProfile)
		if err != nil {
			log.Fatal("could not create memory profile: ", err)
		}
		defer memFile.Close()
		defer func() {
			if err := pprof.WriteHeapProfile(memFile); err != nil {
				log.Fatal("could not write memory profile: ", err)
			}
		}()
	}

	switch cmd {
	case queryCmd.FullCommand():
		location, err := time.LoadLocation(*timezone)
		if err != nil {
			log.Fatalf("Unable to load timezone '%s': %s", *timezone, err)
		}

		outputOptions := &output.LogOutputOptions{
			Timezone:      location,
			NoLabels:      rangeQuery.NoLabels,
			ColoredOutput: rangeQuery.ColoredOutput,
		}

		out, err := output.NewLogOutput(os.Stdout, *outputMode, outputOptions)
		if err != nil {
			log.Fatalf("Unable to create log output: %s", err)
		}

		if *tail {
			rangeQuery.TailQuery(*delayFor, queryClient, out)
		} else {
			rangeQuery.DoQuery(queryClient, out, *statistics)
		}
	case instantQueryCmd.FullCommand():
		location, err := time.LoadLocation(*timezone)
		if err != nil {
			log.Fatalf("Unable to load timezone '%s': %s", *timezone, err)
		}

		outputOptions := &output.LogOutputOptions{
			Timezone:      location,
			NoLabels:      instantQuery.NoLabels,
			ColoredOutput: instantQuery.ColoredOutput,
		}

		out, err := output.NewLogOutput(os.Stdout, *outputMode, outputOptions)
		if err != nil {
			log.Fatalf("Unable to create log output: %s", err)
		}

		instantQuery.DoQuery(queryClient, out, *statistics)
	case labelsCmd.FullCommand():
		labelsQuery.DoLabels(queryClient)
	case seriesCmd.FullCommand():
		seriesQuery.DoSeries(queryClient)
	}
}

func newQueryClient(app *kingpin.Application) client.Client {

	client := &client.DefaultClient{
		TLSConfig: config.TLSConfig{},
	}

	// extract host
	addressAction := func(c *kingpin.ParseContext) error {
		u, err := url.Parse(client.Address)
		if err != nil {
			return err
		}
		client.TLSConfig.ServerName = u.Host
		return nil
	}

	app.Flag("addr", "Server address. Can also be set using LOKI_ADDR env var.").Default("http://localhost:3100").Envar("LOKI_ADDR").Action(addressAction).StringVar(&client.Address)
	app.Flag("username", "Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var.").Default("").Envar("LOKI_USERNAME").StringVar(&client.Username)
	app.Flag("password", "Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var.").Default("").Envar("LOKI_PASSWORD").StringVar(&client.Password)
	app.Flag("ca-cert", "Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var.").Default("").Envar("LOKI_CA_CERT_PATH").StringVar(&client.TLSConfig.CAFile)
	app.Flag("tls-skip-verify", "Server certificate TLS skip verify.").Default("false").Envar("LOKI_TLS_SKIP_VERIFY").BoolVar(&client.TLSConfig.InsecureSkipVerify)
	app.Flag("cert", "Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var.").Default("").Envar("LOKI_CLIENT_CERT_PATH").StringVar(&client.TLSConfig.CertFile)
	app.Flag("key", "Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var.").Default("").Envar("LOKI_CLIENT_KEY_PATH").StringVar(&client.TLSConfig.KeyFile)
	app.Flag("org-id", "adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway.").Default("").Envar("LOKI_ORG_ID").StringVar(&client.OrgID)

	return client
}

func newLabelQuery(cmd *kingpin.CmdClause) *labelquery.LabelQuery {
	var labelName, from, to string
	var since time.Duration

	q := &labelquery.LabelQuery{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		defaultEnd := time.Now()
		defaultStart := defaultEnd.Add(-since)

		q.Start = mustParse(from, defaultStart)
		q.End = mustParse(to, defaultEnd)
		q.LabelName = labelName
		q.Quiet = *quiet
		return nil
	})

	cmd.Arg("label", "The name of the label.").Default("").StringVar(&labelName)
	cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
	cmd.Flag("from", "Start looking for labels at this absolute time (inclusive)").StringVar(&from)
	cmd.Flag("to", "Stop looking for labels at this absolute time (exclusive)").StringVar(&to)

	return q
}

func newSeriesQuery(cmd *kingpin.CmdClause) *seriesquery.SeriesQuery {
	// calculate series range from cli params
	var from, to string
	var since time.Duration

	q := &seriesquery.SeriesQuery{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		defaultEnd := time.Now()
		defaultStart := defaultEnd.Add(-since)

		q.Start = mustParse(from, defaultStart)
		q.End = mustParse(to, defaultEnd)
		q.Quiet = *quiet
		return nil
	})

	cmd.Arg("matcher", "eg '{foo=\"bar\",baz=~\".*blip\"}'").Required().StringVar(&q.Matcher)
	cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
	cmd.Flag("from", "Start looking for logs at this absolute time (inclusive)").StringVar(&from)
	cmd.Flag("to", "Stop looking for logs at this absolute time (exclusive)").StringVar(&to)
	cmd.Flag("analyze-labels", "Printout a summary of labels including count of label value combinations, useful for debugging high cardinality series").BoolVar(&q.AnalyzeLabels)

	return q
}

func newQuery(instant bool, cmd *kingpin.CmdClause) *query.Query {
	// calculate query range from cli params
	var now, from, to string
	var since time.Duration

	q := &query.Query{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		if instant {
			q.SetInstant(mustParse(now, time.Now()))
		} else {
			defaultEnd := time.Now()
			defaultStart := defaultEnd.Add(-since)

			q.Start = mustParse(from, defaultStart)
			q.End = mustParse(to, defaultEnd)
		}
		q.Quiet = *quiet
		return nil
	})

	cmd.Flag("limit", "Limit on number of entries to print.").Default("30").IntVar(&q.Limit)
	if instant {
		cmd.Arg("query", "eg 'rate({foo=\"bar\"} |~ \".*error.*\" [5m])'").Required().StringVar(&q.QueryString)
		cmd.Flag("now", "Time at which to execute the instant query.").StringVar(&now)
	} else {
		cmd.Arg("query", "eg '{foo=\"bar\",baz=~\".*blip\"} |~ \".*error.*\"'").Required().StringVar(&q.QueryString)
		cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
		cmd.Flag("from", "Start looking for logs at this absolute time (inclusive)").StringVar(&from)
		cmd.Flag("to", "Stop looking for logs at this absolute time (exclusive)").StringVar(&to)
		cmd.Flag("step", "Query resolution step width, for metric queries. Evaluate the query at the specified step over the time range.").DurationVar(&q.Step)
		cmd.Flag("interval", "Query interval, for log queries. Return entries at the specified interval, ignoring those between. **This parameter is experimental, please see Issue 1779**").DurationVar(&q.Interval)
		cmd.Flag("batch", "Query batch size to use until 'limit' is reached").Default("1000").IntVar(&q.BatchSize)
	}

	cmd.Flag("forward", "Scan forwards through logs.").Default("false").BoolVar(&q.Forward)
	cmd.Flag("no-labels", "Do not print any labels").Default("false").BoolVar(&q.NoLabels)
	cmd.Flag("exclude-label", "Exclude labels given the provided key during output.").StringsVar(&q.IgnoreLabelsKey)
	cmd.Flag("include-label", "Include labels given the provided key during output.").StringsVar(&q.ShowLabelsKey)
	cmd.Flag("labels-length", "Set a fixed padding to labels").Default("0").IntVar(&q.FixedLabelsLen)
	cmd.Flag("store-config", "Execute the current query using a configured storage from a given Loki configuration file.").Default("").StringVar(&q.LocalConfig)
	cmd.Flag("colored-output", "Show output with colored labels").Default("false").BoolVar(&q.ColoredOutput)

	return q
}

func mustParse(t string, defaultTime time.Time) time.Time {
	if t == "" {
		return defaultTime
	}

	ret, err := time.Parse(time.RFC3339Nano, t)

	if err != nil {
		log.Fatalf("Unable to parse time %v", err)
	}

	return ret
}
<commit_msg>Add a few more instructions to logcli --help. (#2948)<commit_after>package main

import (
	"log"
	"net/url"
	"os"
	"runtime/pprof"
	"time"

	"github.com/prometheus/common/config"
	"github.com/prometheus/common/version"
	"gopkg.in/alecthomas/kingpin.v2"

	_ "github.com/grafana/loki/pkg/build"
	"github.com/grafana/loki/pkg/logcli/client"
	"github.com/grafana/loki/pkg/logcli/labelquery"
	"github.com/grafana/loki/pkg/logcli/output"
	"github.com/grafana/loki/pkg/logcli/query"
	"github.com/grafana/loki/pkg/logcli/seriesquery"
)

var (
	app        = kingpin.New("logcli", "A command-line for loki.").Version(version.Print("logcli"))
	quiet      = app.Flag("quiet", "Suppress query metadata").Default("false").Short('q').Bool()
	statistics = app.Flag("stats", "Show query statistics").Default("false").Bool()
	outputMode = app.Flag("output", "Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp.").Default("default").Short('o').Enum("default", "raw", "jsonl")
	timezone   = app.Flag("timezone", "Specify the timezone to use when formatting output timestamps [Local, UTC]").Default("Local").Short('z').Enum("Local", "UTC")
	cpuProfile = app.Flag("cpuprofile", "Specify the location for writing a CPU profile.").Default("").String()
	memProfile = app.Flag("memprofile", "Specify the location for writing a memory profile.").Default("").String()

	queryClient = newQueryClient(app)

	queryCmd = app.Command("query", `Run a LogQL query.

The "query" command is useful for querying for logs. Logs can be
returned in a few output modes:

	raw: log line
	default: log timestamp + log labels + log line
	jsonl: JSON response from Loki API of log line

The output of the log can be specified with the "-o" flag, for
example, "-o raw" for the raw output format.

The "query" command will output extra information about the query
and its results, such as the API URL, set of common labels, and set
of excluded labels. This extra information can be suppressed with the
--quiet flag.

By default we look over the last hour of data; use --since to modify
or provide specific start and end times with --start and --end.
The output is limited to 30 entries by default; use --limit to increase.

While "query" does support metrics queries, its output contains multiple
data points between the start and end query time. This output is used to
build graphs, similar to what is seen in the Grafana Explore graph view.
If you are querying metrics and just want the most recent data point
(like what is seen in the Grafana Explore table view), then you should use
the "instant-query" command instead.`)
	rangeQuery = newQuery(false, queryCmd)
	tail       = queryCmd.Flag("tail", "Tail the logs").Short('t').Default("false").Bool()
	delayFor   = queryCmd.Flag("delay-for", "Delay in tailing by number of seconds to accumulate logs for re-ordering").Default("0").Int()

	instantQueryCmd = app.Command("instant-query", `Run an instant LogQL query.

The "instant-query" command is useful for evaluating a metric query for
a single point in time. This is equivalent to the Grafana Explore table
view; if you want a metrics query that is used to build a Grafana graph,
you should use the "query" command instead.

This command does not produce useful output when querying for log lines;
you should always use the "query" command when you are running log queries.

For more information about log queries and metric queries, refer to the
LogQL documentation:

https://github.com/grafana/loki/blob/master/docs/logql.md`)
	instantQuery = newQuery(true, instantQueryCmd)

	labelsCmd   = app.Command("labels", "Find values for a given label.")
	labelsQuery = newLabelQuery(labelsCmd)

	seriesCmd = app.Command("series", `Run series query.

The "series" command will take the provided label matcher
and return all the log streams found in the time window.

It is possible to send an empty label matcher '{}' to return all streams.

Use the --analyze-labels flag to get a summary of the labels found in all streams.
This is helpful to find high cardinality labels.
`)
	seriesQuery = newSeriesQuery(seriesCmd)
)

func main() {
	log.SetOutput(os.Stderr)

	cmd := kingpin.MustParse(app.Parse(os.Args[1:]))

	if cpuProfile != nil && *cpuProfile != "" {
		cpuFile, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		defer cpuFile.Close()
		if err := pprof.StartCPUProfile(cpuFile); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
	}

	if memProfile != nil && *memProfile != "" {
		memFile, err := os.Create(*memProfile)
		if err != nil {
			log.Fatal("could not create memory profile: ", err)
		}
		defer memFile.Close()
		defer func() {
			if err := pprof.WriteHeapProfile(memFile); err != nil {
				log.Fatal("could not write memory profile: ", err)
			}
		}()
	}

	switch cmd {
	case queryCmd.FullCommand():
		location, err := time.LoadLocation(*timezone)
		if err != nil {
			log.Fatalf("Unable to load timezone '%s': %s", *timezone, err)
		}

		outputOptions := &output.LogOutputOptions{
			Timezone:      location,
			NoLabels:      rangeQuery.NoLabels,
			ColoredOutput: rangeQuery.ColoredOutput,
		}

		out, err := output.NewLogOutput(os.Stdout, *outputMode, outputOptions)
		if err != nil {
			log.Fatalf("Unable to create log output: %s", err)
		}

		if *tail {
			rangeQuery.TailQuery(*delayFor, queryClient, out)
		} else {
			rangeQuery.DoQuery(queryClient, out, *statistics)
		}
	case instantQueryCmd.FullCommand():
		location, err := time.LoadLocation(*timezone)
		if err != nil {
			log.Fatalf("Unable to load timezone '%s': %s", *timezone, err)
		}

		outputOptions := &output.LogOutputOptions{
			Timezone:      location,
			NoLabels:      instantQuery.NoLabels,
			ColoredOutput: instantQuery.ColoredOutput,
		}

		out, err := output.NewLogOutput(os.Stdout, *outputMode, outputOptions)
		if err != nil {
			log.Fatalf("Unable to create log output: %s", err)
		}

		instantQuery.DoQuery(queryClient, out, *statistics)
	case labelsCmd.FullCommand():
		labelsQuery.DoLabels(queryClient)
	case seriesCmd.FullCommand():
		seriesQuery.DoSeries(queryClient)
	}
}

func newQueryClient(app *kingpin.Application) client.Client {

	client := &client.DefaultClient{
		TLSConfig: config.TLSConfig{},
	}

	// extract host
	addressAction := func(c *kingpin.ParseContext) error {
		u, err := url.Parse(client.Address)
		if err != nil {
			return err
		}
		client.TLSConfig.ServerName = u.Host
		return nil
	}

	app.Flag("addr", "Server address. Can also be set using LOKI_ADDR env var.").Default("http://localhost:3100").Envar("LOKI_ADDR").Action(addressAction).StringVar(&client.Address)
	app.Flag("username", "Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var.").Default("").Envar("LOKI_USERNAME").StringVar(&client.Username)
	app.Flag("password", "Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var.").Default("").Envar("LOKI_PASSWORD").StringVar(&client.Password)
	app.Flag("ca-cert", "Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var.").Default("").Envar("LOKI_CA_CERT_PATH").StringVar(&client.TLSConfig.CAFile)
	app.Flag("tls-skip-verify", "Server certificate TLS skip verify.").Default("false").Envar("LOKI_TLS_SKIP_VERIFY").BoolVar(&client.TLSConfig.InsecureSkipVerify)
	app.Flag("cert", "Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var.").Default("").Envar("LOKI_CLIENT_CERT_PATH").StringVar(&client.TLSConfig.CertFile)
	app.Flag("key", "Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var.").Default("").Envar("LOKI_CLIENT_KEY_PATH").StringVar(&client.TLSConfig.KeyFile)
	app.Flag("org-id", "adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway.").Default("").Envar("LOKI_ORG_ID").StringVar(&client.OrgID)

	return client
}

func newLabelQuery(cmd *kingpin.CmdClause) *labelquery.LabelQuery {
	var labelName, from, to string
	var since time.Duration

	q := &labelquery.LabelQuery{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		defaultEnd := time.Now()
		defaultStart := defaultEnd.Add(-since)

		q.Start = mustParse(from, defaultStart)
		q.End = mustParse(to, defaultEnd)
		q.LabelName = labelName
		q.Quiet = *quiet
		return nil
	})

	cmd.Arg("label", "The name of the label.").Default("").StringVar(&labelName)
	cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
	cmd.Flag("from", "Start looking for labels at this absolute time (inclusive)").StringVar(&from)
	cmd.Flag("to", "Stop looking for labels at this absolute time (exclusive)").StringVar(&to)

	return q
}

func newSeriesQuery(cmd *kingpin.CmdClause) *seriesquery.SeriesQuery {
	// calculate series range from cli params
	var from, to string
	var since time.Duration

	q := &seriesquery.SeriesQuery{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		defaultEnd := time.Now()
		defaultStart := defaultEnd.Add(-since)

		q.Start = mustParse(from, defaultStart)
		q.End = mustParse(to, defaultEnd)
		q.Quiet = *quiet
		return nil
	})

	cmd.Arg("matcher", "eg '{foo=\"bar\",baz=~\".*blip\"}'").Required().StringVar(&q.Matcher)
	cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
	cmd.Flag("from", "Start looking for logs at this absolute time (inclusive)").StringVar(&from)
	cmd.Flag("to", "Stop looking for logs at this absolute time (exclusive)").StringVar(&to)
	cmd.Flag("analyze-labels", "Printout a summary of labels including count of label value combinations, useful for debugging high cardinality series").BoolVar(&q.AnalyzeLabels)

	return q
}

func newQuery(instant bool, cmd *kingpin.CmdClause) *query.Query {
	// calculate query range from cli params
	var now, from, to string
	var since time.Duration

	q := &query.Query{}

	// executed after all command flags are parsed
	cmd.Action(func(c *kingpin.ParseContext) error {

		if instant {
			q.SetInstant(mustParse(now, time.Now()))
		} else {
			defaultEnd := time.Now()
			defaultStart := defaultEnd.Add(-since)

			q.Start = mustParse(from, defaultStart)
			q.End = mustParse(to, defaultEnd)
		}
		q.Quiet = *quiet
		return nil
	})

	cmd.Flag("limit", "Limit on number of entries to print.").Default("30").IntVar(&q.Limit)
	if instant {
		cmd.Arg("query", "eg 'rate({foo=\"bar\"} |~ \".*error.*\" [5m])'").Required().StringVar(&q.QueryString)
		cmd.Flag("now", "Time at which to execute the instant query.").StringVar(&now)
	} else {
		cmd.Arg("query", "eg '{foo=\"bar\",baz=~\".*blip\"} |~ \".*error.*\"'").Required().StringVar(&q.QueryString)
		cmd.Flag("since", "Lookback window.").Default("1h").DurationVar(&since)
		cmd.Flag("from", "Start looking for logs at this absolute time (inclusive)").StringVar(&from)
		cmd.Flag("to", "Stop looking for logs at this absolute time (exclusive)").StringVar(&to)
		cmd.Flag("step", "Query resolution step width, for metric queries. Evaluate the query at the specified step over the time range.").DurationVar(&q.Step)
		cmd.Flag("interval", "Query interval, for log queries. Return entries at the specified interval, ignoring those between. **This parameter is experimental, please see Issue 1779**").DurationVar(&q.Interval)
		cmd.Flag("batch", "Query batch size to use until 'limit' is reached").Default("1000").IntVar(&q.BatchSize)
	}

	cmd.Flag("forward", "Scan forwards through logs.").Default("false").BoolVar(&q.Forward)
	cmd.Flag("no-labels", "Do not print any labels").Default("false").BoolVar(&q.NoLabels)
	cmd.Flag("exclude-label", "Exclude labels given the provided key during output.").StringsVar(&q.IgnoreLabelsKey)
	cmd.Flag("include-label", "Include labels given the provided key during output.").StringsVar(&q.ShowLabelsKey)
	cmd.Flag("labels-length", "Set a fixed padding to labels").Default("0").IntVar(&q.FixedLabelsLen)
	cmd.Flag("store-config", "Execute the current query using a configured storage from a given Loki configuration file.").Default("").StringVar(&q.LocalConfig)
	cmd.Flag("colored-output", "Show output with colored labels").Default("false").BoolVar(&q.ColoredOutput)

	return q
}

func mustParse(t string, defaultTime time.Time) time.Time {
	if t == "" {
		return defaultTime
	}

	ret, err := time.Parse(time.RFC3339Nano, t)

	if err != nil {
		log.Fatalf("Unable to parse time %v", err)
	}

	return ret
}
<|endoftext|>


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

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"path/filepath"
	"strings"

	"github.com/ulikunitz/xz/lzma"
	"github.com/ulikunitz/xz/xlog"
)

type compressor interface {
	outputPaths(path string) (outputPath, tmpPath string, err error)
	compress(w io.Writer, r io.Reader, preset int) (n int64, err error)
}

const lzmaSuffix = ".lzma"

// parameters converts the lzmago executable flags to lzma parameters.
//
// I cannot use the preset config from the Tukaani project directly,
// because I don't have two algorithm modes and can't support parameters
// like nice_len or depth. So at this point in time I stay with the
// dictionary sizes the default combination of (LC,LP,LB) = (3,0,2).
// The default preset is 6.
// Following list provides exponents of two for the dictionary sizes:
// 18, 20, 21, 22, 22, 23, 23, 24, 25, 26.
func parameters(preset int) lzma.Parameters {
	dictCapExps := []uint{18, 20, 21, 22, 22, 23, 23, 24, 25, 26}
	dictCap := 1 << dictCapExps[preset]
	p := lzma.Parameters{
		LC:        3,
		LP:        0,
		PB:        2,
		DictCap:   dictCap,
		Size:      -1,
		EOSMarker: true,
	}
	return p
}

type lzmaCompressor struct{}

func (p lzmaCompressor) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if path == "" {
		err = errors.New("path is empty")
		return
	}
	if strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has suffix %s -- ignored",
			path, lzmaSuffix)
		return
	}
	out = path + lzmaSuffix
	tmp = out + ".compress"
	return
}

func (p lzmaCompressor) compress(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	params := parameters(preset)
	bw := bufio.NewWriter(w)
	lw, err := lzma.NewWriterParams(bw, &params)
	if err != nil {
		return
	}
	n, err = io.Copy(lw, r)
	if err != nil {
		return
	}
	if err = lw.Close(); err != nil {
		return
	}
	err = bw.Flush()
	return
}

type lzmaDecompressor struct{}

func (d lzmaDecompressor) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if !strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has no suffix %s",
			path, lzmaSuffix)
		return
	}
	base := filepath.Base(path)
	if base == lzmaSuffix {
		err = fmt.Errorf(
			"path %s has only suffix %s as filename",
			path, lzmaSuffix)
		return
	}
	out = path[:len(path)-len(lzmaSuffix)]
	tmp = out + ".decompress"
	return
}

func (u lzmaDecompressor) compress(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	br := bufio.NewReader(r)
	lr, err := lzma.NewReader(br)
	if err != nil {
		return
	}
	n, err = io.Copy(w, lr)
	return
}

func signalHandler(tmpPath string) chan<- struct{} {
	quit := make(chan struct{})
	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, os.Interrupt)
	go func() {
		select {
		case <-quit:
			signal.Stop(sigch)
			return
		case <-sigch:
			if tmpPath != "-" {
				os.Remove(tmpPath)
			}
			os.Exit(7)
		}
	}()
	return quit
}

func compressFile(comp compressor, path, tmpPath string, opts *options) error {
	var err error

	// open reader
	var r *os.File
	if path == "-" {
		r = os.Stdin
	} else {
		fi, err := os.Lstat(path)
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", path)
		}
		r, err = os.Open(path)
		if err != nil {
			return err
		}
		fi, err = r.Stat()
		if err != nil {
			r.Close()
			return err
		}
		if !fi.Mode().IsRegular() {
			r.Close()
			return fmt.Errorf("%s is not a regular file", path)
		}
	}
	defer func() {
		if err != nil {
			r.Close()
		} else {
			err = r.Close()
		}
	}()

	// open writer
	var w *os.File
	if tmpPath == "-" {
		w = os.Stdout
	} else {
		if opts.force {
			os.Remove(tmpPath)
		}
		w, err = os.OpenFile(tmpPath,
			os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
		if err != nil {
			return err
		}
		defer func() {
			if err != nil {
				w.Close()
			} else {
				err = w.Close()
			}
		}()
		fi, err := w.Stat()
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", tmpPath)
		}
	}

	_, err = comp.compress(w, r, opts.preset)
	return err
}

// userPathError represents a path error presentable to a user. In
// difference to os.PathError it removes the information of the
// operation returning the error.
type userPathError struct {
	Path string
	Err  error
}

// Error provides the error string for the path error.
func (e *userPathError) Error() string {
	return e.Path + ": " + e.Err.Error()
}

// userError converts path error to an error message that is
// acceptable for lzmago users. PathError provides information about the
// command that has created an error. For instance Lstat informs that
// lstat detected that a file didn't exist this information is not
// relevant for users of the lzmago program. This function converts a
// path error into a generic error removing the operation information.
func userError(err error) error {
	pe, ok := err.(*os.PathError)
	if !ok {
		return err
	}
	return &userPathError{Path: pe.Path, Err: pe.Err}
}

func processFile(path string, opts *options) {
	var comp compressor
	if opts.decompress {
		comp = lzmaDecompressor{}
	} else {
		comp = lzmaCompressor{}
	}
	outputPath, tmpPath, err := comp.outputPaths(path)
	if err != nil {
		xlog.Warn(userError(err))
		return
	}
	if opts.stdout {
		outputPath, tmpPath = "-", "-"
	}
	if outputPath != "-" {
		_, err = os.Lstat(outputPath)
		if err == nil && !opts.force {
			xlog.Warnf("file %s exists", outputPath)
			return
		}
	}
	defer func() {
		if tmpPath != "-" {
			os.Remove(tmpPath)
		}
	}()
	quit := signalHandler(tmpPath)
	defer close(quit)

	if err = compressFile(comp, path, tmpPath, opts); err != nil {
		xlog.Warn(userError(err))
		return
	}
	if tmpPath != "-" && outputPath != "-" {
		if err = os.Rename(tmpPath, outputPath); err != nil {
			xlog.Warn(userError(err))
			return
		}
	}
	if !opts.keep && !opts.stdout && path != "-" {
		if err = os.Remove(path); err != nil {
			xlog.Warn(userError(err))
			return
		}
	}
}
<commit_msg>lzmago: adapted code to new lzma interface<commit_after>// Copyright 2015 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"path/filepath"
	"strings"

	"github.com/ulikunitz/xz/lzma"
	"github.com/ulikunitz/xz/xlog"
)

type compressor interface {
	outputPaths(path string) (outputPath, tmpPath string, err error)
	compress(w io.Writer, r io.Reader, preset int) (n int64, err error)
}

const lzmaSuffix = ".lzma"

// dictCapExps maps preset values to exponent for dictionary capacity
// sizes.
var dictCapExps = []uint{18, 20, 21, 22, 22, 23, 23, 24, 25, 26}

// setParameters sets the parameters for the lzma writer using the given
// preset.
func setParameters(w *lzma.Writer, preset int) {
	w.Properties = lzma.Properties{LC: 3, LP: 0, PB: 2}
	w.DictCap = 1 << dictCapExps[preset]
	w.Size = -1
	w.EOSMarker = true
}

type lzmaCompressor struct{}

func (p lzmaCompressor) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if path == "" {
		err = errors.New("path is empty")
		return
	}
	if strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has suffix %s -- ignored",
			path, lzmaSuffix)
		return
	}
	out = path + lzmaSuffix
	tmp = out + ".compress"
	return
}

func (p lzmaCompressor) compress(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	bw := bufio.NewWriter(w)
	lw := lzma.NewWriter(bw)
	setParameters(lw, preset)
	n, err = io.Copy(lw, r)
	if err != nil {
		return
	}
	if err = lw.Close(); err != nil {
		return
	}
	err = bw.Flush()
	return
}

type lzmaDecompressor struct{}

func (d lzmaDecompressor) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if !strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has no suffix %s",
			path, lzmaSuffix)
		return
	}
	base := filepath.Base(path)
	if base == lzmaSuffix {
		err = fmt.Errorf(
			"path %s has only suffix %s as filename",
			path, lzmaSuffix)
		return
	}
	out = path[:len(path)-len(lzmaSuffix)]
	tmp = out + ".decompress"
	return
}

func (u lzmaDecompressor) compress(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	br := bufio.NewReader(r)
	lr, err := lzma.NewReader(br)
	if err != nil {
		return
	}
	n, err = io.Copy(w, lr)
	return
}

func signalHandler(tmpPath string) chan<- struct{} {
	quit := make(chan struct{})
	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, os.Interrupt)
	go func() {
		select {
		case <-quit:
			signal.Stop(sigch)
			return
		case <-sigch:
			if tmpPath != "-" {
				os.Remove(tmpPath)
			}
			os.Exit(7)
		}
	}()
	return quit
}

func compressFile(comp compressor, path, tmpPath string, opts *options) error {
	var err error

	// open reader
	var r *os.File
	if path == "-" {
		r = os.Stdin
	} else {
		fi, err := os.Lstat(path)
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", path)
		}
		r, err = os.Open(path)
		if err != nil {
			return err
		}
		fi, err = r.Stat()
		if err != nil {
			r.Close()
			return err
		}
		if !fi.Mode().IsRegular() {
			r.Close()
			return fmt.Errorf("%s is not a regular file", path)
		}
	}
	defer func() {
		if err != nil {
			r.Close()
		} else {
			err = r.Close()
		}
	}()

	// open writer
	var w *os.File
	if tmpPath == "-" {
		w = os.Stdout
	} else {
		if opts.force {
			os.Remove(tmpPath)
		}
		w, err = os.OpenFile(tmpPath,
			os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
		if err != nil {
			return err
		}
		defer func() {
			if err != nil {
				w.Close()
			} else {
				err = w.Close()
			}
		}()
		fi, err := w.Stat()
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", tmpPath)
		}
	}

	_, err = comp.compress(w, r, opts.preset)
	return err
}

// userPathError represents a path error presentable to a user. In
// difference to os.PathError it removes the information of the
// operation returning the error.
type userPathError struct {
	Path string
	Err  error
}

// Error provides the error string for the path error.
func (e *userPathError) Error() string {
	return e.Path + ": " + e.Err.Error()
}

// userError converts path error to an error message that is
// acceptable for lzmago users. PathError provides information about the
// command that has created an error. For instance Lstat informs that
// lstat detected that a file didn't exist this information is not
// relevant for users of the lzmago program. This function converts a
// path error into a generic error removing the operation information.
func userError(err error) error {
	pe, ok := err.(*os.PathError)
	if !ok {
		return err
	}
	return &userPathError{Path: pe.Path, Err: pe.Err}
}

func processFile(path string, opts *options) {
	var comp compressor
	if opts.decompress {
		comp = lzmaDecompressor{}
	} else {
		comp = lzmaCompressor{}
	}
	outputPath, tmpPath, err := comp.outputPaths(path)
	if err != nil {
		xlog.Warn(userError(err))
		return
	}
	if opts.stdout {
		outputPath, tmpPath = "-", "-"
	}
	if outputPath != "-" {
		_, err = os.Lstat(outputPath)
		if err == nil && !opts.force {
			xlog.Warnf("file %s exists", outputPath)
			return
		}
	}
	defer func() {
		if tmpPath != "-" {
			os.Remove(tmpPath)
		}
	}()
	quit := signalHandler(tmpPath)
	defer close(quit)

	if err = compressFile(comp, path, tmpPath, opts); err != nil {
		xlog.Warn(userError(err))
		return
	}
	if tmpPath != "-" && outputPath != "-" {
		if err = os.Rename(tmpPath, outputPath); err != nil {
			xlog.Warn(userError(err))
			return
		}
	}
	if !opts.keep && !opts.stdout && path != "-" {
		if err = os.Remove(path); err != nil {
			xlog.Warn(userError(err))
			return
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/css"
	"github.com/tdewolff/minify/html"
	"github.com/tdewolff/minify/js"
	"github.com/tdewolff/minify/json"
	"github.com/tdewolff/minify/svg"
	"github.com/tdewolff/minify/xml"
)

var (
	extMime = map[string]string{
		".css":  "text/css",
		".html": "text/html",
		".js":   "application/javascript",
		".json": "[/+]json$",
		".svg":  "image/svg+xml",
		".xml":  "[/+]xml$",
	}
)

func main() {
	input := ""
	output := ""
	ext := ""
	directory := ""
	recursive := false

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] [file]\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.StringVar(&output, "o", "", "Output file (stdout when empty)")
	flag.StringVar(&ext, "x", "", "File extension (css, html, js, json, svg or xml), optional for input files")
	flag.StringVar(&directory, "d", "", "Directory to search for files")
	flag.BoolVar(&recursive, "r", false, "Recursively minify everything")
	flag.Parse()
	if len(flag.Args()) > 0 {
		input = flag.Arg(0)
	}

	extPassed := (ext != "")

	mediatype := ""
	r := io.Reader(os.Stdin)
	w := io.Writer(os.Stdout)
	m := minify.New()
	m.AddFunc(extMime[".css"], css.Minify)
	m.AddFunc(extMime[".html"], html.Minify)
	m.AddFunc(extMime[".js"], js.Minify)
	m.AddFunc(extMime[".svg"], svg.Minify)
	m.AddFuncRegexp(regexp.MustCompile(extMime[".json"]), json.Minify)
	m.AddFuncRegexp(regexp.MustCompile(extMime[".xml"]), xml.Minify)

	filenames := make(map[string]string)
	if directory != "" {
		filenames = ioNames(directory, recursive)
	} else {
		filenames[input] = output
	}

	for in, out := range filenames {
		input = in
		output = out

		if input != "" {
			in, err := os.Open(input)
			if err != nil {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
			defer in.Close()
			r = in
			if input == output {
				b := &bytes.Buffer{}
				io.Copy(b, r)
				r = b
			}
			if !extPassed {
				ext = filepath.Ext(input)
			}
		}
		if output != "" {
			out, err := os.Create(output)
			if err != nil {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
			defer out.Close()
			w = out
		}
		if ext != "" {
			mediatype = extMime[ext]
		}

		if err := m.Minify(mediatype, w, r); err != nil {
			if err == minify.ErrNotExist {
				io.Copy(w, r)
			} else {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
		}
	}
}

// ioNames returns a map of input paths and output paths.
func ioNames(startDir string, recursive bool) map[string]string {
	names := map[string]string{}

	if recursive {
		filepath.Walk(startDir, func(path string, info os.FileInfo, _ error) error {
			if !validFile(info) {
				return nil
			}

			names[path] = minExt(path)

			return nil
		})

		return names
	}

	infos, err := ioutil.ReadDir(startDir)
	if err != nil {
		return map[string]string{}
	}

	for _, info := range infos {
		if !validFile(info) {
			continue
		}

		fullPath := filepath.Join(startDir, info.Name())
		names[fullPath] = minExt(fullPath)
	}

	return names
}

// validFile checks to see if a file is a directory, hidden, already has the
// minified extension, or if it's one of the minifiable extensions.
func validFile(info os.FileInfo) bool {
	if info.IsDir() {
		return false
	}

	if info.Name()[0] == '.' {
		return false
	}

	// don't want to reminify already minified files
	if strings.Contains(info.Name(), ".min.") {
		return false
	}

	_, exists := extMime[strings.ToLower(filepath.Ext(info.Name()))]
	return exists
}

// minExt adds .min before a file's extension. If a file doesn't have an
// extension then .min will become the file's extension.
func minExt(path string) string {
	dot := strings.LastIndex(path, ".")

	if dot == -1 {
		return path + ".min"
	}

	return path[:dot] + ".min" + path[dot:]
}
<commit_msg>fix incorrect json and xml mime type; use string literals and regexp in AddFunc and AddFuncRegexp<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/css"
	"github.com/tdewolff/minify/html"
	"github.com/tdewolff/minify/js"
	"github.com/tdewolff/minify/json"
	"github.com/tdewolff/minify/svg"
	"github.com/tdewolff/minify/xml"
)

var (
	extMime = map[string]string{
		".css":  "text/css",
		".html": "text/html",
		".js":   "application/javascript",
		".json": "application/json",
		".svg":  "image/svg+xml",
		".xml":  "text/xml",
	}
)

func main() {
	input := ""
	output := ""
	ext := ""
	directory := ""
	recursive := false

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] [file]\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.StringVar(&output, "o", "", "Output file (stdout when empty)")
	flag.StringVar(&ext, "x", "", "File extension (css, html, js, json, svg or xml), optional for input files")
	flag.StringVar(&directory, "d", "", "Directory to search for files")
	flag.BoolVar(&recursive, "r", false, "Recursively minify everything")
	flag.Parse()
	if len(flag.Args()) > 0 {
		input = flag.Arg(0)
	}

	extPassed := (ext != "")

	mediatype := ""
	r := io.Reader(os.Stdin)
	w := io.Writer(os.Stdout)
	m := minify.New()
	m.AddFunc("text/css", css.Minify)
	m.AddFunc("text/html", html.Minify)
	m.AddFunc("application/javascript", js.Minify)
	m.AddFunc("image/svg+xml", svg.Minify)
	m.AddFuncRegexp(regexp.MustCompile("[/+]json$"), json.Minify)
	m.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), xml.Minify)

	filenames := make(map[string]string)
	if directory != "" {
		filenames = ioNames(directory, recursive)
	} else {
		filenames[input] = output
	}

	for in, out := range filenames {
		input = in
		output = out

		if input != "" {
			in, err := os.Open(input)
			if err != nil {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
			defer in.Close()
			r = in
			if input == output {
				b := &bytes.Buffer{}
				io.Copy(b, r)
				r = b
			}
			if !extPassed {
				ext = filepath.Ext(input)
			}
		}
		if output != "" {
			out, err := os.Create(output)
			if err != nil {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
			defer out.Close()
			w = out
		}
		if ext != "" {
			mediatype = extMime[ext]
		}

		if err := m.Minify(mediatype, w, r); err != nil {
			if err == minify.ErrNotExist {
				io.Copy(w, r)
			} else {
				fmt.Println("Error:", err)
				os.Exit(1)
			}
		}
	}
}

// ioNames returns a map of input paths and output paths.
func ioNames(startDir string, recursive bool) map[string]string {
	names := map[string]string{}

	if recursive {
		filepath.Walk(startDir, func(path string, info os.FileInfo, _ error) error {
			if !validFile(info) {
				return nil
			}

			names[path] = minExt(path)

			return nil
		})

		return names
	}

	infos, err := ioutil.ReadDir(startDir)
	if err != nil {
		return map[string]string{}
	}

	for _, info := range infos {
		if !validFile(info) {
			continue
		}

		fullPath := filepath.Join(startDir, info.Name())
		names[fullPath] = minExt(fullPath)
	}

	return names
}

// validFile checks to see if a file is a directory, hidden, already has the
// minified extension, or if it's one of the minifiable extensions.
func validFile(info os.FileInfo) bool {
	if info.IsDir() {
		return false
	}

	if info.Name()[0] == '.' {
		return false
	}

	// don't want to reminify already minified files
	if strings.Contains(info.Name(), ".min.") {
		return false
	}

	_, exists := extMime[strings.ToLower(filepath.Ext(info.Name()))]
	return exists
}

// minExt adds .min before a file's extension. If a file doesn't have an
// extension then .min will become the file's extension.
func minExt(path string) string {
	dot := strings.LastIndex(path, ".")

	if dot == -1 {
		return path + ".min"
	}

	return path[:dot] + ".min" + path[dot:]
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/pflag"

	apiv1 "k8s.io/api/core/v1"

	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
	"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
	"k8s.io/ingress-nginx/internal/ingress/controller"
	ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
	ing_net "k8s.io/ingress-nginx/internal/net"
)

func parseFlags() (bool, *controller.Configuration, error) {
	var (
		flags = pflag.NewFlagSet("", pflag.ExitOnError)

		apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
			"to connect to in the format of protocol://address:port, e.g., "+
			"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
			"Kubernetes cluster and local discovery is attempted.")
		kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")

		defaultSvc = flags.String("default-backend-service", "",
			`Service used to serve a 404 page for the default backend. Takes the form
		namespace/name. The controller uses the first node port of this Service for
		the default backend.`)

		ingressClass = flags.String("ingress-class", "",
			`Name of the ingress class to route through this controller.`)

		configMap = flags.String("configmap", "",
			`Name of the ConfigMap that contains the custom configuration to use`)

		publishSvc = flags.String("publish-service", "",
			`Service fronting the ingress controllers. Takes the form namespace/name.
		The controller will set the endpoint records on the ingress objects to reflect those on the service.`)

		tcpConfigMapName = flags.String("tcp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the TCP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.
		The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)

		udpConfigMapName = flags.String("udp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the UDP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.`)

		resyncPeriod = flags.Duration("sync-period", 600*time.Second,
			`Relist and confirm cloud resources this often. Default is 10 minutes`)

		watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
			`Namespace to watch for Ingress. Default is to watch all namespaces`)

		profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)

		defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
		that contains a SSL certificate to be used as default for a HTTPS catch-all server.
		Takes the form <namespace>/<secret name>.`)

		defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
		the URL to be used as health check inside in the default server in NGINX.`)

		updateStatus = flags.Bool("update-status", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname. Default is true`)

		electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)

		forceIsolation = flags.Bool("force-namespace-isolation", false,
			`Force namespace isolation. This flag is required to avoid the reference of secrets or
		configmaps located in a different namespace than the specified in the flag --watch-namespace.`)

		updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname when the controller
		is being stopped. Default is true`)

		sortBackends = flags.Bool("sort-backends", false,
			`Defines if backends and it's endpoints should be sorted`)

		useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
			`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)

		showVersion = flags.Bool("version", false,
			`Shows release information about the NGINX Ingress controller`)

		enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)

		httpPort      = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
		httpsPort     = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
		statusPort    = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
		sslProxyPort  = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
		defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
		healthzPort   = flags.Int("healthz-port", 10254, "port for healthz endpoint.")

		annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)

		enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
			`Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates.
		If the certificate contain issues chain issues is not possible to enable OCSP.
		Default is true.`)

		syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
			`Define the sync frequency upper limit`)

		publishStatusAddress = flags.String("publish-status-address", "",
			`User customized address to be set in the status of ingress resources. The controller will set the
		endpoint records on the ingress using this address.`)

		dynamicConfigurationEnabled = flags.Bool("enable-dynamic-configuration", false,
			`When enabled controller will try to avoid Nginx reloads as much as possible by using Lua. Disabled by default.`)
	)

	flag.Set("logtostderr", "true")

	flags.AddGoFlagSet(flag.CommandLine)
	flags.Parse(os.Args)

	// Workaround for this issue:
	// https://github.com/kubernetes/kubernetes/issues/17162
	flag.CommandLine.Parse([]string{})

	pflag.VisitAll(func(flag *pflag.Flag) {
		glog.V(2).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})

	if *showVersion {
		return true, nil, nil
	}

	if *defaultSvc == "" {
		return false, nil, fmt.Errorf("Please specify --default-backend-service")
	}

	if *ingressClass != "" {
		glog.Infof("Watching for ingress class: %s", *ingressClass)

		if *ingressClass != class.DefaultClass {
			glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
		}

		class.IngressClass = *ingressClass
	}

	parser.AnnotationsPrefix = *annotationsPrefix

	// check port collisions
	if !ing_net.IsPortAvailable(*httpPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
	}

	if !ing_net.IsPortAvailable(*httpsPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
	}

	if !ing_net.IsPortAvailable(*statusPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
	}

	if !ing_net.IsPortAvailable(*defServerPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
	}

	if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
	}

	if !*enableSSLChainCompletion {
		glog.Warningf("Check of SSL certificate chain is disabled (--enable-ssl-chain-completion=false)")
	}

	// LuaJIT is not available on arch s390x and ppc64le
	disableLua := false
	if runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64le" {
		disableLua = true
		if *dynamicConfigurationEnabled {
			*dynamicConfigurationEnabled = false
			glog.Warningf("Disabling dynamic configuration feature (LuaJIT is not available in s390x and ppc64le)")
		}
	}

	config := &controller.Configuration{
		APIServerHost:               *apiserverHost,
		KubeConfigFile:              *kubeConfigFile,
		UpdateStatus:                *updateStatus,
		ElectionID:                  *electionID,
		EnableProfiling:             *profiling,
		EnableSSLPassthrough:        *enableSSLPassthrough,
		EnableSSLChainCompletion:    *enableSSLChainCompletion,
		ResyncPeriod:                *resyncPeriod,
		DefaultService:              *defaultSvc,
		Namespace:                   *watchNamespace,
		ConfigMapName:               *configMap,
		TCPConfigMapName:            *tcpConfigMapName,
		UDPConfigMapName:            *udpConfigMapName,
		DefaultSSLCertificate:       *defSSLCertificate,
		DefaultHealthzURL:           *defHealthzURL,
		PublishService:              *publishSvc,
		PublishStatusAddress:        *publishStatusAddress,
		ForceNamespaceIsolation:     *forceIsolation,
		UpdateStatusOnShutdown:      *updateStatusOnShutdown,
		SortBackends:                *sortBackends,
		UseNodeInternalIP:           *useNodeInternalIP,
		SyncRateLimit:               *syncRateLimit,
		DynamicConfigurationEnabled: *dynamicConfigurationEnabled,
		DisableLua:                  disableLua,
		ListenPorts: &ngx_config.ListenPorts{
			Default:  *defServerPort,
			Health:   *healthzPort,
			HTTP:     *httpPort,
			HTTPS:    *httpsPort,
			SSLProxy: *sslProxyPort,
			Status:   *statusPort,
		},
	}

	return false, config, nil
}
<commit_msg>Correct some info in flags.go<commit_after>/*
Copyright 2017 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 main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/pflag"

	apiv1 "k8s.io/api/core/v1"

	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
	"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
	"k8s.io/ingress-nginx/internal/ingress/controller"
	ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
	ing_net "k8s.io/ingress-nginx/internal/net"
)

func parseFlags() (bool, *controller.Configuration, error) {
	var (
		flags = pflag.NewFlagSet("", pflag.ExitOnError)

		apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
			"to connect to in the format of protocol://address:port, e.g., "+
			"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
			"Kubernetes cluster and local discovery is attempted.")
		kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")

		defaultSvc = flags.String("default-backend-service", "",
			`Service used to serve a 404 page for the default backend. Takes the form
		namespace/name. The controller uses the first node port of this Service for
		the default backend.`)

		ingressClass = flags.String("ingress-class", "",
			`Name of the ingress class to route through this controller.`)

		configMap = flags.String("configmap", "",
			`Name of the ConfigMap that contains the custom configuration to use`)

		publishSvc = flags.String("publish-service", "",
			`Service fronting the ingress controllers. Takes the form namespace/name.
		The controller will set the endpoint records on the ingress objects to reflect those on the service.`)

		tcpConfigMapName = flags.String("tcp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the TCP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.
		The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)

		udpConfigMapName = flags.String("udp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the UDP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.`)

		resyncPeriod = flags.Duration("sync-period", 600*time.Second,
			`Relist and confirm cloud resources this often. Default is 10 minutes`)

		watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
			`Namespace to watch for Ingress. Default is to watch all namespaces`)

		profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)

		defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
		that contains a SSL certificate to be used as default for a HTTPS catch-all server.
		Takes the form <namespace>/<secret name>.`)

		defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
		the URL to be used as health check inside in the default server in NGINX.`)

		updateStatus = flags.Bool("update-status", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname. Default is true`)

		electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)

		forceIsolation = flags.Bool("force-namespace-isolation", false,
			`Force namespace isolation. This flag is required to avoid the reference of secrets or
		configmaps located in a different namespace than the specified in the flag --watch-namespace.`)

		updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname when the controller
		is being stopped. Default is true`)

		sortBackends = flags.Bool("sort-backends", false,
			`Defines if backends and its endpoints should be sorted`)

		useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
			`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)

		showVersion = flags.Bool("version", false,
			`Shows release information about the NGINX Ingress controller`)

		enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)

		httpPort      = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
		httpsPort     = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
		statusPort    = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
		sslProxyPort  = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
		defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
		healthzPort   = flags.Int("healthz-port", 10254, "port for healthz endpoint.")

		annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)

		enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
			`Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates.
		If the certificate contain issues chain issues is not possible to enable OCSP.
		Default is true.`)

		syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
			`Define the sync frequency upper limit`)

		publishStatusAddress = flags.String("publish-status-address", "",
			`User customized address to be set in the status of ingress resources. The controller will set the
		endpoint records on the ingress using this address.`)

		dynamicConfigurationEnabled = flags.Bool("enable-dynamic-configuration", false,
			`When enabled controller will try to avoid Nginx reloads as much as possible by using Lua. Disabled by default.`)
	)

	flag.Set("logtostderr", "true")

	flags.AddGoFlagSet(flag.CommandLine)
	flags.Parse(os.Args)

	// Workaround for this issue:
	// https://github.com/kubernetes/kubernetes/issues/17162
	flag.CommandLine.Parse([]string{})

	pflag.VisitAll(func(flag *pflag.Flag) {
		glog.V(2).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})

	if *showVersion {
		return true, nil, nil
	}

	if *defaultSvc == "" {
		return false, nil, fmt.Errorf("Please specify --default-backend-service")
	}

	if *ingressClass != "" {
		glog.Infof("Watching for ingress class: %s", *ingressClass)

		if *ingressClass != class.DefaultClass {
			glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
		}

		class.IngressClass = *ingressClass
	}

	parser.AnnotationsPrefix = *annotationsPrefix

	// check port collisions
	if !ing_net.IsPortAvailable(*httpPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
	}

	if !ing_net.IsPortAvailable(*httpsPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
	}

	if !ing_net.IsPortAvailable(*statusPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
	}

	if !ing_net.IsPortAvailable(*defServerPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
	}

	if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
	}

	if !*enableSSLChainCompletion {
		glog.Warningf("Check of SSL certificate chain is disabled (--enable-ssl-chain-completion=false)")
	}

	// LuaJIT is not available on arch s390x and ppc64le
	disableLua := false
	if runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64le" {
		disableLua = true
		if *dynamicConfigurationEnabled {
			*dynamicConfigurationEnabled = false
			glog.Warningf("Disabling dynamic configuration feature (LuaJIT is not available in s390x and ppc64le)")
		}
	}

	config := &controller.Configuration{
		APIServerHost:               *apiserverHost,
		KubeConfigFile:              *kubeConfigFile,
		UpdateStatus:                *updateStatus,
		ElectionID:                  *electionID,
		EnableProfiling:             *profiling,
		EnableSSLPassthrough:        *enableSSLPassthrough,
		EnableSSLChainCompletion:    *enableSSLChainCompletion,
		ResyncPeriod:                *resyncPeriod,
		DefaultService:              *defaultSvc,
		Namespace:                   *watchNamespace,
		ConfigMapName:               *configMap,
		TCPConfigMapName:            *tcpConfigMapName,
		UDPConfigMapName:            *udpConfigMapName,
		DefaultSSLCertificate:       *defSSLCertificate,
		DefaultHealthzURL:           *defHealthzURL,
		PublishService:              *publishSvc,
		PublishStatusAddress:        *publishStatusAddress,
		ForceNamespaceIsolation:     *forceIsolation,
		UpdateStatusOnShutdown:      *updateStatusOnShutdown,
		SortBackends:                *sortBackends,
		UseNodeInternalIP:           *useNodeInternalIP,
		SyncRateLimit:               *syncRateLimit,
		DynamicConfigurationEnabled: *dynamicConfigurationEnabled,
		DisableLua:                  disableLua,
		ListenPorts: &ngx_config.ListenPorts{
			Default:  *defServerPort,
			Health:   *healthzPort,
			HTTP:     *httpPort,
			HTTPS:    *httpsPort,
			SSLProxy: *sslProxyPort,
			Status:   *statusPort,
		},
	}

	return false, config, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/fogleman/fauxgl"
	embree "github.com/fogleman/go-embree"
)

func timed(name string) func() {
	fmt.Printf("%s... ", name)
	start := time.Now()
	return func() {
		fmt.Println(time.Since(start))
	}
}

func fauxglToEmbree(mesh *fauxgl.Mesh) *embree.Mesh {
	triangles := make([]embree.Triangle, len(mesh.Triangles))
	for i, t := range mesh.Triangles {
		triangles[i] = embree.Triangle{
			embree.Vector{t.V1.Position.X, t.V1.Position.Y, t.V1.Position.Z},
			embree.Vector{t.V2.Position.X, t.V2.Position.Y, t.V2.Position.Z},
			embree.Vector{t.V3.Position.X, t.V3.Position.Y, t.V3.Position.Z},
		}
	}
	return embree.NewMesh(triangles)
}

func main() {
	var done func()

	done = timed("creating sphere")
	sphere := fauxgl.NewSphere2(6)
	hitSphere := fauxgl.NewSphere2(3)
	embreeSphere := fauxglToEmbree(hitSphere)
	spherePoints := make(map[fauxgl.Vector]bool)
	for _, t := range sphere.Triangles {
		spherePoints[t.V1.Position] = true
		spherePoints[t.V2.Position] = true
		spherePoints[t.V3.Position] = true
	}
	done()

	done = timed("loading mesh")
	mesh, err := fauxgl.LoadMesh(os.Args[1])
	if err != nil {
		panic(err)
	}
	done()

	done = timed("first pass")
	lookup1 := make(map[fauxgl.Vector]float64)
	for _, t := range mesh.Triangles {
		n := t.Normal()
		a := t.Area()
		if math.IsNaN(n.Length()) {
			continue
		}
		ray := embree.Ray{embree.Vector{}, embree.Vector{n.X, n.Y, n.Z}}
		hit := embreeSphere.Intersect(ray)
		p := n.MulScalar(hit.T)
		st := hitSphere.Triangles[hit.Index]
		p1 := st.V1.Position
		p2 := st.V2.Position
		p3 := st.V3.Position
		b := fauxgl.Barycentric(p1, p2, p3, p)
		lookup1[p1] += a * b.X
		lookup1[p2] += a * b.Y
		lookup1[p3] += a * b.Z
	}
	done()

	done = timed("second pass")
	lookup2 := make(map[fauxgl.Vector]float64)
	for p1, a := range lookup1 {
		for p2 := range spherePoints {
			p := p1.X*p2.X + p1.Y*p2.Y + p1.Z*p2.Z
			if p < 0.5 {
				continue
			}
			if p >= 1 {
				p = 1
			} else {
				p = math.Pow(p, 32)
			}
			lookup2[p2] += a * p
		}
	}
	done()

	done = timed("creating oriented.stl")
	var bestVector fauxgl.Vector
	bestScore := math.Inf(1)
	for k, v := range lookup2 {
		if v < bestScore {
			bestScore = v
			bestVector = k
		}
	}
	mesh.Transform(fauxgl.RotateTo(bestVector, fauxgl.Vector{0, 0, 1}))
	mesh.SaveSTL("oriented.stl")
	done()

	done = timed("creating normals.stl")
	for _, t := range sphere.Triangles {
		t.V1.Position = t.V1.Position.MulScalar(lookup2[t.V1.Position])
		t.V2.Position = t.V2.Position.MulScalar(lookup2[t.V2.Position])
		t.V3.Position = t.V3.Position.MulScalar(lookup2[t.V3.Position])
	}
	sphere.SaveSTL("normals.stl")
	done()
}
<commit_msg>use new api<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/fogleman/fauxgl"
	embree "github.com/fogleman/go-embree"
)

func timed(name string) func() {
	fmt.Printf("%s... ", name)
	start := time.Now()
	return func() {
		fmt.Println(time.Since(start))
	}
}

func fauxglToEmbree(mesh *fauxgl.Mesh) *embree.Mesh {
	triangles := make([]embree.Triangle, len(mesh.Triangles))
	for i, t := range mesh.Triangles {
		triangles[i] = embree.Triangle{
			embree.Vector{t.V1.Position.X, t.V1.Position.Y, t.V1.Position.Z},
			embree.Vector{t.V2.Position.X, t.V2.Position.Y, t.V2.Position.Z},
			embree.Vector{t.V3.Position.X, t.V3.Position.Y, t.V3.Position.Z},
		}
	}
	return embree.NewMesh(triangles)
}

func main() {
	var done func()

	done = timed("creating sphere")
	sphere := fauxgl.NewSphere(6)
	hitSphere := fauxgl.NewSphere(3)
	embreeSphere := fauxglToEmbree(hitSphere)
	spherePoints := make(map[fauxgl.Vector]bool)
	for _, t := range sphere.Triangles {
		spherePoints[t.V1.Position] = true
		spherePoints[t.V2.Position] = true
		spherePoints[t.V3.Position] = true
	}
	done()

	done = timed("loading mesh")
	mesh, err := fauxgl.LoadMesh(os.Args[1])
	if err != nil {
		panic(err)
	}
	done()

	done = timed("first pass")
	lookup1 := make(map[fauxgl.Vector]float64)
	for _, t := range mesh.Triangles {
		n := t.Normal()
		a := t.Area()
		if math.IsNaN(n.Length()) {
			continue
		}
		ray := embree.Ray{embree.Vector{}, embree.Vector{n.X, n.Y, n.Z}}
		hit := embreeSphere.Intersect(ray)
		p := n.MulScalar(hit.T)
		st := hitSphere.Triangles[hit.Index]
		p1 := st.V1.Position
		p2 := st.V2.Position
		p3 := st.V3.Position
		b := fauxgl.Barycentric(p1, p2, p3, p)
		lookup1[p1] += a * b.X
		lookup1[p2] += a * b.Y
		lookup1[p3] += a * b.Z
	}
	done()

	done = timed("second pass")
	lookup2 := make(map[fauxgl.Vector]float64)
	for p1, a := range lookup1 {
		for p2 := range spherePoints {
			p := p1.X*p2.X + p1.Y*p2.Y + p1.Z*p2.Z
			if p < 0.5 {
				continue
			}
			if p >= 1 {
				p = 1
			} else {
				p = math.Pow(p, 32)
			}
			lookup2[p2] += a * p
		}
	}
	done()

	done = timed("creating oriented.stl")
	var bestVector fauxgl.Vector
	bestScore := math.Inf(1)
	for k, v := range lookup2 {
		if v < bestScore {
			bestScore = v
			bestVector = k
		}
	}
	mesh.Transform(fauxgl.RotateTo(bestVector, fauxgl.Vector{0, 0, 1}))
	mesh.SaveSTL("oriented.stl")
	done()

	done = timed("creating normals.stl")
	for _, t := range sphere.Triangles {
		t.V1.Position = t.V1.Position.MulScalar(lookup2[t.V1.Position])
		t.V2.Position = t.V2.Position.MulScalar(lookup2[t.V2.Position])
		t.V3.Position = t.V3.Position.MulScalar(lookup2[t.V3.Position])
	}
	sphere.SaveSTL("normals.stl")
	done()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"time"

	"github.com/opencontainers/runtime-spec/specs-go"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/baggageclaim"
	"github.com/concourse/baggageclaim/client"
	"github.com/jessevdk/go-flags"
)

type PluginCommand struct {
	CreateCommand    CreateCommand    `command:"create"`
	DeleteCommand    DeleteCommand    `command:"delete"`
	ListCommand      ListCommand      `command:"list"`
	InitStoreCommand InitStoreCommand `command:"init-store"`

	BaggageclaimUrl string `long:"baggageclaimURL" required:"true" description:"Address to Baggageclaim Server"`
}

type CreateCommand struct {
	Path   string `required:"true" positional-args:"yes" description:"Path to rootfs"`
	Handle string `required:"true" positional-args:"yes" description:"Handle to Create"`
}

type DeleteCommand struct {
	Handle string `required:"true" positional-args:"yes" description:"Handle to Delete"`
}

type InitStoreCommand struct {
	StoreSizeBytes string `long:"store-size-bytes" required:"true" description:"Address to Baggageclaim Server"`
}

type ListCommand struct {
}

func (cc *CreateCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)

	rootfsURL, err := url.Parse(args[0])
	if err != nil {
		return err
	}

	dir, _ := path.Split(rootfsURL.Path)
	handle := path.Base(dir)
	logger.Debug("create-volume", lager.Data{"path": rootfsURL.Path, "handle": handle})
	vol, err := client.CreateVolume(
		logger,
		cc.Handle,
		baggageclaim.VolumeSpec{
			Strategy: baggageclaim.COWStrategy{
				Parent: NewPluginVolume(rootfsURL.Path, handle),
			},
			Privileged: false, ///TODO: Set this to a sane value
		},
	)
	if err != nil {
		logger.Error("could not create COW volume", err, lager.Data{"args": args})
		return err
	}

	runtimeSpec := &specs.Spec{
		Root: &specs.Root{
			Path:     vol.Path(),
			Readonly: false,
		},
	}

	logger.Debug("created-cow-volume", lager.Data{"path": vol.Path()})

	b, _ := json.Marshal(runtimeSpec)
	fmt.Println(string(b))
	return nil
}

func (dc *DeleteCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)

	err := client.DestroyVolume(logger, dc.Handle)
	if err != nil {
		return err
	}
	return nil
}

func (lc *InitStoreCommand) Execute(args []string) error {
	return nil
}

func (lc *ListCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)
	volumes, err := client.ListVolumes(logger, nil)
	if err != nil {
		return err
	}

	logger.Debug("list-volumes", lager.Data{"volumes": volumes})
	return nil
}

var defaultRoundTripper http.RoundTripper = &http.Transport{
	Proxy: http.ProxyFromEnvironment,
	DialContext: (&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}).DialContext,
	TLSHandshakeTimeout: 10 * time.Second,
}

var Plugin PluginCommand
var logger lager.Logger

func main() {
	logger = lager.NewLogger("baggageclaim_plugin")
	sink := lager.NewWriterSink(os.Stderr, lager.DEBUG)
	logger.RegisterSink(sink)

	parser := flags.NewParser(&Plugin, flags.HelpFlag|flags.PrintErrors|flags.IgnoreUnknown)
	parser.NamespaceDelimiter = "-"

	_, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}
}
<commit_msg>rename vol to volume in plugin<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"time"

	"github.com/opencontainers/runtime-spec/specs-go"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/baggageclaim"
	"github.com/concourse/baggageclaim/client"
	"github.com/jessevdk/go-flags"
)

type PluginCommand struct {
	CreateCommand    CreateCommand    `command:"create"`
	DeleteCommand    DeleteCommand    `command:"delete"`
	ListCommand      ListCommand      `command:"list"`
	InitStoreCommand InitStoreCommand `command:"init-store"`

	BaggageclaimUrl string `long:"baggageclaimURL" required:"true" description:"Address to Baggageclaim Server"`
}

type CreateCommand struct {
	Path   string `required:"true" positional-args:"yes" description:"Path to rootfs"`
	Handle string `required:"true" positional-args:"yes" description:"Handle to Create"`
}

type DeleteCommand struct {
	Handle string `required:"true" positional-args:"yes" description:"Handle to Delete"`
}

type InitStoreCommand struct {
	StoreSizeBytes string `long:"store-size-bytes" required:"true" description:"Address to Baggageclaim Server"`
}

type ListCommand struct {
}

func (cc *CreateCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)

	rootfsURL, err := url.Parse(args[0])
	if err != nil {
		return err
	}

	dir, _ := path.Split(rootfsURL.Path)
	handle := path.Base(dir)

	logger.Debug("create-volume", lager.Data{"path": rootfsURL.Path, "handle": handle})

	volume, err := client.CreateVolume(
		logger,
		cc.Handle,
		baggageclaim.VolumeSpec{
			Strategy: baggageclaim.COWStrategy{
				Parent: NewPluginVolume(rootfsURL.Path, handle),
			},
			Privileged: true, ///TODO: Set this to a sane value
		},
	)
	if err != nil {
		logger.Error("could not create COW volume", err, lager.Data{"args": args})
		return err
	}

	runtimeSpec := &specs.Spec{
		Root: &specs.Root{
			Path:     volume.Path(),
			Readonly: false,
		},
	}

	logger.Debug("created-cow-volume", lager.Data{"path": volume.Path()})

	b, _ := json.Marshal(runtimeSpec)
	fmt.Println(string(b))
	return nil
}

func (dc *DeleteCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)

	err := client.DestroyVolume(logger, dc.Handle)
	if err != nil {
		return err
	}
	return nil
}

func (lc *InitStoreCommand) Execute(args []string) error {
	return nil
}

func (lc *ListCommand) Execute(args []string) error {
	client := client.New(Plugin.BaggageclaimUrl, defaultRoundTripper)
	volumes, err := client.ListVolumes(logger, nil)
	if err != nil {
		return err
	}

	logger.Debug("list-volumes", lager.Data{"volumes": volumes})
	return nil
}

var defaultRoundTripper http.RoundTripper = &http.Transport{
	Proxy: http.ProxyFromEnvironment,
	DialContext: (&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}).DialContext,
	TLSHandshakeTimeout: 10 * time.Second,
}

var Plugin PluginCommand
var logger lager.Logger

func main() {
	logger = lager.NewLogger("baggageclaim_plugin")
	sink := lager.NewWriterSink(os.Stderr, lager.DEBUG)
	logger.RegisterSink(sink)

	parser := flags.NewParser(&Plugin, flags.HelpFlag|flags.PrintErrors|flags.IgnoreUnknown)
	parser.NamespaceDelimiter = "-"

	_, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"math"
	"sync"
	"time"

	"github.com/gnamma/server"
)

var (
	addr       = flag.String("address", "localhost:3000", "The address for the server you want to connect to")
	assetsAddr = flag.String("assets-address", "localhost:3001", "The address for the specific address server you want to listen on")
	username   = flag.String("username", "reverb", "The username this bot will take")

	client *server.Client
)

func main() {
	flag.Parse()

	client = &server.Client{
		Addr:       *addr,
		AssetsAddr: *assetsAddr,
		Username:   *username,
	}

	err := client.Connect()
	if err != nil {
		log.Fatal("Couldn't connect to server:", err)
		return
	}

	log.Println(*client)

	var nodes = []*server.Node{
		{
			Type:     server.HeadNode,
			Label:    "Your head, bro!",
			Asset:    "box",
			Position: server.Point{0, 2, 0},
		},
		{
			Type:     server.ArmNode,
			Label:    "This is your arm, sis!",
			Asset:    "box",
			Rotation: server.Point{-1, 1, 0},
		},
		{
			Type:     server.ArmNode,
			Label:    "This is your arm, you!",
			Asset:    "box",
			Rotation: server.Point{1, 1, 0},
		},
	}

	var wg sync.WaitGroup

	for _, n := range nodes {
		wg.Add(1)

		go func(n *server.Node) {
			defer wg.Done()

			err := client.RegisterNode(n)
			if err != nil {
				log.Println("Unable to register node: ", err)
				return
			}
		}(n)
	}

	wg.Wait()

	move(nodes)
}

func move(nodes []*server.Node) {
	speed := float64(math.Pi / 180) // Want to move 1 radian each iteration
	x := float64(0)

	wait := time.Second / time.Duration(10)

	for {
		var wg sync.WaitGroup

		for _, n := range nodes {
			wg.Add(1)

			go func(n *server.Node) {
				defer wg.Done()
				n.Rotation.Z = math.Sin(x)

				log.Println("at:", n.Rotation.Z)

				err := client.UpdateNode(*n)
				if err != nil {
					log.Fatal("Couldn't update node:", err)
					return
				}
			}(n)
		}

		x += speed
		wg.Wait()

		time.Sleep(wait)
	}

}
<commit_msg>Fix move position instead of rotate<commit_after>package main

import (
	"flag"
	"log"
	"math"
	"sync"
	"time"

	"github.com/gnamma/server"
)

var (
	addr       = flag.String("address", "localhost:3000", "The address for the server you want to connect to")
	assetsAddr = flag.String("assets-address", "localhost:3001", "The address for the specific address server you want to listen on")
	username   = flag.String("username", "reverb", "The username this bot will take")

	client *server.Client
)

func main() {
	flag.Parse()

	client = &server.Client{
		Addr:       *addr,
		AssetsAddr: *assetsAddr,
		Username:   *username,
	}

	err := client.Connect()
	if err != nil {
		log.Fatal("Couldn't connect to server:", err)
		return
	}

	log.Println(*client)

	var nodes = []*server.Node{
		{
			Type:     server.HeadNode,
			Label:    "Your head, bro!",
			Asset:    "box",
			Position: server.Point{0, 2, 0},
		},
		{
			Type:     server.ArmNode,
			Label:    "This is your arm, sis!",
			Asset:    "box",
			Position: server.Point{-1, 1, 0},
		},
		{
			Type:     server.ArmNode,
			Label:    "This is your arm, you!",
			Asset:    "box",
			Position: server.Point{1, 1, 0},
		},
	}

	var wg sync.WaitGroup

	for _, n := range nodes {
		wg.Add(1)

		go func(n *server.Node) {
			defer wg.Done()

			err := client.RegisterNode(n)
			if err != nil {
				log.Println("Unable to register node: ", err)
				return
			}
		}(n)
	}

	wg.Wait()

	move(nodes)
}

func move(nodes []*server.Node) {
	speed := float64(math.Pi/180) * 5 // Want to move 1 radian each iteration
	x := float64(0)

	wait := time.Second / time.Duration(10)

	for {
		var wg sync.WaitGroup

		for _, n := range nodes {
			wg.Add(1)

			go func(n *server.Node) {
				defer wg.Done()
				n.Position.Z = math.Sin(x)

				log.Println("at:", n.Position.Z)

				err := client.UpdateNode(*n)
				if err != nil {
					log.Fatal("Couldn't update node:", err)
					return
				}
			}(n)
		}

		x += speed
		wg.Wait()

		time.Sleep(wait)
	}

}
<|endoftext|>


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

package main

import (
	"log"
	"os"

	"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
	"github.com/google/gops/agent"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/api"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
	"github.com/tsuru/tsuru/provision"
	_ "github.com/tsuru/tsuru/provision/docker"
	_ "github.com/tsuru/tsuru/provision/kubernetes"
	_ "github.com/tsuru/tsuru/provision/mesos"
	_ "github.com/tsuru/tsuru/provision/swarm"
	_ "github.com/tsuru/tsuru/repository/gandalf"
)

const defaultConfigPath = "/etc/tsuru/tsuru.conf"

var configPath = defaultConfigPath

func buildManager() *cmd.Manager {
	m := cmd.NewManager("tsurud", api.Version, "", os.Stdout, os.Stderr, os.Stdin, nil)
	m.Register(&tsurudCommand{Command: &apiCmd{}})
	m.Register(&tsurudCommand{Command: tokenCmd{}})
	m.Register(&tsurudCommand{Command: &migrateCmd{}})
	m.Register(&tsurudCommand{Command: gandalfSyncCmd{}})
	m.Register(&tsurudCommand{Command: createRootUserCmd{}})
	m.Register(&migrationListCmd{})
	err := registerProvisionersCommands(m)
	if err != nil {
		log.Fatalf("unable to register commands: %v", err)
	}
	return m
}

func registerProvisionersCommands(m *cmd.Manager) error {
	provisioners, err := provision.Registry()
	if err != nil {
		return err
	}
	for _, p := range provisioners {
		if c, ok := p.(cmd.Commandable); ok {
			commands := c.Commands()
			for _, cmd := range commands {
				m.Register(&tsurudCommand{Command: cmd})
			}
		}
	}
	return nil
}

func inDockerMachineDriverMode() bool {
	return os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal
}

func main() {
	if err := agent.Start(); err != nil {
		log.Fatalf("Unable to start a Gops agent %s", err)
	}
	if inDockerMachineDriverMode() {
		err := dockermachine.RunDriver(os.Getenv(localbinary.PluginEnvDriverName))
		if err != nil {
			log.Fatalf("Error running driver: %s", err)
		}
	} else {
		localbinary.CurrentBinaryIsDockerMachine = true
		config.ReadConfigFile(configPath)
		listenSignals()
		m := buildManager()
		m.Run(os.Args[1:])
	}
}
<commit_msg>cmd/tsurud: start gops agent without signal handling<commit_after>// Copyright 2016 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.

package main

import (
	"log"
	"os"

	"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
	"github.com/google/gops/agent"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/api"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
	"github.com/tsuru/tsuru/provision"
	_ "github.com/tsuru/tsuru/provision/docker"
	_ "github.com/tsuru/tsuru/provision/kubernetes"
	_ "github.com/tsuru/tsuru/provision/mesos"
	_ "github.com/tsuru/tsuru/provision/swarm"
	_ "github.com/tsuru/tsuru/repository/gandalf"
)

const defaultConfigPath = "/etc/tsuru/tsuru.conf"

var configPath = defaultConfigPath

func buildManager() *cmd.Manager {
	m := cmd.NewManager("tsurud", api.Version, "", os.Stdout, os.Stderr, os.Stdin, nil)
	m.Register(&tsurudCommand{Command: &apiCmd{}})
	m.Register(&tsurudCommand{Command: tokenCmd{}})
	m.Register(&tsurudCommand{Command: &migrateCmd{}})
	m.Register(&tsurudCommand{Command: gandalfSyncCmd{}})
	m.Register(&tsurudCommand{Command: createRootUserCmd{}})
	m.Register(&migrationListCmd{})
	err := registerProvisionersCommands(m)
	if err != nil {
		log.Fatalf("unable to register commands: %v", err)
	}
	return m
}

func registerProvisionersCommands(m *cmd.Manager) error {
	provisioners, err := provision.Registry()
	if err != nil {
		return err
	}
	for _, p := range provisioners {
		if c, ok := p.(cmd.Commandable); ok {
			commands := c.Commands()
			for _, cmd := range commands {
				m.Register(&tsurudCommand{Command: cmd})
			}
		}
	}
	return nil
}

func inDockerMachineDriverMode() bool {
	return os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal
}

func main() {
	gopsAgent := agent.Agent{
		HandleSignals: false,
	}
	if err := gopsAgent.Start(); err != nil {
		log.Fatalf("Unable to start a Gops agent %s", err)
	}
	defer gopsAgent.Stop()
	if inDockerMachineDriverMode() {
		err := dockermachine.RunDriver(os.Getenv(localbinary.PluginEnvDriverName))
		if err != nil {
			log.Fatalf("Error running driver: %s", err)
		}
	} else {
		localbinary.CurrentBinaryIsDockerMachine = true
		config.ReadConfigFile(configPath)
		listenSignals()
		m := buildManager()
		m.Run(os.Args[1:])
	}
}
<|endoftext|>