<commit_before>// Copyright (c) 2012-2019 Eli Janssen
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// go-camo daemon (go-camod)
package main

import (
	"bufio"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/cactus/go-camo/pkg/camo"
	"github.com/cactus/go-camo/pkg/htrie"
	"github.com/cactus/go-camo/pkg/router"

	"github.com/cactus/mlog"
	flags "github.com/jessevdk/go-flags"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/prometheus/common/version"
)

const metricNamespace = "camo"

var (
	// ServerVersion holds the server version string
	ServerVersion = "no-version"

	responseSize = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricNamespace,
			Name:      "response_size_bytes",
			Help:      "A histogram of sizes for proxy responses.",
			Buckets:   prometheus.ExponentialBuckets(1024, 2, 10),
		},
		[]string{},
	)
	responseDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricNamespace,
			Name:      "response_duration_seconds",
			Help:      "A histogram of latencies for proxy responses.",
			Buckets:   prometheus.DefBuckets,
		},
		[]string{},
	)
	responseCount = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "responses_total",
			Help:      "Total HTTP requests processed by the go-camo, excluding scrapes.",
		},
		[]string{"code", "method"},
	)
)

func loadFilterList(fname string) ([]camo.FilterFunc, error) {
	// #nosec
	file, err := os.Open(fname)
	if err != nil {
		return nil, fmt.Errorf("could not open filter-ruleset file: %s", err)
	}
	defer file.Close()

	allowFilter := htrie.NewURLMatcher()
	denyFilter := htrie.NewURLMatcher()
	hasAllow := false
	hasDeny := false

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()

		if strings.HasPrefix(line, "allow|") {
			line = strings.TrimPrefix(line, "allow")
			err = allowFilter.AddRule(line)
			if err != nil {
				break
			}
			hasAllow = true
		} else if strings.HasPrefix(line, "deny|") {
			line = strings.TrimPrefix(line, "deny")
			err = denyFilter.AddRule(line)
			if err != nil {
				break
			}
			hasDeny = true
		} else {
			fmt.Println("ignoring line: ", line)
		}

		err = scanner.Err()
		if err != nil {
			break
		}
	}
	if err != nil {
		return nil, fmt.Errorf("error building filter ruleset: %s", err)
	}

	// append in order. allow first, then deny filters.
	// first false value aborts the request.
	filterFuncs := make([]camo.FilterFunc, 0)

	if hasAllow {
		filterFuncs = append(filterFuncs, allowFilter.CheckURL)
	}

	// denyFilter returns true on a match. we want a "false" value to abort processing.
	// so just wrap and invert the bool.
	if hasDeny {
		denyF := func(u *url.URL) bool {
			return !denyFilter.CheckURL(u)
		}
		filterFuncs = append(filterFuncs, denyF)
	}

	if hasAllow && hasDeny {
		mlog.Printf("Warning! Allow and Deny rules both supplied. Having Allow rules means anything not matching an allow rule is denied. THEN deny rules are evaluated. Be sure this is what you want!")
	}

	return filterFuncs, nil
}

func main() {
	// command line flags
	var opts struct {
		HMACKey             string        `short:"k" long:"key" description:"HMAC key"`
		AddHeaders          []string      `short:"H" long:"header" description:"Add additional header to each response. This option can be used multiple times to add multiple headers"`
		BindAddress         string        `long:"listen" default:"0.0.0.0:8080" description:"Address:Port to bind to for HTTP"`
		BindAddressSSL      string        `long:"ssl-listen" description:"Address:Port to bind to for HTTPS/SSL/TLS"`
		SSLKey              string        `long:"ssl-key" description:"ssl private key (key.pem) path"`
		SSLCert             string        `long:"ssl-cert" description:"ssl cert (cert.pem) path"`
		MaxSize             int64         `long:"max-size" description:"Max allowed response size (KB)"`
		ReqTimeout          time.Duration `long:"timeout" default:"4s" description:"Upstream request timeout"`
		MaxRedirects        int           `long:"max-redirects" default:"3" description:"Maximum number of redirects to follow"`
		Metrics             bool          `long:"metrics" description:"Enable Prometheus compatible metrics endpoint"`
		NoLogTS             bool          `long:"no-log-ts" description:"Do not add a timestamp to logging"`
		DisableKeepAlivesFE bool          `long:"no-fk" description:"Disable frontend http keep-alive support"`
		DisableKeepAlivesBE bool          `long:"no-bk" description:"Disable backend http keep-alive support"`
		AllowContentVideo   bool          `long:"allow-content-video" description:"Additionally allow 'video/*' content"`
		AllowContentAudio   bool          `long:"allow-content-audio" description:"Additionally allow 'audio/*' content"`
		AllowCredetialURLs  bool          `long:"allow-credential-urls" description:"Allow urls to contain user/pass credentials"`
		FilterRuleset       string        `long:"filter-ruleset" description:"Text file containing filtering rules (one per line)"`
		ServerName          string        `long:"server-name" default:"go-camo" description:"Value to use for the HTTP server field"`
		ExposeServerVersion bool          `long:"expose-server-version" description:"Include the server version in the HTTP server response header"`
		EnableXFwdFor       bool          `long:"enable-xfwd4" description:"Enable x-forwarded-for passthrough/generation"`
		Verbose             bool          `short:"v" long:"verbose" description:"Show verbose (debug) log level output"`
		Version             []bool        `short:"V" long:"version" description:"Print version and exit; specify twice to show license information"`
	}

	// parse said flags
	_, err := flags.Parse(&opts)
	if err != nil {
		if e, ok := err.(*flags.Error); ok {
			if e.Type == flags.ErrHelp {
				os.Exit(0)
			}
		}
		os.Exit(1)
	}

	// set the server name
	ServerName := opts.ServerName

	// setup the server response field
	ServerResponse := opts.ServerName

	// expand/override server response value if showing version is desired
	if opts.ExposeServerVersion {
		ServerResponse = fmt.Sprintf("%s %s", ServerName, ServerVersion)
	}

	// setup -V version output
	if len(opts.Version) > 0 {
		fmt.Printf("%s %s (%s,%s-%s)\n", "go-camo", ServerVersion, runtime.Version(), runtime.Compiler, runtime.GOARCH)
		if len(opts.Version) > 1 {
			fmt.Printf("\n%s\n", strings.TrimSpace(licenseText))
		}
		os.Exit(0)
	}

	// start out with a very bare logger that only prints
	// the message (no special format or log elements)
	mlog.SetFlags(0)

	config := camo.Config{}
	if hmacKey := os.Getenv("GOCAMO_HMAC"); hmacKey != "" {
		config.HMACKey = []byte(hmacKey)
	}

	// flags override env var
	if opts.HMACKey != "" {
		config.HMACKey = []byte(opts.HMACKey)
	}

	if len(config.HMACKey) == 0 {
		mlog.Fatal("HMAC key required")
	}

	if opts.BindAddress == "" && opts.BindAddressSSL == "" {
		mlog.Fatal("One of listen or ssl-listen required")
	}

	if opts.BindAddressSSL != "" && opts.SSLKey == "" {
		mlog.Fatal("ssl-key is required when specifying ssl-listen")
	}
	if opts.BindAddressSSL != "" && opts.SSLCert == "" {
		mlog.Fatal("ssl-cert is required when specifying ssl-listen")
	}

	// set keepalive options
	config.DisableKeepAlivesBE = opts.DisableKeepAlivesBE
	config.DisableKeepAlivesFE = opts.DisableKeepAlivesFE

	// other options
	config.EnableXFwdFor = opts.EnableXFwdFor
	config.AllowCredetialURLs = opts.AllowCredetialURLs

	// additional content types to allow
	config.AllowContentVideo = opts.AllowContentVideo
	config.AllowContentAudio = opts.AllowContentAudio

	var filters []camo.FilterFunc
	if opts.FilterRuleset != "" {
		filters, err = loadFilterList(opts.FilterRuleset)
		if err != nil {
			mlog.Fatal("Could not read filter-ruleset", err)
		}

	}

	AddHeaders := map[string]string{
		"X-Content-Type-Options":  "nosniff",
		"X-XSS-Protection":        "1; mode=block",
		"Content-Security-Policy": "default-src 'none'; img-src data:; style-src 'unsafe-inline'",
	}

	for _, v := range opts.AddHeaders {
		s := strings.SplitN(v, ":", 2)
		if len(s) != 2 {
			mlog.Printf("ignoring bad header: '%s'", v)
			continue
		}

		s0 := strings.TrimSpace(s[0])
		s1 := strings.TrimSpace(s[1])

		if len(s0) == 0 || len(s1) == 0 {
			mlog.Printf("ignoring bad header: '%s'", v)
			continue
		}
		AddHeaders[s[0]] = s[1]
	}

	// now configure a standard logger
	mlog.SetFlags(mlog.Lstd)
	if opts.NoLogTS {
		mlog.SetFlags(mlog.Flags() ^ mlog.Ltimestamp)
	}

	if opts.Verbose {
		mlog.SetFlags(mlog.Flags() | mlog.Ldebug)
		mlog.Debug("debug logging enabled")
	}

	// convert from KB to Bytes
	config.MaxSize = opts.MaxSize * 1024
	config.RequestTimeout = opts.ReqTimeout
	config.MaxRedirects = opts.MaxRedirects
	config.ServerName = ServerName

	// configure metrics collection in camo
	if opts.Metrics {
		config.CollectMetrics = true
	}

	proxy, err := camo.NewWithFilters(config, filters)
	if err != nil {
		mlog.Fatal("Error creating camo", err)
	}

	var router http.Handler = &router.DumbRouter{
		ServerName:  ServerResponse,
		AddHeaders:  AddHeaders,
		CamoHandler: proxy,
	}

	// configure router endpoint for rendering metrics
	if opts.Metrics {
		mlog.Printf("Enabling metrics at /metrics")
		http.Handle("/metrics", promhttp.Handler())
		// Register a version info metric.
		verOverride := os.Getenv("APP_INFO_VERSION")
		if verOverride != "" {
			version.Version = verOverride
		} else {
			version.Version = ServerVersion
		}
		version.Revision = os.Getenv("APP_INFO_REVISION")
		version.Branch = os.Getenv("APP_INFO_BRANCH")
		version.BuildDate = os.Getenv("APP_INFO_BUILD_DATE")
		prometheus.MustRegister(version.NewCollector(metricNamespace))
		// Wrap the dumb router in instrumentation.
		router = promhttp.InstrumentHandlerDuration(responseDuration, router)
		router = promhttp.InstrumentHandlerCounter(responseCount, router)
		router = promhttp.InstrumentHandlerResponseSize(responseSize, router)
	}

	http.Handle("/", router)

	if opts.BindAddress != "" {
		mlog.Printf("Starting server on: %s", opts.BindAddress)
		go func() {
			srv := &http.Server{
				Addr:        opts.BindAddress,
				ReadTimeout: 30 * time.Second}
			mlog.Fatal(srv.ListenAndServe())
		}()
	}
	if opts.BindAddressSSL != "" {
		mlog.Printf("Starting TLS server on: %s", opts.BindAddressSSL)
		go func() {
			srv := &http.Server{
				Addr:        opts.BindAddressSSL,
				ReadTimeout: 30 * time.Second}
			mlog.Fatal(srv.ListenAndServeTLS(opts.SSLCert, opts.SSLKey))
		}()
	}

	// just block. listen and serve will exit the program if they fail/return
	// so we just need to block to prevent main from exiting.
	select {}
}
<commit_msg>quiet gosec on this line<commit_after>// Copyright (c) 2012-2019 Eli Janssen
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// go-camo daemon (go-camod)
package main

import (
	"bufio"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/cactus/go-camo/pkg/camo"
	"github.com/cactus/go-camo/pkg/htrie"
	"github.com/cactus/go-camo/pkg/router"

	"github.com/cactus/mlog"
	flags "github.com/jessevdk/go-flags"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/prometheus/common/version"
)

const metricNamespace = "camo"

var (
	// ServerVersion holds the server version string
	ServerVersion = "no-version"

	responseSize = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricNamespace,
			Name:      "response_size_bytes",
			Help:      "A histogram of sizes for proxy responses.",
			Buckets:   prometheus.ExponentialBuckets(1024, 2, 10),
		},
		[]string{},
	)
	responseDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricNamespace,
			Name:      "response_duration_seconds",
			Help:      "A histogram of latencies for proxy responses.",
			Buckets:   prometheus.DefBuckets,
		},
		[]string{},
	)
	responseCount = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "responses_total",
			Help:      "Total HTTP requests processed by the go-camo, excluding scrapes.",
		},
		[]string{"code", "method"},
	)
)

func loadFilterList(fname string) ([]camo.FilterFunc, error) {
	// #nosec
	file, err := os.Open(fname)
	if err != nil {
		return nil, fmt.Errorf("could not open filter-ruleset file: %s", err)
	}
	// #nosec
	defer file.Close()

	allowFilter := htrie.NewURLMatcher()
	denyFilter := htrie.NewURLMatcher()
	hasAllow := false
	hasDeny := false

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()

		if strings.HasPrefix(line, "allow|") {
			line = strings.TrimPrefix(line, "allow")
			err = allowFilter.AddRule(line)
			if err != nil {
				break
			}
			hasAllow = true
		} else if strings.HasPrefix(line, "deny|") {
			line = strings.TrimPrefix(line, "deny")
			err = denyFilter.AddRule(line)
			if err != nil {
				break
			}
			hasDeny = true
		} else {
			fmt.Println("ignoring line: ", line)
		}

		err = scanner.Err()
		if err != nil {
			break
		}
	}
	if err != nil {
		return nil, fmt.Errorf("error building filter ruleset: %s", err)
	}

	// append in order. allow first, then deny filters.
	// first false value aborts the request.
	filterFuncs := make([]camo.FilterFunc, 0)

	if hasAllow {
		filterFuncs = append(filterFuncs, allowFilter.CheckURL)
	}

	// denyFilter returns true on a match. we want a "false" value to abort processing.
	// so just wrap and invert the bool.
	if hasDeny {
		denyF := func(u *url.URL) bool {
			return !denyFilter.CheckURL(u)
		}
		filterFuncs = append(filterFuncs, denyF)
	}

	if hasAllow && hasDeny {
		mlog.Printf("Warning! Allow and Deny rules both supplied. Having Allow rules means anything not matching an allow rule is denied. THEN deny rules are evaluated. Be sure this is what you want!")
	}

	return filterFuncs, nil
}

func main() {
	// command line flags
	var opts struct {
		HMACKey             string        `short:"k" long:"key" description:"HMAC key"`
		AddHeaders          []string      `short:"H" long:"header" description:"Add additional header to each response. This option can be used multiple times to add multiple headers"`
		BindAddress         string        `long:"listen" default:"0.0.0.0:8080" description:"Address:Port to bind to for HTTP"`
		BindAddressSSL      string        `long:"ssl-listen" description:"Address:Port to bind to for HTTPS/SSL/TLS"`
		SSLKey              string        `long:"ssl-key" description:"ssl private key (key.pem) path"`
		SSLCert             string        `long:"ssl-cert" description:"ssl cert (cert.pem) path"`
		MaxSize             int64         `long:"max-size" description:"Max allowed response size (KB)"`
		ReqTimeout          time.Duration `long:"timeout" default:"4s" description:"Upstream request timeout"`
		MaxRedirects        int           `long:"max-redirects" default:"3" description:"Maximum number of redirects to follow"`
		Metrics             bool          `long:"metrics" description:"Enable Prometheus compatible metrics endpoint"`
		NoLogTS             bool          `long:"no-log-ts" description:"Do not add a timestamp to logging"`
		DisableKeepAlivesFE bool          `long:"no-fk" description:"Disable frontend http keep-alive support"`
		DisableKeepAlivesBE bool          `long:"no-bk" description:"Disable backend http keep-alive support"`
		AllowContentVideo   bool          `long:"allow-content-video" description:"Additionally allow 'video/*' content"`
		AllowContentAudio   bool          `long:"allow-content-audio" description:"Additionally allow 'audio/*' content"`
		AllowCredetialURLs  bool          `long:"allow-credential-urls" description:"Allow urls to contain user/pass credentials"`
		FilterRuleset       string        `long:"filter-ruleset" description:"Text file containing filtering rules (one per line)"`
		ServerName          string        `long:"server-name" default:"go-camo" description:"Value to use for the HTTP server field"`
		ExposeServerVersion bool          `long:"expose-server-version" description:"Include the server version in the HTTP server response header"`
		EnableXFwdFor       bool          `long:"enable-xfwd4" description:"Enable x-forwarded-for passthrough/generation"`
		Verbose             bool          `short:"v" long:"verbose" description:"Show verbose (debug) log level output"`
		Version             []bool        `short:"V" long:"version" description:"Print version and exit; specify twice to show license information"`
	}

	// parse said flags
	_, err := flags.Parse(&opts)
	if err != nil {
		if e, ok := err.(*flags.Error); ok {
			if e.Type == flags.ErrHelp {
				os.Exit(0)
			}
		}
		os.Exit(1)
	}

	// set the server name
	ServerName := opts.ServerName

	// setup the server response field
	ServerResponse := opts.ServerName

	// expand/override server response value if showing version is desired
	if opts.ExposeServerVersion {
		ServerResponse = fmt.Sprintf("%s %s", ServerName, ServerVersion)
	}

	// setup -V version output
	if len(opts.Version) > 0 {
		fmt.Printf("%s %s (%s,%s-%s)\n", "go-camo", ServerVersion, runtime.Version(), runtime.Compiler, runtime.GOARCH)
		if len(opts.Version) > 1 {
			fmt.Printf("\n%s\n", strings.TrimSpace(licenseText))
		}
		os.Exit(0)
	}

	// start out with a very bare logger that only prints
	// the message (no special format or log elements)
	mlog.SetFlags(0)

	config := camo.Config{}
	if hmacKey := os.Getenv("GOCAMO_HMAC"); hmacKey != "" {
		config.HMACKey = []byte(hmacKey)
	}

	// flags override env var
	if opts.HMACKey != "" {
		config.HMACKey = []byte(opts.HMACKey)
	}

	if len(config.HMACKey) == 0 {
		mlog.Fatal("HMAC key required")
	}

	if opts.BindAddress == "" && opts.BindAddressSSL == "" {
		mlog.Fatal("One of listen or ssl-listen required")
	}

	if opts.BindAddressSSL != "" && opts.SSLKey == "" {
		mlog.Fatal("ssl-key is required when specifying ssl-listen")
	}
	if opts.BindAddressSSL != "" && opts.SSLCert == "" {
		mlog.Fatal("ssl-cert is required when specifying ssl-listen")
	}

	// set keepalive options
	config.DisableKeepAlivesBE = opts.DisableKeepAlivesBE
	config.DisableKeepAlivesFE = opts.DisableKeepAlivesFE

	// other options
	config.EnableXFwdFor = opts.EnableXFwdFor
	config.AllowCredetialURLs = opts.AllowCredetialURLs

	// additional content types to allow
	config.AllowContentVideo = opts.AllowContentVideo
	config.AllowContentAudio = opts.AllowContentAudio

	var filters []camo.FilterFunc
	if opts.FilterRuleset != "" {
		filters, err = loadFilterList(opts.FilterRuleset)
		if err != nil {
			mlog.Fatal("Could not read filter-ruleset", err)
		}

	}

	AddHeaders := map[string]string{
		"X-Content-Type-Options":  "nosniff",
		"X-XSS-Protection":        "1; mode=block",
		"Content-Security-Policy": "default-src 'none'; img-src data:; style-src 'unsafe-inline'",
	}

	for _, v := range opts.AddHeaders {
		s := strings.SplitN(v, ":", 2)
		if len(s) != 2 {
			mlog.Printf("ignoring bad header: '%s'", v)
			continue
		}

		s0 := strings.TrimSpace(s[0])
		s1 := strings.TrimSpace(s[1])

		if len(s0) == 0 || len(s1) == 0 {
			mlog.Printf("ignoring bad header: '%s'", v)
			continue
		}
		AddHeaders[s[0]] = s[1]
	}

	// now configure a standard logger
	mlog.SetFlags(mlog.Lstd)
	if opts.NoLogTS {
		mlog.SetFlags(mlog.Flags() ^ mlog.Ltimestamp)
	}

	if opts.Verbose {
		mlog.SetFlags(mlog.Flags() | mlog.Ldebug)
		mlog.Debug("debug logging enabled")
	}

	// convert from KB to Bytes
	config.MaxSize = opts.MaxSize * 1024
	config.RequestTimeout = opts.ReqTimeout
	config.MaxRedirects = opts.MaxRedirects
	config.ServerName = ServerName

	// configure metrics collection in camo
	if opts.Metrics {
		config.CollectMetrics = true
	}

	proxy, err := camo.NewWithFilters(config, filters)
	if err != nil {
		mlog.Fatal("Error creating camo", err)
	}

	var router http.Handler = &router.DumbRouter{
		ServerName:  ServerResponse,
		AddHeaders:  AddHeaders,
		CamoHandler: proxy,
	}

	// configure router endpoint for rendering metrics
	if opts.Metrics {
		mlog.Printf("Enabling metrics at /metrics")
		http.Handle("/metrics", promhttp.Handler())
		// Register a version info metric.
		verOverride := os.Getenv("APP_INFO_VERSION")
		if verOverride != "" {
			version.Version = verOverride
		} else {
			version.Version = ServerVersion
		}
		version.Revision = os.Getenv("APP_INFO_REVISION")
		version.Branch = os.Getenv("APP_INFO_BRANCH")
		version.BuildDate = os.Getenv("APP_INFO_BUILD_DATE")
		prometheus.MustRegister(version.NewCollector(metricNamespace))
		// Wrap the dumb router in instrumentation.
		router = promhttp.InstrumentHandlerDuration(responseDuration, router)
		router = promhttp.InstrumentHandlerCounter(responseCount, router)
		router = promhttp.InstrumentHandlerResponseSize(responseSize, router)
	}

	http.Handle("/", router)

	if opts.BindAddress != "" {
		mlog.Printf("Starting server on: %s", opts.BindAddress)
		go func() {
			srv := &http.Server{
				Addr:        opts.BindAddress,
				ReadTimeout: 30 * time.Second}
			mlog.Fatal(srv.ListenAndServe())
		}()
	}
	if opts.BindAddressSSL != "" {
		mlog.Printf("Starting TLS server on: %s", opts.BindAddressSSL)
		go func() {
			srv := &http.Server{
				Addr:        opts.BindAddressSSL,
				ReadTimeout: 30 * time.Second}
			mlog.Fatal(srv.ListenAndServeTLS(opts.SSLCert, opts.SSLKey))
		}()
	}

	// just block. listen and serve will exit the program if they fail/return
	// so we just need to block to prevent main from exiting.
	select {}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// General mobile build environment. Initialized by envInit.
var (
	cwd          string
	gomobilepath string // $GOPATH/pkg/gomobile
	ndkccpath    string // $GOPATH/pkg/gomobile/android-{{.NDK}}

	androidArmEnv  []string
	darwinArmEnv   []string
	darwinArm64Env []string
	darwin386Env   []string
	darwinAmd64Env []string

	androidArmNM string
	darwinArmNM  string
)

func buildEnvInit() (cleanup func(), err error) {
	// Find gomobilepath.
	gopath := goEnv("GOPATH")
	for _, p := range filepath.SplitList(gopath) {
		gomobilepath = filepath.Join(p, "pkg", "gomobile")
		if _, err := os.Stat(gomobilepath); buildN || err == nil {
			break
		}
	}

	if err := envInit(); err != nil {
		return nil, err
	}

	if buildX {
		fmt.Fprintln(xout, "GOMOBILE="+gomobilepath)
	}

	// Check the toolchain is in a good state.
	// Pick a temporary directory for assembling an apk/app.
	version, err := goVersion()
	if err != nil {
		return nil, err
	}
	if gomobilepath == "" {
		return nil, errors.New("toolchain not installed, run `gomobile init`")
	}

	cleanupFn := func() {
		if buildWork {
			fmt.Printf("WORK=%s\n", tmpdir)
			return
		}
		removeAll(tmpdir)
	}
	if buildN {
		tmpdir = "$WORK"
		cleanupFn = func() {}
	} else {
		verpath := filepath.Join(gomobilepath, "version")
		installedVersion, err := ioutil.ReadFile(verpath)
		if err != nil {
			return nil, errors.New("toolchain partially installed, run `gomobile init`")
		}
		if !bytes.Equal(installedVersion, version) {
			return nil, errors.New("toolchain out of date, run `gomobile init`")
		}

		tmpdir, err = ioutil.TempDir("", "gomobile-work-")
		if err != nil {
			return nil, err
		}
	}
	if buildX {
		fmt.Fprintln(xout, "WORK="+tmpdir)
	}

	return cleanupFn, nil
}

func envInit() (err error) {
	// TODO(crawshaw): cwd only used by ctx.Import, which can take "."
	cwd, err = os.Getwd()
	if err != nil {
		return err
	}

	// Setup the cross-compiler environments.

	// TODO(crawshaw): Remove ndkccpath global.
	ndkccpath = filepath.Join(gomobilepath, "android-"+ndkVersion)
	ndkccbin := filepath.Join(ndkccpath, "arm", "bin")

	exe := ""
	if goos == "windows" {
		exe = ".exe"
	}
	androidArmEnv = []string{
		"GOOS=android",
		"GOARCH=arm",
		"GOARM=7",
		"CC=" + filepath.Join(ndkccbin, "arm-linux-androideabi-gcc"+exe),
		"CXX=" + filepath.Join(ndkccbin, "arm-linux-androideabi-g++"+exe),
		"CGO_ENABLED=1",
	}
	androidArmNM = filepath.Join(ndkccbin, "arm-linux-androideabi-nm"+exe)

	if runtime.GOOS != "darwin" {
		return nil
	}

	clang, cflags, err := envClang("iphoneos")
	if err != nil {
		return err
	}
	darwinArmEnv = []string{
		"GOOS=darwin",
		"GOARCH=arm",
		"GOARM=7",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -arch " + archClang("arm"),
		"CGO_LDFLAGS=" + cflags + " -arch " + archClang("arm"),
		"CGO_ENABLED=1",
	}
	darwinArmNM = "nm"
	darwinArm64Env = []string{
		"GOOS=darwin",
		"GOARCH=arm64",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -arch " + archClang("arm64"),
		"CGO_LDFLAGS=" + cflags + " -arch " + archClang("arm64"),
		"CGO_ENABLED=1",
	}

	clang, cflags, err = envClang("iphonesimulator")
	if err != nil {
		return err
	}
	darwin386Env = []string{
		"GOOS=darwin",
		"GOARCH=386",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
		"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
		"CGO_ENABLED=1",
	}
	darwinAmd64Env = []string{
		"GOOS=darwin",
		"GOARCH=amd64",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
		"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
		"CGO_ENABLED=1",
	}

	return nil
}

func envClang(sdkName string) (clang, cflags string, err error) {
	if buildN {
		return "clang-" + sdkName, "-isysroot=" + sdkName, nil
	}
	cmd := exec.Command("xcrun", "--sdk", sdkName, "--find", "clang")
	out, err := cmd.Output()
	if err != nil {
		return "", "", fmt.Errorf("xcrun --find: %v\n%s", err, out)
	}
	clang = strings.TrimSpace(string(out))

	cmd = exec.Command("xcrun", "--sdk", sdkName, "--show-sdk-path")
	out, err = cmd.Output()
	if err != nil {
		return "", "", fmt.Errorf("xcrun --show-sdk-path: %v\n%s", err, out)
	}
	sdk := strings.TrimSpace(string(out))

	return clang, "-isysroot " + sdk, nil
}

func archClang(goarch string) string {
	switch goarch {
	case "arm":
		return "armv7"
	case "arm64":
		return "arm64"
	case "386":
		return "i386"
	case "amd64":
		return "x86_64"
	default:
		panic(fmt.Sprintf("unknown GOARCH: %q", goarch))
	}
}

// environ merges os.Environ and the given "key=value" pairs.
// If a key is in both os.Environ and kv, kv takes precedence.
func environ(kv []string) []string {
	cur := os.Environ()
	new := make([]string, 0, len(cur)+len(kv))

	envs := make(map[string]string, len(cur))
	for _, ev := range cur {
		elem := strings.SplitN(ev, "=", 2)
		if len(elem) != 2 || elem[0] == "" {
			// pass the env var of unusual form untouched.
			// e.g. Windows may have env var names starting with "=".
			new = append(new, ev)
			continue
		}
		if goos == "windows" {
			elem[0] = strings.ToUpper(elem[0])
		}
		envs[elem[0]] = elem[1]
	}
	for _, ev := range kv {
		elem := strings.SplitN(ev, "=", 2)
		if len(elem) != 2 || elem[0] == "" {
			panic(fmt.Sprintf("malformed env var %q from input", ev))
		}
		if goos == "windows" {
			elem[0] = strings.ToUpper(elem[0])
		}
		envs[elem[0]] = elem[1]
	}
	for k, v := range envs {
		new = append(new, k+"="+v)
	}
	return new
}

func getenv(env []string, key string) string {
	prefix := key + "="
	for _, kv := range env {
		if strings.HasPrefix(kv, prefix) {
			return kv[len(prefix):]
		}
	}
	return ""
}

func pkgdir(env []string) string {
	return gomobilepath + "/pkg_" + getenv(env, "GOOS") + "_" + getenv(env, "GOARCH")
}
<commit_msg>cmd/gomobile: print stderr on xcrun failure<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// General mobile build environment. Initialized by envInit.
var (
	cwd          string
	gomobilepath string // $GOPATH/pkg/gomobile
	ndkccpath    string // $GOPATH/pkg/gomobile/android-{{.NDK}}

	androidArmEnv  []string
	darwinArmEnv   []string
	darwinArm64Env []string
	darwin386Env   []string
	darwinAmd64Env []string

	androidArmNM string
	darwinArmNM  string
)

func buildEnvInit() (cleanup func(), err error) {
	// Find gomobilepath.
	gopath := goEnv("GOPATH")
	for _, p := range filepath.SplitList(gopath) {
		gomobilepath = filepath.Join(p, "pkg", "gomobile")
		if _, err := os.Stat(gomobilepath); buildN || err == nil {
			break
		}
	}

	if err := envInit(); err != nil {
		return nil, err
	}

	if buildX {
		fmt.Fprintln(xout, "GOMOBILE="+gomobilepath)
	}

	// Check the toolchain is in a good state.
	// Pick a temporary directory for assembling an apk/app.
	version, err := goVersion()
	if err != nil {
		return nil, err
	}
	if gomobilepath == "" {
		return nil, errors.New("toolchain not installed, run `gomobile init`")
	}

	cleanupFn := func() {
		if buildWork {
			fmt.Printf("WORK=%s\n", tmpdir)
			return
		}
		removeAll(tmpdir)
	}
	if buildN {
		tmpdir = "$WORK"
		cleanupFn = func() {}
	} else {
		verpath := filepath.Join(gomobilepath, "version")
		installedVersion, err := ioutil.ReadFile(verpath)
		if err != nil {
			return nil, errors.New("toolchain partially installed, run `gomobile init`")
		}
		if !bytes.Equal(installedVersion, version) {
			return nil, errors.New("toolchain out of date, run `gomobile init`")
		}

		tmpdir, err = ioutil.TempDir("", "gomobile-work-")
		if err != nil {
			return nil, err
		}
	}
	if buildX {
		fmt.Fprintln(xout, "WORK="+tmpdir)
	}

	return cleanupFn, nil
}

func envInit() (err error) {
	// TODO(crawshaw): cwd only used by ctx.Import, which can take "."
	cwd, err = os.Getwd()
	if err != nil {
		return err
	}

	// Setup the cross-compiler environments.

	// TODO(crawshaw): Remove ndkccpath global.
	ndkccpath = filepath.Join(gomobilepath, "android-"+ndkVersion)
	ndkccbin := filepath.Join(ndkccpath, "arm", "bin")

	exe := ""
	if goos == "windows" {
		exe = ".exe"
	}
	androidArmEnv = []string{
		"GOOS=android",
		"GOARCH=arm",
		"GOARM=7",
		"CC=" + filepath.Join(ndkccbin, "arm-linux-androideabi-gcc"+exe),
		"CXX=" + filepath.Join(ndkccbin, "arm-linux-androideabi-g++"+exe),
		"CGO_ENABLED=1",
	}
	androidArmNM = filepath.Join(ndkccbin, "arm-linux-androideabi-nm"+exe)

	if runtime.GOOS != "darwin" {
		return nil
	}

	clang, cflags, err := envClang("iphoneos")
	if err != nil {
		return err
	}
	darwinArmEnv = []string{
		"GOOS=darwin",
		"GOARCH=arm",
		"GOARM=7",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -arch " + archClang("arm"),
		"CGO_LDFLAGS=" + cflags + " -arch " + archClang("arm"),
		"CGO_ENABLED=1",
	}
	darwinArmNM = "nm"
	darwinArm64Env = []string{
		"GOOS=darwin",
		"GOARCH=arm64",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -arch " + archClang("arm64"),
		"CGO_LDFLAGS=" + cflags + " -arch " + archClang("arm64"),
		"CGO_ENABLED=1",
	}

	clang, cflags, err = envClang("iphonesimulator")
	if err != nil {
		return err
	}
	darwin386Env = []string{
		"GOOS=darwin",
		"GOARCH=386",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
		"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
		"CGO_ENABLED=1",
	}
	darwinAmd64Env = []string{
		"GOOS=darwin",
		"GOARCH=amd64",
		"CC=" + clang,
		"CXX=" + clang,
		"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
		"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
		"CGO_ENABLED=1",
	}

	return nil
}

func envClang(sdkName string) (clang, cflags string, err error) {
	if buildN {
		return "clang-" + sdkName, "-isysroot=" + sdkName, nil
	}
	cmd := exec.Command("xcrun", "--sdk", sdkName, "--find", "clang")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", "", fmt.Errorf("xcrun --find: %v\n%s", err, out)
	}
	clang = strings.TrimSpace(string(out))

	cmd = exec.Command("xcrun", "--sdk", sdkName, "--show-sdk-path")
	out, err = cmd.CombinedOutput()
	if err != nil {
		return "", "", fmt.Errorf("xcrun --show-sdk-path: %v\n%s", err, out)
	}
	sdk := strings.TrimSpace(string(out))

	return clang, "-isysroot " + sdk, nil
}

func archClang(goarch string) string {
	switch goarch {
	case "arm":
		return "armv7"
	case "arm64":
		return "arm64"
	case "386":
		return "i386"
	case "amd64":
		return "x86_64"
	default:
		panic(fmt.Sprintf("unknown GOARCH: %q", goarch))
	}
}

// environ merges os.Environ and the given "key=value" pairs.
// If a key is in both os.Environ and kv, kv takes precedence.
func environ(kv []string) []string {
	cur := os.Environ()
	new := make([]string, 0, len(cur)+len(kv))

	envs := make(map[string]string, len(cur))
	for _, ev := range cur {
		elem := strings.SplitN(ev, "=", 2)
		if len(elem) != 2 || elem[0] == "" {
			// pass the env var of unusual form untouched.
			// e.g. Windows may have env var names starting with "=".
			new = append(new, ev)
			continue
		}
		if goos == "windows" {
			elem[0] = strings.ToUpper(elem[0])
		}
		envs[elem[0]] = elem[1]
	}
	for _, ev := range kv {
		elem := strings.SplitN(ev, "=", 2)
		if len(elem) != 2 || elem[0] == "" {
			panic(fmt.Sprintf("malformed env var %q from input", ev))
		}
		if goos == "windows" {
			elem[0] = strings.ToUpper(elem[0])
		}
		envs[elem[0]] = elem[1]
	}
	for k, v := range envs {
		new = append(new, k+"="+v)
	}
	return new
}

func getenv(env []string, key string) string {
	prefix := key + "="
	for _, kv := range env {
		if strings.HasPrefix(kv, prefix) {
			return kv[len(prefix):]
		}
	}
	return ""
}

func pkgdir(env []string) string {
	return gomobilepath + "/pkg_" + getenv(env, "GOOS") + "_" + getenv(env, "GOARCH")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
)

const logo = `
+---------------------------------------------+
|  _____        __ _            _____  ____   |
| |_   _|      / _| |          |  __ \|  _ \  |
|   | |  _ __ | |_| |_   ___  _| |  | | |_) | |
|   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |
|  _| |_| | | | | | | |_| |>  <| |__| | |_) | |
| |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |
+---------------------------------------------+
`

// These variables are populated via the Go linker.
var (
	version string = "0.9"
	commit  string
)

// Various constants used by the main package.
const (
	configDefaultPath string = "/etc/influxdb.conf"
)

func main() {
	log.SetFlags(0)

	// Shift binary name off argument list.
	args := os.Args[1:]

	// Retrieve command name as first argument.
	var cmd string
	if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
		cmd = args[0]
	}

	// Special case -h immediately following binary name
	if args[0] == "-h" {
		cmd = "help"
	}

	// If command is "help" and has an argument then rewrite args to use "-h".
	if cmd == "help" && len(args) > 1 {
		args[0], args[1] = args[1], "-h"
		cmd = args[0]
	}

	// Extract name from args.
	switch cmd {
	case "create-cluster":
		execCreateCluster(args[1:])
	case "join-cluster":
		execJoinCluster(args[1:])
	case "run":
		execRun(args[1:])
	case "":
		execRun(args)
	case "version":
		execVersion(args[1:])
	case "help":
		execHelp(args[1:])
	default:
		log.Fatalf(`influxd: unknown command "%s"`+"\n"+`Run 'influxd help' for usage`+"\n\n", cmd)
	}
}

// execVersion runs the "version" command.
// Prints the commit SHA1 if set by the build process.
func execVersion(args []string) {
	fs := flag.NewFlagSet("", flag.ExitOnError)
	fs.Usage = func() {
		log.Println(`usage: version

	version displays the InfluxDB version and build git commit hash
	`)
	}
	fs.Parse(args)

	s := fmt.Sprintf("InfluxDB v%s", version)
	if commit != "" {
		s += fmt.Sprintf(" (git: %s)", commit)
	}
	log.Print(s)
}

// execHelp runs the "help" command.
func execHelp(args []string) {
	fmt.Println(`
Configure and start an InfluxDB server.

Usage:

	influxd [[command] [arguments]]

The commands are:

    create-cluster       create a new node that other nodes can join to form a new cluster
    join-cluster         create a new node that will join an existing cluster
    run                  run node with existing configuration
    version              displays the InfluxDB version

"run" is the default command.

Use "influxd help [command]" for more information about a command.
`)
}

type Stopper interface {
	Stop()
}

type State struct {
	Mode string `json:"mode"`
}
<commit_msg>Fix panic when just 'influxd' is run<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
)

const logo = `
+---------------------------------------------+
|  _____        __ _            _____  ____   |
| |_   _|      / _| |          |  __ \|  _ \  |
|   | |  _ __ | |_| |_   ___  _| |  | | |_) | |
|   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |
|  _| |_| | | | | | | |_| |>  <| |__| | |_) | |
| |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |
+---------------------------------------------+
`

// These variables are populated via the Go linker.
var (
	version string = "0.9"
	commit  string
)

// Various constants used by the main package.
const (
	configDefaultPath string = "/etc/influxdb.conf"
)

func main() {
	log.SetFlags(0)

	// Shift binary name off argument list.
	args := os.Args[1:]

	// Retrieve command name as first argument.
	var cmd string
	if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
		cmd = args[0]
	}

	// Special case -h immediately following binary name
	if len(args) > 0 && args[0] == "-h" {
		cmd = "help"
	}

	// If command is "help" and has an argument then rewrite args to use "-h".
	if cmd == "help" && len(args) > 1 {
		args[0], args[1] = args[1], "-h"
		cmd = args[0]
	}

	// Extract name from args.
	switch cmd {
	case "create-cluster":
		execCreateCluster(args[1:])
	case "join-cluster":
		execJoinCluster(args[1:])
	case "run":
		execRun(args[1:])
	case "":
		execRun(args)
	case "version":
		execVersion(args[1:])
	case "help":
		execHelp(args[1:])
	default:
		log.Fatalf(`influxd: unknown command "%s"`+"\n"+`Run 'influxd help' for usage`+"\n\n", cmd)
	}
}

// execVersion runs the "version" command.
// Prints the commit SHA1 if set by the build process.
func execVersion(args []string) {
	fs := flag.NewFlagSet("", flag.ExitOnError)
	fs.Usage = func() {
		log.Println(`usage: version

	version displays the InfluxDB version and build git commit hash
	`)
	}
	fs.Parse(args)

	s := fmt.Sprintf("InfluxDB v%s", version)
	if commit != "" {
		s += fmt.Sprintf(" (git: %s)", commit)
	}
	log.Print(s)
}

// execHelp runs the "help" command.
func execHelp(args []string) {
	fmt.Println(`
Configure and start an InfluxDB server.

Usage:

	influxd [[command] [arguments]]

The commands are:

    create-cluster       create a new node that other nodes can join to form a new cluster
    join-cluster         create a new node that will join an existing cluster
    run                  run node with existing configuration
    version              displays the InfluxDB version

"run" is the default command.

Use "influxd help [command]" for more information about a command.
`)
}

type Stopper interface {
	Stop()
}

type State struct {
	Mode string `json:"mode"`
}
<|endoftext|>


<commit_before>// Copyright 2017 Istio 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 (
	"fmt"
	"os"
	"time"

	"istio.io/manager/cmd"
	"istio.io/manager/model"
	"istio.io/manager/platform/kube"
	"istio.io/manager/proxy/envoy"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

type args struct {
	proxy                    envoy.MeshConfig
	identity                 envoy.ProxyNode
	sdsPort                  int
	ingressSecret            string
	ingressClass             string
	defaultIngressController bool
}

const (
	resyncPeriod = 100 * time.Millisecond
)

var (
	flags = &args{
		proxy: *envoy.DefaultMeshConfig,
	}

	discoveryCmd = &cobra.Command{
		Use:   "discovery",
		Short: "Start Istio Manager discovery service",
		RunE: func(c *cobra.Command, args []string) (err error) {
			controller := kube.NewController(cmd.Client, kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressOff,
			})
			sds := envoy.NewDiscoveryService(controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				&flags.proxy,
				flags.sdsPort)
			stop := make(chan struct{})
			go controller.Run(stop)
			go sds.Run()
			cmd.WaitSignal(stop)
			return
		},
	}

	proxyCmd = &cobra.Command{
		Use:   "proxy",
		Short: "Istio Proxy agent",
	}

	sidecarCmd = &cobra.Command{
		Use:   "sidecar",
		Short: "Istio Proxy sidecar agent",
		RunE: func(c *cobra.Command, args []string) (err error) {
			setFlagsFromEnv()
			controller := kube.NewController(cmd.Client, kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressOff,
			})
			w, err := envoy.NewWatcher(controller,
				controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				&flags.proxy,
				&flags.identity)
			if err != nil {
				return
			}
			stop := make(chan struct{})
			go w.Run(stop)
			cmd.WaitSignal(stop)
			return
		},
	}

	ingressCmd = &cobra.Command{
		Use:   "ingress",
		Short: "Istio Proxy ingress controller",
		RunE: func(c *cobra.Command, args []string) error {
			controllerConfig := kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressStrict,
				IngressClass:    flags.ingressClass,
			}
			if flags.defaultIngressController {
				controllerConfig.IngressSyncMode = kube.IngressDefault
			}
			controller := kube.NewController(cmd.Client, controllerConfig)
			w, err := envoy.NewIngressWatcher(controller, controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				cmd.Client, &flags.proxy, flags.ingressSecret, cmd.RootFlags.Namespace)
			if err != nil {
				return err
			}
			stop := make(chan struct{})
			go w.Run(stop)
			cmd.WaitSignal(stop)
			return nil
		},
	}

	egressCmd = &cobra.Command{
		Use:   "egress",
		Short: "Istio Proxy external service agent",
		RunE: func(c *cobra.Command, args []string) error {
			// TODO: implement this method
			stop := make(chan struct{})
			cmd.WaitSignal(stop)
			return nil
		},
	}
)

func init() {
	discoveryCmd.PersistentFlags().IntVarP(&flags.sdsPort, "port", "p", 8080,
		"Discovery service port")
	discoveryCmd.PersistentFlags().StringVarP(&flags.proxy.MixerAddress, "mixer", "m",
		"",
		"Mixer DNS address (or empty to disable Mixer)")

	proxyCmd.PersistentFlags().StringVar(&flags.identity.IP, "nodeIP", "",
		"Proxy node IP address. If not provided uses ${POD_IP} environment variable.")
	proxyCmd.PersistentFlags().StringVar(&flags.identity.Name, "nodeName", "",
		"Proxy node name. If not provided uses ${POD_NAME}.${POD_NAMESPACE}")

	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.DiscoveryAddress, "sds", "s",
		envoy.DefaultMeshConfig.DiscoveryAddress,
		"Discovery service DNS address")
	proxyCmd.PersistentFlags().IntVarP(&flags.proxy.ProxyPort, "port", "p",
		envoy.DefaultMeshConfig.ProxyPort,
		"Envoy proxy port")
	proxyCmd.PersistentFlags().IntVarP(&flags.proxy.AdminPort, "admin_port", "a",
		envoy.DefaultMeshConfig.AdminPort,
		"Envoy admin port")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.BinaryPath, "envoy_path", "b",
		envoy.DefaultMeshConfig.BinaryPath,
		"Envoy binary location")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.ConfigPath, "config_path", "e",
		envoy.DefaultMeshConfig.ConfigPath,
		"Envoy config root location")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.MixerAddress, "mixer", "m",
		"",
		"Mixer DNS address (or empty to disable Mixer)")
	proxyCmd.PersistentFlags().BoolVar(&flags.proxy.EnableAuth, "enable_auth",
		envoy.DefaultMeshConfig.EnableAuth,
		"The Envoy enforces auth for proxy-proxy traffic")
	proxyCmd.PersistentFlags().StringVar(&flags.proxy.AuthConfigPath, "auth_config_path",
		envoy.DefaultMeshConfig.AuthConfigPath,
		"The path Envoy uses to find files: cert_chain, private_key, ca_cert")

	proxyCmd.AddCommand(sidecarCmd)
	proxyCmd.AddCommand(ingressCmd)
	proxyCmd.AddCommand(egressCmd)

	// TODO: remove this once we write the logic to obtain secrets dynamically
	ingressCmd.PersistentFlags().StringVar(&flags.ingressSecret, "secret",
		"",
		"Kubernetes secret name for ingress SSL termination")
	ingressCmd.PersistentFlags().StringVar(&flags.ingressClass, "ingress_class",
		"istio",
		"The class of ingress resources to be processed by this ingress controller")
	ingressCmd.PersistentFlags().BoolVar(&flags.defaultIngressController, "default_ingress_controller",
		true,
		"Specifies whether running as the cluster's default ingress controller, "+
			"thereby processing unclassified ingress resources")

	cmd.RootCmd.Use = "manager"
	cmd.RootCmd.Long = `
Istio Manager provides management plane functionality to the Istio proxy mesh and Istio Mixer.`
	cmd.RootCmd.AddCommand(discoveryCmd)
	cmd.RootCmd.AddCommand(proxyCmd)
}

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		glog.Error(err)
		os.Exit(-1)
	}
}

// setFlagsFromEnv sets default values for flags that are not specified
func setFlagsFromEnv() {
	if flags.identity.IP == "" {
		flags.identity.IP = os.Getenv("POD_IP")
	}
	if flags.identity.Name == "" {
		flags.identity.Name = fmt.Sprintf("%s.%s", os.Getenv("POD_NAME"), os.Getenv("POD_NAMESPACE"))
	}

}
<commit_msg>Add auth related flags for discovery command (#419)<commit_after>// Copyright 2017 Istio 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 (
	"fmt"
	"os"
	"time"

	"istio.io/manager/cmd"
	"istio.io/manager/model"
	"istio.io/manager/platform/kube"
	"istio.io/manager/proxy/envoy"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

type args struct {
	proxy                    envoy.MeshConfig
	identity                 envoy.ProxyNode
	sdsPort                  int
	ingressSecret            string
	ingressClass             string
	defaultIngressController bool
}

const (
	resyncPeriod = 100 * time.Millisecond
)

var (
	flags = &args{
		proxy: *envoy.DefaultMeshConfig,
	}

	discoveryCmd = &cobra.Command{
		Use:   "discovery",
		Short: "Start Istio Manager discovery service",
		RunE: func(c *cobra.Command, args []string) (err error) {
			controller := kube.NewController(cmd.Client, kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressOff,
			})
			sds := envoy.NewDiscoveryService(controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				&flags.proxy,
				flags.sdsPort)
			stop := make(chan struct{})
			go controller.Run(stop)
			go sds.Run()
			cmd.WaitSignal(stop)
			return
		},
	}

	proxyCmd = &cobra.Command{
		Use:   "proxy",
		Short: "Istio Proxy agent",
	}

	sidecarCmd = &cobra.Command{
		Use:   "sidecar",
		Short: "Istio Proxy sidecar agent",
		RunE: func(c *cobra.Command, args []string) (err error) {
			setFlagsFromEnv()
			controller := kube.NewController(cmd.Client, kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressOff,
			})
			w, err := envoy.NewWatcher(controller,
				controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				&flags.proxy,
				&flags.identity)
			if err != nil {
				return
			}
			stop := make(chan struct{})
			go w.Run(stop)
			cmd.WaitSignal(stop)
			return
		},
	}

	ingressCmd = &cobra.Command{
		Use:   "ingress",
		Short: "Istio Proxy ingress controller",
		RunE: func(c *cobra.Command, args []string) error {
			controllerConfig := kube.ControllerConfig{
				Namespace:       cmd.RootFlags.Namespace,
				ResyncPeriod:    resyncPeriod,
				IngressSyncMode: kube.IngressStrict,
				IngressClass:    flags.ingressClass,
			}
			if flags.defaultIngressController {
				controllerConfig.IngressSyncMode = kube.IngressDefault
			}
			controller := kube.NewController(cmd.Client, controllerConfig)
			w, err := envoy.NewIngressWatcher(controller, controller,
				&model.IstioRegistry{ConfigRegistry: controller},
				cmd.Client, &flags.proxy, flags.ingressSecret, cmd.RootFlags.Namespace)
			if err != nil {
				return err
			}
			stop := make(chan struct{})
			go w.Run(stop)
			cmd.WaitSignal(stop)
			return nil
		},
	}

	egressCmd = &cobra.Command{
		Use:   "egress",
		Short: "Istio Proxy external service agent",
		RunE: func(c *cobra.Command, args []string) error {
			// TODO: implement this method
			stop := make(chan struct{})
			cmd.WaitSignal(stop)
			return nil
		},
	}
)

func init() {
	discoveryCmd.PersistentFlags().IntVarP(&flags.sdsPort, "port", "p", 8080,
		"Discovery service port")
	discoveryCmd.PersistentFlags().StringVarP(&flags.proxy.MixerAddress, "mixer", "m",
		"",
		"Mixer DNS address (or empty to disable Mixer)")
	discoveryCmd.PersistentFlags().BoolVar(&flags.proxy.EnableAuth, "enable_auth",
		envoy.DefaultMeshConfig.EnableAuth,
		"Enable mutual TLS for proxy-to-proxy traffic")
	discoveryCmd.PersistentFlags().StringVar(&flags.proxy.AuthConfigPath, "auth_config_path",
		envoy.DefaultMeshConfig.AuthConfigPath,
		"The directory in which certificate and key files are stored")

	proxyCmd.PersistentFlags().StringVar(&flags.identity.IP, "nodeIP", "",
		"Proxy node IP address. If not provided uses ${POD_IP} environment variable.")
	proxyCmd.PersistentFlags().StringVar(&flags.identity.Name, "nodeName", "",
		"Proxy node name. If not provided uses ${POD_NAME}.${POD_NAMESPACE}")

	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.DiscoveryAddress, "sds", "s",
		envoy.DefaultMeshConfig.DiscoveryAddress,
		"Discovery service DNS address")
	proxyCmd.PersistentFlags().IntVarP(&flags.proxy.ProxyPort, "port", "p",
		envoy.DefaultMeshConfig.ProxyPort,
		"Envoy proxy port")
	proxyCmd.PersistentFlags().IntVarP(&flags.proxy.AdminPort, "admin_port", "a",
		envoy.DefaultMeshConfig.AdminPort,
		"Envoy admin port")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.BinaryPath, "envoy_path", "b",
		envoy.DefaultMeshConfig.BinaryPath,
		"Envoy binary location")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.ConfigPath, "config_path", "e",
		envoy.DefaultMeshConfig.ConfigPath,
		"Envoy config root location")
	proxyCmd.PersistentFlags().StringVarP(&flags.proxy.MixerAddress, "mixer", "m",
		"",
		"Mixer DNS address (or empty to disable Mixer)")
	proxyCmd.PersistentFlags().BoolVar(&flags.proxy.EnableAuth, "enable_auth",
		envoy.DefaultMeshConfig.EnableAuth,
		"Enable mutual TLS for proxy-to-proxy traffic")
	proxyCmd.PersistentFlags().StringVar(&flags.proxy.AuthConfigPath, "auth_config_path",
		envoy.DefaultMeshConfig.AuthConfigPath,
		"The directory in which certificate and key files are stored")

	proxyCmd.AddCommand(sidecarCmd)
	proxyCmd.AddCommand(ingressCmd)
	proxyCmd.AddCommand(egressCmd)

	// TODO: remove this once we write the logic to obtain secrets dynamically
	ingressCmd.PersistentFlags().StringVar(&flags.ingressSecret, "secret",
		"",
		"Kubernetes secret name for ingress SSL termination")
	ingressCmd.PersistentFlags().StringVar(&flags.ingressClass, "ingress_class",
		"istio",
		"The class of ingress resources to be processed by this ingress controller")
	ingressCmd.PersistentFlags().BoolVar(&flags.defaultIngressController, "default_ingress_controller",
		true,
		"Specifies whether running as the cluster's default ingress controller, "+
			"thereby processing unclassified ingress resources")

	cmd.RootCmd.Use = "manager"
	cmd.RootCmd.Long = `
Istio Manager provides management plane functionality to the Istio proxy mesh and Istio Mixer.`
	cmd.RootCmd.AddCommand(discoveryCmd)
	cmd.RootCmd.AddCommand(proxyCmd)
}

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		glog.Error(err)
		os.Exit(-1)
	}
}

// setFlagsFromEnv sets default values for flags that are not specified
func setFlagsFromEnv() {
	if flags.identity.IP == "" {
		flags.identity.IP = os.Getenv("POD_IP")
	}
	if flags.identity.Name == "" {
		flags.identity.Name = fmt.Sprintf("%s.%s", os.Getenv("POD_NAME"), os.Getenv("POD_NAMESPACE"))
	}

}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google LLC.

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

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

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

package main

import (
	"os"

	"k8s.io/airflow-operator/pkg/apis"
	"k8s.io/airflow-operator/pkg/controller"
	"k8s.io/airflow-operator/pkg/webhook"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	"sigs.k8s.io/controller-runtime/pkg/client/config"
	"sigs.k8s.io/controller-runtime/pkg/manager"
	logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
	"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
)

func main() {
	logf.SetLogger(logf.ZapLogger(false))
	log := logf.Log.WithName("entrypoint")

	// Get a config to talk to the apiserver
	log.Info("setting up client for manager")
	cfg, err := config.GetConfig()
	if err != nil {
		log.Error(err, "unable to set up client config")
		os.Exit(1)
	}

	// Create a new Cmd to provide shared dependencies and start components
	log.Info("setting up manager")
	mgr, err := manager.New(cfg, manager.Options{})
	if err != nil {
		log.Error(err, "unable to set up overall controller manager")
		os.Exit(1)
	}

	log.Info("Registering Components.")

	// Setup Scheme for all resources
	log.Info("setting up scheme")
	if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
		log.Error(err, "unable add APIs to scheme")
		os.Exit(1)
	}

	// Setup all Controllers
	log.Info("Setting up controller")
	if err := controller.AddToManager(mgr); err != nil {
		log.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

	log.Info("setting up webhooks")
	if err := webhook.AddToManager(mgr); err != nil {
		log.Error(err, "unable to register webhooks to the manager")
		os.Exit(1)
	}

	// Start the Cmd
	log.Info("Starting the Cmd.")
	if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
		log.Error(err, "unable to run the manager")
		os.Exit(1)
	}
}
<commit_msg>reconcile every 2mins<commit_after>/*
Copyright 2018 Google LLC.

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

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

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

package main

import (
	"os"

	"k8s.io/airflow-operator/pkg/apis"
	"k8s.io/airflow-operator/pkg/controller"
	"k8s.io/airflow-operator/pkg/webhook"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	"sigs.k8s.io/controller-runtime/pkg/client/config"
	"sigs.k8s.io/controller-runtime/pkg/manager"
	logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
	"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
	"time"
)

func main() {
	logf.SetLogger(logf.ZapLogger(false))
	log := logf.Log.WithName("entrypoint")

	// Get a config to talk to the apiserver
	log.Info("setting up client for manager")
	cfg, err := config.GetConfig()
	if err != nil {
		log.Error(err, "unable to set up client config")
		os.Exit(1)
	}

	// Create a new Cmd to provide shared dependencies and start components
	log.Info("setting up manager")
	syncperiod := time.Minute * 2
	mgr, err := manager.New(cfg, manager.Options{SyncPeriod: &syncperiod})
	if err != nil {
		log.Error(err, "unable to set up overall controller manager")
		os.Exit(1)
	}

	log.Info("Registering Components.")

	// Setup Scheme for all resources
	log.Info("setting up scheme")
	if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
		log.Error(err, "unable add APIs to scheme")
		os.Exit(1)
	}

	// Setup all Controllers
	log.Info("Setting up controller")
	if err := controller.AddToManager(mgr); err != nil {
		log.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

	log.Info("setting up webhooks")
	if err := webhook.AddToManager(mgr); err != nil {
		log.Error(err, "unable to register webhooks to the manager")
		os.Exit(1)
	}

	// Start the Cmd
	log.Info("Starting the Cmd.")
	if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
		log.Error(err, "unable to run the manager")
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"log"
	"os"

	"github.com/dolmen-go/mylogin"
)

func main() {
	//mylogin.ReadConfig(os.Args[1], os.Args[2])
	file, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	rd, err := mylogin.Decode(bufio.NewReader(file))
	if err != nil {
		log.Fatal(err)
	}

	if len(os.Args) == 3 {
		rd = mylogin.FilterSection(rd, os.Args[2])
	}

	_, err = io.Copy(os.Stdout, rd)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>cmd/mylogin: use the default file if len(os.Args) == 0<commit_after>package main

import (
	"bufio"
	"io"
	"log"
	"os"

	"github.com/dolmen-go/mylogin"
)

func main() {
	var filename string

	if len(os.Args) > 1 {
		filename = os.Args[1]
	} else {
		filename = mylogin.DefaultFile()
	}

	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	rd, err := mylogin.Decode(bufio.NewReader(file))
	if err != nil {
		log.Fatal(err)
	}

	if len(os.Args) == 3 {
		rd = mylogin.FilterSection(rd, os.Args[2])
	}

	_, err = io.Copy(os.Stdout, rd)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// nvim-go is a Go language development plugin for Neovim written in pure Go.
package main

import (
	"context"
	logpkg "log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/google/gops/agent"
	"github.com/neovim/go-client/nvim/plugin"
	"github.com/pkg/errors"
	"github.com/zchee/nvim-go/src/autocmd"
	"github.com/zchee/nvim-go/src/buildctx"
	"github.com/zchee/nvim-go/src/command"
	"github.com/zchee/nvim-go/src/logger"
	"github.com/zchee/nvim-go/src/server"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	zapLogger, undo := logger.NewRedirectZapLogger()
	defer undo()
	ctx = logger.NewContext(ctx, zapLogger)

	var eg = &errgroup.Group{}
	eg, ctx = errgroup.WithContext(ctx)
	eg.Go(func() error {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		plugin.Main(fn)
		return nil
	})
	eg.Go(func() error {
		return Child(ctx)
	})
	go func() {
		if err := eg.Wait(); err != nil {
			zapLogger.Fatal("eg.Wait", zap.Error(err))
		}
	}()

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
	select {
	case sig := <-sigc:
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			zapLogger.Debug("main", zap.String("interrupted %s signal", sig.String()))
			cancel() // avoid goroutine leak
			return
		}
	}
}

func Main(ctx context.Context, p *plugin.Plugin) error {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""
	pprof := os.Getenv("NVIM_GO_PPROF") != ""

	log := logger.FromContext(ctx).Named("main")

	buildctxt := buildctx.NewContext()
	c := command.Register(ctx, p, buildctxt)
	autocmd.Register(ctx, p, buildctxt, c)

	if debug {
		// starts the gops agent
		if err := agent.Listen(&agent.Options{NoShutdownCleanup: true}); err != nil {
			return err
		}

		if pprof {
			const addr = "localhost:14715" // (n: 14)vim-(g: 7)(o: 15)
			log.Debug("start the pprof debugging", zap.String("listen at", addr))

			// enable the report of goroutine blocking events
			runtime.SetBlockProfileRate(1)
			go logpkg.Println(http.ListenAndServe(addr, nil))
		}
	}

	return nil
}

func Child(ctx context.Context) error {
	log := logger.FromContext(ctx).Named("child")

	s, err := server.NewServer(ctx)
	if err != nil {
		return errors.Wrap(err, "failed to create NewServer")
	}
	go s.Serve()
	defer func() {
		if err := s.Close(); err != nil {
			log.Fatal("Close", zap.Error(err))
		}
	}()

	bufs, err := s.Buffers()
	if err != nil {
		return errors.Wrap(err, "failed to get buffers")
	}
	// Get the names using a single atomic call to Nvim.
	names := make([]string, len(bufs))
	b := s.NewBatch()
	for i, buf := range bufs {
		b.BufferName(buf, &names[i])
	}

	if err := b.Execute(); err != nil {
		return errors.Wrap(err, "failed to execute batch")
	}

	for _, name := range names {
		log.Info("", zap.String("name", name))
	}

	return nil
}
<commit_msg>cmd/nvim-go: remove %s verb from zap.String<commit_after>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// nvim-go is a Go language development plugin for Neovim written in pure Go.
package main

import (
	"context"
	logpkg "log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/google/gops/agent"
	"github.com/neovim/go-client/nvim/plugin"
	"github.com/pkg/errors"
	"github.com/zchee/nvim-go/src/autocmd"
	"github.com/zchee/nvim-go/src/buildctx"
	"github.com/zchee/nvim-go/src/command"
	"github.com/zchee/nvim-go/src/logger"
	"github.com/zchee/nvim-go/src/server"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	zapLogger, undo := logger.NewRedirectZapLogger()
	defer undo()
	ctx = logger.NewContext(ctx, zapLogger)

	var eg = &errgroup.Group{}
	eg, ctx = errgroup.WithContext(ctx)
	eg.Go(func() error {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		plugin.Main(fn)
		return nil
	})
	eg.Go(func() error {
		return Child(ctx)
	})
	go func() {
		if err := eg.Wait(); err != nil {
			zapLogger.Fatal("eg.Wait", zap.Error(err))
		}
	}()

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
	select {
	case sig := <-sigc:
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			zapLogger.Debug("main", zap.String("interrupted signal", sig.String()))
			cancel() // avoid goroutine leak
			return
		}
	}
}

func Main(ctx context.Context, p *plugin.Plugin) error {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""
	pprof := os.Getenv("NVIM_GO_PPROF") != ""

	log := logger.FromContext(ctx).Named("main")

	buildctxt := buildctx.NewContext()
	c := command.Register(ctx, p, buildctxt)
	autocmd.Register(ctx, p, buildctxt, c)

	if debug {
		// starts the gops agent
		if err := agent.Listen(&agent.Options{NoShutdownCleanup: true}); err != nil {
			return err
		}

		if pprof {
			const addr = "localhost:14715" // (n: 14)vim-(g: 7)(o: 15)
			log.Debug("start the pprof debugging", zap.String("listen at", addr))

			// enable the report of goroutine blocking events
			runtime.SetBlockProfileRate(1)
			go logpkg.Println(http.ListenAndServe(addr, nil))
		}
	}

	return nil
}

func Child(ctx context.Context) error {
	log := logger.FromContext(ctx).Named("child")

	s, err := server.NewServer(ctx)
	if err != nil {
		return errors.Wrap(err, "failed to create NewServer")
	}
	go s.Serve()
	defer func() {
		if err := s.Close(); err != nil {
			log.Fatal("Close", zap.Error(err))
		}
	}()

	bufs, err := s.Buffers()
	if err != nil {
		return errors.Wrap(err, "failed to get buffers")
	}
	// Get the names using a single atomic call to Nvim.
	names := make([]string, len(bufs))
	b := s.NewBatch()
	for i, buf := range bufs {
		b.BufferName(buf, &names[i])
	}

	if err := b.Execute(); err != nil {
		return errors.Wrap(err, "failed to execute batch")
	}

	for _, name := range names {
		log.Info("", zap.String("name", name))
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/zyxar/shooter"
)

var dirname string

func init() {
	flag.StringVar(&dirname, "dir", "", "set target directory")
}

type message struct {
	body io.ReadCloser
	fn   string
}

func main() {
	flag.Parse()
	for _, fullpath := range flag.Args() {
		filehash, err := shooter.FileHash(fullpath)
		if err != nil {
			fmt.Println("[ERROR]", err)
			continue
		}
		var filename string
		if dirname == "" {
			fullpath, err = filepath.Abs(fullpath)
			if err != nil {
				fmt.Println("[ERROR]", err)
				continue
			}
			dirname, filename = filepath.Split(fullpath)
		} else {
			filename = filepath.Base(fullpath)
		}
		files, err := shooter.Query(filehash, filename)
		if err != nil {
			fmt.Println("[ERROR]", err)
			continue
		}
		filesNum := len(files)
		fmt.Printf("Found %d subtitles for %s\n", filesNum, filename)
		msgChan := make(chan *message, filesNum)
		for i := range files {
			go func(i int) {
				body, fn, err := files[i].FetchContent()
				if err != nil {
					fmt.Printf("[ERROR] %s-%d %v\n", fn, i, err)
					msgChan <- nil
				} else {
					msgChan <- &message{body, fn}
				}
			}(i)
		}
		j := 1
		var saveFile = func(body io.ReadCloser, fn string) {
			ext := filepath.Ext(fn)
			if dirname != "" {
				fn = filepath.Join(dirname, fn)
			}
			filename := fn
			fn = fn[:len(fn)-len(ext)]
			var file *os.File
			var err error
		retry:
			if _, err = os.Lstat(filename); os.IsNotExist(err) {
				if file, err = os.Create(filename); err == nil {
					_, err = io.Copy(file, body)
					body.Close()
					file.Close()
					fmt.Printf("[DONE] %s\n", filename)
				} else {
					fmt.Println("[ERROR]", err)
				}
			} else {
				filename = fmt.Sprintf("%s-%d%s", fn, j, ext)
				j++
				goto retry
			}
			return
		}
		for i := 0; i < filesNum; i++ {
			msg := <-msgChan
			if msg != nil {
				saveFile(msg.body, msg.fn)
			}
		}
	}
}
<commit_msg>shooter: usage<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/zyxar/shooter"
)

var dirname string

func init() {
	flag.StringVar(&dirname, "dir", "", "set target directory")
	flag.Usage = func() {
		fmt.Println("Usage: shooter [OPTION] film_file")
		flag.PrintDefaults()
	}
}

type message struct {
	body io.ReadCloser
	fn   string
}

func main() {
	flag.Parse()
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}
	for _, fullpath := range flag.Args() {
		filehash, err := shooter.FileHash(fullpath)
		if err != nil {
			fmt.Println("[ERROR]", err)
			continue
		}
		var filename string
		if dirname == "" {
			fullpath, err = filepath.Abs(fullpath)
			if err != nil {
				fmt.Println("[ERROR]", err)
				continue
			}
			dirname, filename = filepath.Split(fullpath)
		} else {
			filename = filepath.Base(fullpath)
		}
		files, err := shooter.Query(filehash, filename)
		if err != nil {
			fmt.Println("[ERROR]", err)
			continue
		}
		filesNum := len(files)
		fmt.Printf("Found %d subtitles for %s\n", filesNum, filename)
		msgChan := make(chan *message, filesNum)
		for i := range files {
			go func(i int) {
				body, fn, err := files[i].FetchContent()
				if err != nil {
					fmt.Printf("[ERROR] %s-%d %v\n", fn, i, err)
					msgChan <- nil
				} else {
					msgChan <- &message{body, fn}
				}
			}(i)
		}
		j := 1
		var saveFile = func(body io.ReadCloser, fn string) {
			ext := filepath.Ext(fn)
			if dirname != "" {
				fn = filepath.Join(dirname, fn)
			}
			filename := fn
			fn = fn[:len(fn)-len(ext)]
			var file *os.File
			var err error
		retry:
			if _, err = os.Lstat(filename); os.IsNotExist(err) {
				if file, err = os.Create(filename); err == nil {
					_, err = io.Copy(file, body)
					body.Close()
					file.Close()
					fmt.Printf("[DONE] %s\n", filename)
				} else {
					fmt.Println("[ERROR]", err)
				}
			} else {
				filename = fmt.Sprintf("%s-%d%s", fn, j, ext)
				j++
				goto retry
			}
			return
		}
		for i := 0; i < filesNum; i++ {
			msg := <-msgChan
			if msg != nil {
				saveFile(msg.body, msg.fn)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

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

	"gopkg.in/alecthomas/kingpin.v2"
)

const syslModuleName = "syslmodules"

type modCmd struct {
	subcommand string
}

func (m *modCmd) Name() string       { return "mod" }
func (m *modCmd) MaxSyslModule() int { return 0 }

func (m *modCmd) Configure(app *kingpin.Application) *kingpin.CmdClause {
	opts := []string{"init"}
	cmd := app.Command(m.Name(), "Configure sysl module system")
	cmd.Arg("command", fmt.Sprintf("commands: [%s]", strings.Join(opts, ","))).Required().EnumVar(&m.subcommand, opts...)

	return cmd
}

func (m *modCmd) Execute(args ExecuteArgs) error {
	if m.subcommand == "init" {
		// ignore folder creation error
		_err := args.Filesystem.Mkdir(syslRootMarker, 0755)
		if _err != nil {
			args.Logger.Warn(_err.Error())
		}
		err := os.Chdir(syslRootMarker)
		if err != nil {
			return err
		}
		out, err := exec.Command("go", "mod", "init", syslModuleName).CombinedOutput()
		if err != nil {
			return err
		}
		args.Logger.Debug(out)
	}
	return nil
}
<commit_msg>Extract mod init code to separate function<commit_after>package main

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

	"gopkg.in/alecthomas/kingpin.v2"
)

const syslModuleName = "syslmodules"

type modCmd struct {
	subcommand string
}

func (m *modCmd) Name() string       { return "mod" }
func (m *modCmd) MaxSyslModule() int { return 0 }

func (m *modCmd) Configure(app *kingpin.Application) *kingpin.CmdClause {
	opts := []string{"init"}
	cmd := app.Command(m.Name(), "Configure sysl module system")
	cmd.Arg("command", fmt.Sprintf("commands: [%s]", strings.Join(opts, ","))).Required().EnumVar(&m.subcommand, opts...)

	return cmd
}

func (m *modCmd) Execute(args ExecuteArgs) error {
	if m.subcommand == "init" {
		err := syslModInit(args)
		if err != nil {
			return err
		}
	}
	return nil
}

func syslModInit(args ExecuteArgs) error {
	// ignore folder creation error
	_err := args.Filesystem.Mkdir(syslRootMarker, 0755)
	if _err != nil {
		args.Logger.Warn(_err.Error())
	}

	err := os.Chdir(syslRootMarker)
	if err != nil {
		return err
	}

	out, err := exec.Command("go", "mod", "init", syslModuleName).CombinedOutput()
	if err != nil {
		return err
	}

	args.Logger.Debug(out)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"

	"github.com/spf13/cobra"

	"github.com/coreos/torus"
	"github.com/coreos/torus/block"
	"github.com/coreos/torus/block/aoe"
)

var aoeCommand = &cobra.Command{
	Use:   "aoe VOLUME INTERFACE MAJOR MINOR",
	Short: "serve a volume over AoE",
	Long: strings.TrimSpace(`
Serve a volume over AoE using the specified network interface and AoE
major and minor addresses.

It is important to note that all AoE servers on the same layer 2 network
must have different major and minor addresses.

An example of serving two volumes using AoE on the same server over the
eth0 network interface:

	torusblk aoe vol01 eth0 1 1
	torusblk aoe vol02 eth0 1 2
`),
	Run: func(cmd *cobra.Command, args []string) {
		err := aoeAction(cmd, args)
		if err == torus.ErrUsage {
			cmd.Usage()
			os.Exit(1)
		} else if err != nil {
			die("%v", err)
		}
	},
}

func aoeAction(cmd *cobra.Command, args []string) error {
	if len(args) != 4 {
		return torus.ErrUsage
	}

	srv := createServer()

	vol := args[0]
	ifname := args[1]
	maj := args[2]
	min := args[3]

	major, err := strconv.ParseUint(maj, 10, 16)
	if err != nil {
		return fmt.Errorf("Failed to parse major address %q: %v", maj, err)
	}

	minor, err := strconv.ParseUint(min, 10, 8)
	if err != nil {
		return fmt.Errorf("Failed to parse minor address %q: %v", min, err)
	}

	blockvol, err := block.OpenBlockVolume(srv, vol)
	if err != nil {
		return fmt.Errorf("server doesn't support block volumes: %v", err)
	}

	ai, err := aoe.NewInterface(ifname)
	if err != nil {
		return fmt.Errorf("Failed to set up interface %q: %v", ifname, err)
	}

	as, err := aoe.NewServer(blockvol, &aoe.ServerOptions{
		Major: uint16(major),
		Minor: uint8(minor),
	})
	if err != nil {
		return fmt.Errorf("Failed to crate AoE server: %v", err)
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)

	go func(sv *torus.Server, iface *aoe.Interface) {
		for _ = range signalChan {
			fmt.Println("\nReceived an interrupt, stopping services...")

			iface.Close()
			sv.Close()
			as.Close()
			os.Exit(0)
		}
	}(srv, ai)

	if err = as.Serve(ai); err != nil {
		return fmt.Errorf("Failed to serve AoE: %v", err)
	}
	return nil
}
<commit_msg>aoe: close servers by defer<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"

	"github.com/spf13/cobra"

	"github.com/coreos/torus"
	"github.com/coreos/torus/block"
	"github.com/coreos/torus/block/aoe"
)

var aoeCommand = &cobra.Command{
	Use:   "aoe VOLUME INTERFACE MAJOR MINOR",
	Short: "serve a volume over AoE",
	Long: strings.TrimSpace(`
Serve a volume over AoE using the specified network interface and AoE
major and minor addresses.

It is important to note that all AoE servers on the same layer 2 network
must have different major and minor addresses.

An example of serving two volumes using AoE on the same server over the
eth0 network interface:

	torusblk aoe vol01 eth0 1 1
	torusblk aoe vol02 eth0 1 2
`),
	Run: func(cmd *cobra.Command, args []string) {
		err := aoeAction(cmd, args)
		if err == torus.ErrUsage {
			cmd.Usage()
			os.Exit(1)
		} else if err != nil {
			die("%v", err)
		}
	},
}

func aoeAction(cmd *cobra.Command, args []string) error {
	if len(args) != 4 {
		return torus.ErrUsage
	}

	srv := createServer()
	defer srv.Close()

	vol := args[0]
	ifname := args[1]
	maj := args[2]
	min := args[3]

	major, err := strconv.ParseUint(maj, 10, 16)
	if err != nil {
		return fmt.Errorf("Failed to parse major address %q: %v", maj, err)
	}

	minor, err := strconv.ParseUint(min, 10, 8)
	if err != nil {
		return fmt.Errorf("Failed to parse minor address %q: %v", min, err)
	}

	blockvol, err := block.OpenBlockVolume(srv, vol)
	if err != nil {
		return fmt.Errorf("server doesn't support block volumes: %v", err)
	}

	ai, err := aoe.NewInterface(ifname)
	if err != nil {
		return fmt.Errorf("Failed to set up interface %q: %v", ifname, err)
	}

	as, err := aoe.NewServer(blockvol, &aoe.ServerOptions{
		Major: uint16(major),
		Minor: uint8(minor),
	})
	if err != nil {
		return fmt.Errorf("Failed to crate AoE server: %v", err)
	}
	defer as.Close()

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)

	go func(iface *aoe.Interface) {
		for _ = range signalChan {
			fmt.Println("\nReceived an interrupt, stopping services...")
			iface.Close()
		}
	}(ai)

	if err = as.Serve(ai); err != nil {
		return fmt.Errorf("Failed to serve AoE: %v", err)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"strings"
	"sync"

	"github.com/datawire/ambassador/pkg/supervisor"
	"github.com/datawire/ambassador/pkg/tpu"
)

type invoker struct {
	Snapshots        chan string
	mux              sync.Mutex
	invokedSnapshots map[int]string
	id               int
	notify           []string
	apiServerPort    int

	// This stores the latest snapshot, but we don't assign an id
	// unless/until we invoke... some of these will be discarded
	// by the rate limiting/coalescing logic
	latestSnapshot string
	process        *supervisor.Process
}

func NewInvoker(port int, notify []string) *invoker {
	return &invoker{
		Snapshots:        make(chan string),
		invokedSnapshots: make(map[int]string),
		notify:           notify,
		apiServerPort:    port,
	}
}

func (a *invoker) Work(p *supervisor.Process) error {
	a.process = p
	p.Ready()

	invoking := make(chan string)

	go func() {
		for snapshot := range invoking {
			// ignore empty snapshots to deal with the
			// corner case where we haven't yet received a
			// snapshot
			if snapshot != "" {
				a.latestSnapshot = snapshot
				a.invoke()
			}
		}
	}()

	potentialSnapshot := ""

	for {
		select {
		case potentialSnapshot = <-a.Snapshots:
			// if a new snapshot is available to be read,
			// and we can't write to the invoking channel,
			// then we will overwrite potentialSnapshot
			// with a newer snapshot
		case invoking <- potentialSnapshot:
			// if we aren't currently blocked in
			// a.invoke() then the above goroutine will be
			// reading from the invoking channel and we
			// will send the current potentialSnapshot
			// value over the invoking channel to be
			// processed

			select {
			case potentialSnapshot = <-a.Snapshots:
				// whenever we write a
				// potentialSnapshot to invoking, we
				// also need to do a synchronous read
				// from a.Snapshots to make sure we
				// won't ever invoke the same snapshot
				// twice
			case <-p.Shutdown():
				p.Logf("shutdown initiated")
				return nil
			}
		case <-p.Shutdown():
			p.Logf("shutdown initiated")
			return nil
		}
	}
}

func (a *invoker) storeSnapshot(snapshot string) int {
	a.mux.Lock()
	defer a.mux.Unlock()
	a.id += 1
	a.invokedSnapshots[a.id] = snapshot
	a.gcSnapshots()
	return a.id
}

func (a *invoker) gcSnapshots() {
	for k := range a.invokedSnapshots {
		if k <= a.id-10 {
			delete(a.invokedSnapshots, k)
			a.process.Logf("deleting snapshot %d", k)
		}
	}
}

func (a *invoker) getSnapshot(id int) string {
	a.mux.Lock()
	defer a.mux.Unlock()
	return a.invokedSnapshots[id]
}

func (a *invoker) getKeys() (result []int) {
	for i := range a.invokedSnapshots {
		result = append(result, i)
	}
	return
}

func (a *invoker) invoke() {
	id := a.storeSnapshot(a.latestSnapshot)
	for _, n := range a.notify {
		k := tpu.NewKeeper("notify", fmt.Sprintf("%s http://localhost:%d/snapshots/%d", n, a.apiServerPort, id))
		k.Limit = 1
		k.Start()
		k.Wait()
	}
}

type apiServer struct {
	port    int
	invoker *invoker
}

func (s *apiServer) Work(p *supervisor.Process) error {
	http.HandleFunc("/snapshots/", func(w http.ResponseWriter, r *http.Request) {
		relpath := strings.TrimPrefix(r.URL.Path, "/snapshots/")

		if relpath == "" {
			w.Header().Set("content-type", "text/html")
			if _, err := w.Write([]byte(s.index())); err != nil {
				p.Logf("write index error: %v", err)
			}
		} else {
			id, err := strconv.Atoi(relpath)
			if err != nil {
				http.Error(w, "ID is not an integer", http.StatusBadRequest)
				return
			}

			snapshot := s.invoker.getSnapshot(id)

			if snapshot == "" {
				w.WriteHeader(http.StatusNotFound)
				return
			}

			w.Header().Set("content-type", "application/json")
			if _, err := w.Write([]byte(snapshot)); err != nil {
				p.Logf("write snapshot error: %v", err)
			}
		}
	})

	listenHostAndPort := fmt.Sprintf(":%d", s.port)
	listener, err := net.Listen("tcp", listenHostAndPort)
	if err != nil {
		return err
	}
	p.Ready()
	p.Logf("snapshot server listening on: %s", listenHostAndPort)
	srv := &http.Server{
		Addr: listenHostAndPort,
	}
	return p.DoClean(func() error {
		err := srv.Serve(listener)
		if err == http.ErrServerClosed {
			return nil
		}
		return err
	},
		func() error {
			return srv.Shutdown(p.Context())
		})

}

func (s *apiServer) index() string {
	var result strings.Builder

	result.WriteString("
\n")

	for _, v := range s.invoker.getKeys() {
		result.WriteString(fmt.Sprintf("
%d
\n", v, v))
	}

	result.WriteString("
\n")

	return result.String()
}
<commit_msg>added more comments<commit_after>package main

import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"strings"
	"sync"

	"github.com/datawire/ambassador/pkg/supervisor"
	"github.com/datawire/ambassador/pkg/tpu"
)

type invoker struct {
	Snapshots        chan string
	mux              sync.Mutex
	invokedSnapshots map[int]string
	id               int
	notify           []string
	apiServerPort    int

	// This stores the latest snapshot, but we don't assign an id
	// unless/until we invoke... some of these will be discarded
	// by the rate limiting/coalescing logic
	latestSnapshot string
	process        *supervisor.Process
}

func NewInvoker(port int, notify []string) *invoker {
	return &invoker{
		Snapshots:        make(chan string),
		invokedSnapshots: make(map[int]string),
		notify:           notify,
		apiServerPort:    port,
	}
}

func (a *invoker) Work(p *supervisor.Process) error {
	// The general strategy here is:
	//
	// 1. Be continuously reading all available snapshots from
	//    a.Snapshots and store them in the potentialSnapshot
	//    variable. This means at any given point (modulo caveats
	//    below), the potentialSnapshot variable will have the
	//    latest and greatest snapshot available.
	//
	// 2. At the same time, whenever there is capacity to write
	//    down the invoking channel, we send potentialSnapshot to
	//    be invoked.
	//
	//    The anonymous goroutine below will be constantly reading
	//    from the invoking channel and performing a blocking
	//    a.invoke(). This means that we can only *write* to the
	//    invoking channel when we are not currently processing a
	//    snapshot, but when that happens, we will still read from
	//    a.Snapshots and update potentialSnapshot.
	//
	// There are two caveats to the above:
	//
	// 1. At startup, we don't yet have a snapshot to write, but
	//    we're not invoking anything, so we will try to write
	//    something down the invoking channel. To cope with this,
	//    the invoking goroutine will ignore snapshots that
	//    consist of the empty string.
	//
	// 2. If we process a snapshot quickly, or if there aren't new
	//    snapshots available, then we end up busy looping and
	//    sending the same potentialSnapshot value down the
	//    invoking channel multiple times. To cope with this,
	//    whenever we have successfully written to the invoking
	//    channel, we do a *blocking* read of the next snapshot
	//    from a.Snapshots.

	a.process = p
	p.Ready()

	invoking := make(chan string)

	go func() {
		for snapshot := range invoking {
			// ignore empty snapshots to deal with the
			// corner case where we haven't yet received a
			// snapshot
			if snapshot != "" {
				a.latestSnapshot = snapshot
				a.invoke()
			}
		}
	}()

	potentialSnapshot := ""

	for {
		select {
		case potentialSnapshot = <-a.Snapshots:
			// if a new snapshot is available to be read,
			// and we can't write to the invoking channel,
			// then we will overwrite potentialSnapshot
			// with a newer snapshot
		case invoking <- potentialSnapshot:
			// if we aren't currently blocked in
			// a.invoke() then the above goroutine will be
			// reading from the invoking channel and we
			// will send the current potentialSnapshot
			// value over the invoking channel to be
			// processed

			select {
			case potentialSnapshot = <-a.Snapshots:
				// whenever we write a
				// potentialSnapshot to invoking, we
				// also need to do a synchronous read
				// from a.Snapshots to make sure we
				// won't ever invoke the same snapshot
				// twice
			case <-p.Shutdown():
				p.Logf("shutdown initiated")
				return nil
			}
		case <-p.Shutdown():
			p.Logf("shutdown initiated")
			return nil
		}
	}
}

func (a *invoker) storeSnapshot(snapshot string) int {
	a.mux.Lock()
	defer a.mux.Unlock()
	a.id += 1
	a.invokedSnapshots[a.id] = snapshot
	a.gcSnapshots()
	return a.id
}

func (a *invoker) gcSnapshots() {
	for k := range a.invokedSnapshots {
		if k <= a.id-10 {
			delete(a.invokedSnapshots, k)
			a.process.Logf("deleting snapshot %d", k)
		}
	}
}

func (a *invoker) getSnapshot(id int) string {
	a.mux.Lock()
	defer a.mux.Unlock()
	return a.invokedSnapshots[id]
}

func (a *invoker) getKeys() (result []int) {
	for i := range a.invokedSnapshots {
		result = append(result, i)
	}
	return
}

func (a *invoker) invoke() {
	id := a.storeSnapshot(a.latestSnapshot)
	for _, n := range a.notify {
		k := tpu.NewKeeper("notify", fmt.Sprintf("%s http://localhost:%d/snapshots/%d", n, a.apiServerPort, id))
		k.Limit = 1
		k.Start()
		k.Wait()
	}
}

type apiServer struct {
	port    int
	invoker *invoker
}

func (s *apiServer) Work(p *supervisor.Process) error {
	http.HandleFunc("/snapshots/", func(w http.ResponseWriter, r *http.Request) {
		relpath := strings.TrimPrefix(r.URL.Path, "/snapshots/")

		if relpath == "" {
			w.Header().Set("content-type", "text/html")
			if _, err := w.Write([]byte(s.index())); err != nil {
				p.Logf("write index error: %v", err)
			}
		} else {
			id, err := strconv.Atoi(relpath)
			if err != nil {
				http.Error(w, "ID is not an integer", http.StatusBadRequest)
				return
			}

			snapshot := s.invoker.getSnapshot(id)

			if snapshot == "" {
				w.WriteHeader(http.StatusNotFound)
				return
			}

			w.Header().Set("content-type", "application/json")
			if _, err := w.Write([]byte(snapshot)); err != nil {
				p.Logf("write snapshot error: %v", err)
			}
		}
	})

	listenHostAndPort := fmt.Sprintf(":%d", s.port)
	listener, err := net.Listen("tcp", listenHostAndPort)
	if err != nil {
		return err
	}
	p.Ready()
	p.Logf("snapshot server listening on: %s", listenHostAndPort)
	srv := &http.Server{
		Addr: listenHostAndPort,
	}
	return p.DoClean(func() error {
		err := srv.Serve(listener)
		if err == http.ErrServerClosed {
			return nil
		}
		return err
	},
		func() error {
			return srv.Shutdown(p.Context())
		})

}

func (s *apiServer) index() string {
	var result strings.Builder

	result.WriteString("
\n")

	for _, v := range s.invoker.getKeys() {
		result.WriteString(fmt.Sprintf("
%d
\n", v, v))
	}

	result.WriteString("
\n")

	return result.String()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"os"
	path "path/filepath"
	"strings"
)

const tplMainGo = `package main

import (
   "log"
   "runtime"

   "github.com/labstack/echo"
   "github.com/labstack/echo/engine/standard"
   "github.com/labstack/echo/middleware"
   "github.com/trumae/valente"
	 "{{ . }}"

   "golang.org/x/net/websocket"
)

//App is a Web Application representation
type App struct {
    valente.App
}

//Initialize inits the App
func (app *App) Initialize() {
    log.Println("App Initialize")

    app.AddForm("login", forms.FormLogin{})
    app.AddForm("home", forms.FormHome{})

    app.GoTo("login", nil)
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())

    e := echo.New()

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Use(middleware.Static("public"))

    e.Get("/ws", standard.WrapHandler(websocket.Handler(func(ws *websocket.Conn) {
       app := App{}
       app.WS = ws
       app.Initialize()
       app.Run()
    })))

		log.Println("Server running")
    e.Run(standard.New(":8000"))
}

`

func createApp(name string) {
	curpath, _ := os.Getwd()
	log.Println("current path:", curpath)
	gopath := os.Getenv("GOPATH")
	log.Println("gopath:", gopath)
	if gopath == "" {
		log.Println("[ERRO] $GOPATH not found")
		log.Println("[HINT] Set $GOPATH in your environment vairables")
		os.Exit(2)
	}

	haspath := false
	appsrcpath := ""

	wgopath := path.SplitList(gopath)
	for _, wg := range wgopath {

		wg = path.Join(wg, "src")

		if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
			haspath = true
			appsrcpath = wg
			break
		}

		wg, _ = path.EvalSymlinks(wg)

		if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
			haspath = true
			appsrcpath = wg
			break
		}

	}

	if !haspath {
		log.Printf("[ERRO] Unable to create an application outside of $GOPATH%ssrc(%s%ssrc)\n", string(path.Separator), gopath, string(path.Separator))
		log.Printf("[HINT] Change your work directory by `cd ($GOPATH%ssrc)`\n", string(path.Separator))
		os.Exit(2)
	}

	apppath := path.Join(curpath, name)

	if isExist(apppath) {
		log.Printf("[ERRO] Path (%s) already exists\n", apppath)
		log.Printf("[WARN] Do you want to overwrite it? [yes|no]]")
		if !askForConfirmation() {
			os.Exit(2)
		}
	}
	pathToValente := path.Join(appsrcpath, "github.com", "trumae", "valente")
	pathToValenteData := path.Join(pathToValente, "data")
	pathToValenteDataPublic := path.Join(pathToValenteData, "public")
	pathToValenteDataForms := path.Join(pathToValenteData, "forms")

	log.Println("Creating application ...")

	os.MkdirAll(apppath, 0755)
	fmt.Println(apppath + string(path.Separator))

	copyDir(pathToValenteDataPublic, path.Join(apppath, "public"))
	copyDir(pathToValenteDataForms, path.Join(apppath, "forms"))

	packageForms := path.Join(apppath[len(appsrcpath)+1:], "forms")

	tmpl, err := template.New("forms").Parse(tplMainGo)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	err = tmpl.Execute(buf, packageForms)
	if err != nil {
		panic(err)
	}
	writetofile(path.Join(apppath, "main.go"), buf.String())

}
<commit_msg>info on new<commit_after>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"os"
	path "path/filepath"
	"strings"
)

const tplMainGo = `package main

import (
   "log"
   "runtime"

   "github.com/labstack/echo"
   "github.com/labstack/echo/engine/standard"
   "github.com/labstack/echo/middleware"
   "github.com/trumae/valente"
   "github.com/trumae/valente/status"
	 "{{ . }}"

   "golang.org/x/net/websocket"
)

//App is a Web Application representation
type App struct {
    valente.App
}

//Initialize inits the App
func (app *App) Initialize() {
    log.Println("App Initialize")

    app.AddForm("login", forms.FormLogin{})
    app.AddForm("home", forms.FormHome{})

    app.GoTo("login", nil)
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())

    e := echo.New()

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Use(middleware.Static("public"))

    e.GET("/status", status.ValenteStatusHandler)
    e.GET("/ws", standard.WrapHandler(websocket.Handler(func(ws *websocket.Conn) {
       app := App{}
       app.WS = ws
       app.Initialize()
       app.Run()
    })))

		log.Println("Server running")
    e.Run(standard.New(":8000"))
}

`

func createApp(name string) {
	curpath, _ := os.Getwd()
	log.Println("current path:", curpath)
	gopath := os.Getenv("GOPATH")
	log.Println("gopath:", gopath)
	if gopath == "" {
		log.Println("[ERRO] $GOPATH not found")
		log.Println("[HINT] Set $GOPATH in your environment vairables")
		os.Exit(2)
	}

	haspath := false
	appsrcpath := ""

	wgopath := path.SplitList(gopath)
	for _, wg := range wgopath {

		wg = path.Join(wg, "src")

		if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
			haspath = true
			appsrcpath = wg
			break
		}

		wg, _ = path.EvalSymlinks(wg)

		if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
			haspath = true
			appsrcpath = wg
			break
		}

	}

	if !haspath {
		log.Printf("[ERRO] Unable to create an application outside of $GOPATH%ssrc(%s%ssrc)\n", string(path.Separator), gopath, string(path.Separator))
		log.Printf("[HINT] Change your work directory by `cd ($GOPATH%ssrc)`\n", string(path.Separator))
		os.Exit(2)
	}

	apppath := path.Join(curpath, name)

	if isExist(apppath) {
		log.Printf("[ERRO] Path (%s) already exists\n", apppath)
		log.Printf("[WARN] Do you want to overwrite it? [yes|no]]")
		if !askForConfirmation() {
			os.Exit(2)
		}
	}
	pathToValente := path.Join(appsrcpath, "github.com", "trumae", "valente")
	pathToValenteData := path.Join(pathToValente, "data")
	pathToValenteDataPublic := path.Join(pathToValenteData, "public")
	pathToValenteDataForms := path.Join(pathToValenteData, "forms")

	log.Println("Creating application ...")

	os.MkdirAll(apppath, 0755)
	fmt.Println(apppath + string(path.Separator))

	copyDir(pathToValenteDataPublic, path.Join(apppath, "public"))
	copyDir(pathToValenteDataForms, path.Join(apppath, "forms"))

	packageForms := path.Join(apppath[len(appsrcpath)+1:], "forms")

	tmpl, err := template.New("forms").Parse(tplMainGo)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	err = tmpl.Execute(buf, packageForms)
	if err != nil {
		panic(err)
	}
	writetofile(path.Join(apppath, "main.go"), buf.String())

}
<|endoftext|>