<commit_before>package main_test

import (
	"fmt"
	"syscall"
	"time"

	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/storerunner/etcdstorerunner"
	"github.com/hashicorp/consul/consul/structs"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/pivotal-golang/lager/lagertest"

	"github.com/cloudfoundry-incubator/consuladapter"
	"github.com/cloudfoundry-incubator/converger/converger_runner"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	"github.com/cloudfoundry-incubator/runtime-schema/bbs/shared"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
)

var _ = Describe("Converger", func() {
	const (
		exitDuration = 4 * time.Second
	)

	var (
		etcdRunner *etcdstorerunner.ETCDClusterRunner
		bbs        *Bbs.BBS
		runner     *converger_runner.ConvergerRunner

		consulRunner  *consuladapter.ClusterRunner
		consulAdapter consuladapter.Adapter

		convergeRepeatInterval      time.Duration
		taskKickInterval            time.Duration
		expireCompletedTaskDuration time.Duration

		etcdClient storeadapter.StoreAdapter

		logger lager.Logger
	)

	SynchronizedBeforeSuite(func() []byte {
		convergerBinPath, err := gexec.Build("github.com/cloudfoundry-incubator/converger/cmd/converger", "-race")
		Ω(err).ShouldNot(HaveOccurred())
		return []byte(convergerBinPath)
	}, func(convergerBinPath []byte) {
		etcdPort := 5001 + config.GinkgoConfig.ParallelNode
		etcdCluster := fmt.Sprintf("http://127.0.0.1:%d", etcdPort)
		etcdRunner = etcdstorerunner.NewETCDClusterRunner(etcdPort, 1)

		etcdClient = etcdRunner.Adapter()

		consulRunner = consuladapter.NewClusterRunner(
			9001+config.GinkgoConfig.ParallelNode*consuladapter.PortOffsetLength,
			1,
			"http",
		)

		logger = lagertest.NewTestLogger("test")

		runner = converger_runner.New(string(convergerBinPath), etcdCluster, consulRunner.ConsulCluster(), "info")
	})

	SynchronizedAfterSuite(func() {
		etcdRunner.Stop()
	}, func() {
		gexec.CleanupBuildArtifacts()
	})

	BeforeEach(func() {
		etcdRunner.Start()
		consulRunner.Start()

		consulAdapter = consulRunner.NewAdapter()
		bbs = Bbs.NewBBS(etcdClient, consulAdapter, "http://receptor.bogus.com", clock.NewClock(), logger)

		capacity := models.NewCellCapacity(512, 1024, 124)
		cellPresence := models.NewCellPresence("the-cell-id", "1.2.3.4", "the-zone", capacity)

		value, err := models.ToJSON(cellPresence)
		Ω(err).ShouldNot(HaveOccurred())

		_, err = consulAdapter.AcquireAndMaintainLock(
			shared.CellSchemaPath(cellPresence.CellID),
			value,
			structs.SessionTTLMin,
			nil)
		Ω(err).ShouldNot(HaveOccurred())

		convergeRepeatInterval = 500 * time.Millisecond
		taskKickInterval = convergeRepeatInterval
		expireCompletedTaskDuration = 3 * convergeRepeatInterval
	})

	AfterEach(func() {
		runner.KillWithFire()
		consulRunner.Stop()
		etcdRunner.Stop()
	})

	startConverger := func() {
		runner.Start(convergeRepeatInterval, taskKickInterval, 30*time.Minute, expireCompletedTaskDuration)
		time.Sleep(convergeRepeatInterval)
	}

	createRunningTaskWithDeadCell := func() {
		task := models.Task{
			Domain: "tests",

			TaskGuid: "task-guid",
			RootFS:   "some:rootfs",
			Action: &models.RunAction{
				Path: "cat",
				Args: []string{"/tmp/file"},
			},
		}

		err := bbs.DesireTask(logger, task)
		Ω(err).ShouldNot(HaveOccurred())

		_, err = bbs.StartTask(logger, task.TaskGuid, "dead-cell")
		Ω(err).ShouldNot(HaveOccurred())
	}

	itIsInactive := func() {
		Describe("when a task is desired but its cell is dead", func() {
			JustBeforeEach(createRunningTaskWithDeadCell)

			It("does not converge the task", func() {
				Consistently(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 5*convergeRepeatInterval).Should(BeEmpty())
			})
		})
	}

	Context("when the converger has the lock", func() {
		Describe("when a task is desired but its cell is dead", func() {
			JustBeforeEach(createRunningTaskWithDeadCell)

			It("marks the task as completed and failed", func() {
				Consistently(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 0.5).Should(BeEmpty())

				startConverger()

				Eventually(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 5*convergeRepeatInterval).Should(HaveLen(1))
			})
		})
	})

	Context("when the converger loses the lock", func() {
		BeforeEach(func() {
			startConverger()
			Eventually(runner.Session, 5*time.Second).Should(gbytes.Say("succeeded-acquiring-lock"))

			consulRunner.Reset()
		})

		It("exits with an error", func() {
			Eventually(runner.Session, exitDuration).Should(gexec.Exit(1))
		})
	})

	Context("when the converger initially does not have the lock", func() {

		BeforeEach(func() {
			_, err := consulAdapter.AcquireAndMaintainLock(
				shared.LockSchemaPath("converge_lock"),
				[]byte("something-else"),
				structs.SessionTTLMin,
				nil)
			Ω(err).ShouldNot(HaveOccurred())

			startConverger()
		})

		itIsInactive()

		Describe("when the lock becomes available", func() {
			BeforeEach(func() {
				err := consulAdapter.ReleaseAndDeleteLock(shared.LockSchemaPath("converge_lock"))
				Ω(err).ShouldNot(HaveOccurred())
				time.Sleep(convergeRepeatInterval + 10*time.Millisecond)
			})

			Describe("when a running task with a dead cell is present", func() {
				JustBeforeEach(createRunningTaskWithDeadCell)

				It("eventually marks the task as failed", func() {
					Eventually(func() ([]models.Task, error) {
						return bbs.CompletedTasks(logger)
					}, 5*convergeRepeatInterval).Should(HaveLen(1))
				})
			})
		})
	})

	Describe("signal handling", func() {
		BeforeEach(func() {
			startConverger()
		})

		Describe("when it receives SIGINT", func() {
			It("exits successfully", func() {
				runner.Session.Command.Process.Signal(syscall.SIGINT)
				Eventually(runner.Session, exitDuration).Should(gexec.Exit(0))
			})
		})

		Describe("when it receives SIGTERM", func() {
			It("exits successfully", func() {
				runner.Session.Command.Process.Signal(syscall.SIGTERM)
				Eventually(runner.Session, exitDuration).Should(gexec.Exit(0))
			})
		})
	})
})
<commit_msg>Specify when to wait for Consul<commit_after>package main_test

import (
	"fmt"
	"syscall"
	"time"

	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/storerunner/etcdstorerunner"
	"github.com/hashicorp/consul/consul/structs"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/pivotal-golang/lager/lagertest"

	"github.com/cloudfoundry-incubator/consuladapter"
	"github.com/cloudfoundry-incubator/converger/converger_runner"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	"github.com/cloudfoundry-incubator/runtime-schema/bbs/shared"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
)

var _ = Describe("Converger", func() {
	const (
		exitDuration = 4 * time.Second
	)

	var (
		etcdRunner *etcdstorerunner.ETCDClusterRunner
		bbs        *Bbs.BBS
		runner     *converger_runner.ConvergerRunner

		consulRunner  *consuladapter.ClusterRunner
		consulAdapter consuladapter.Adapter

		convergeRepeatInterval      time.Duration
		taskKickInterval            time.Duration
		expireCompletedTaskDuration time.Duration

		etcdClient storeadapter.StoreAdapter

		logger lager.Logger
	)

	SynchronizedBeforeSuite(func() []byte {
		convergerBinPath, err := gexec.Build("github.com/cloudfoundry-incubator/converger/cmd/converger", "-race")
		Ω(err).ShouldNot(HaveOccurred())
		return []byte(convergerBinPath)
	}, func(convergerBinPath []byte) {
		etcdPort := 5001 + config.GinkgoConfig.ParallelNode
		etcdCluster := fmt.Sprintf("http://127.0.0.1:%d", etcdPort)
		etcdRunner = etcdstorerunner.NewETCDClusterRunner(etcdPort, 1)

		etcdClient = etcdRunner.Adapter()

		consulRunner = consuladapter.NewClusterRunner(
			9001+config.GinkgoConfig.ParallelNode*consuladapter.PortOffsetLength,
			1,
			"http",
		)

		logger = lagertest.NewTestLogger("test")

		runner = converger_runner.New(string(convergerBinPath), etcdCluster, consulRunner.ConsulCluster(), "info")
	})

	SynchronizedAfterSuite(func() {
		etcdRunner.Stop()
	}, func() {
		gexec.CleanupBuildArtifacts()
	})

	BeforeEach(func() {
		etcdRunner.Start()
		consulRunner.Start()

		consulAdapter = consulRunner.NewAdapter()
		bbs = Bbs.NewBBS(etcdClient, consulAdapter, "http://receptor.bogus.com", clock.NewClock(), logger)

		capacity := models.NewCellCapacity(512, 1024, 124)
		cellPresence := models.NewCellPresence("the-cell-id", "1.2.3.4", "the-zone", capacity)

		value, err := models.ToJSON(cellPresence)
		Ω(err).ShouldNot(HaveOccurred())

		consulRunner.WaitUntilReady()
		_, err = consulAdapter.AcquireAndMaintainLock(
			shared.CellSchemaPath(cellPresence.CellID),
			value,
			structs.SessionTTLMin,
			nil)
		Ω(err).ShouldNot(HaveOccurred())

		convergeRepeatInterval = 500 * time.Millisecond
		taskKickInterval = convergeRepeatInterval
		expireCompletedTaskDuration = 3 * convergeRepeatInterval
	})

	AfterEach(func() {
		runner.KillWithFire()
		consulRunner.Stop()
		etcdRunner.Stop()
	})

	startConverger := func() {
		runner.Start(convergeRepeatInterval, taskKickInterval, 30*time.Minute, expireCompletedTaskDuration)
		time.Sleep(convergeRepeatInterval)
	}

	createRunningTaskWithDeadCell := func() {
		task := models.Task{
			Domain: "tests",

			TaskGuid: "task-guid",
			RootFS:   "some:rootfs",
			Action: &models.RunAction{
				Path: "cat",
				Args: []string{"/tmp/file"},
			},
		}

		err := bbs.DesireTask(logger, task)
		Ω(err).ShouldNot(HaveOccurred())

		_, err = bbs.StartTask(logger, task.TaskGuid, "dead-cell")
		Ω(err).ShouldNot(HaveOccurred())
	}

	itIsInactive := func() {
		Describe("when a task is desired but its cell is dead", func() {
			JustBeforeEach(createRunningTaskWithDeadCell)

			It("does not converge the task", func() {
				Consistently(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 5*convergeRepeatInterval).Should(BeEmpty())
			})
		})
	}

	Context("when the converger has the lock", func() {
		Describe("when a task is desired but its cell is dead", func() {
			JustBeforeEach(createRunningTaskWithDeadCell)

			It("marks the task as completed and failed", func() {
				Consistently(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 0.5).Should(BeEmpty())

				startConverger()

				Eventually(func() ([]models.Task, error) {
					return bbs.CompletedTasks(logger)
				}, 5*convergeRepeatInterval).Should(HaveLen(1))
			})
		})
	})

	Context("when the converger loses the lock", func() {
		BeforeEach(func() {
			startConverger()
			Eventually(runner.Session, 5*time.Second).Should(gbytes.Say("succeeded-acquiring-lock"))

			consulRunner.Reset()
		})

		It("exits with an error", func() {
			Eventually(runner.Session, exitDuration).Should(gexec.Exit(1))
		})
	})

	Context("when the converger initially does not have the lock", func() {

		BeforeEach(func() {
			_, err := consulAdapter.AcquireAndMaintainLock(
				shared.LockSchemaPath("converge_lock"),
				[]byte("something-else"),
				structs.SessionTTLMin,
				nil)
			Ω(err).ShouldNot(HaveOccurred())

			startConverger()
		})

		itIsInactive()

		Describe("when the lock becomes available", func() {
			BeforeEach(func() {
				err := consulAdapter.ReleaseAndDeleteLock(shared.LockSchemaPath("converge_lock"))
				Ω(err).ShouldNot(HaveOccurred())
				time.Sleep(convergeRepeatInterval + 10*time.Millisecond)
			})

			Describe("when a running task with a dead cell is present", func() {
				JustBeforeEach(createRunningTaskWithDeadCell)

				It("eventually marks the task as failed", func() {
					Eventually(func() ([]models.Task, error) {
						return bbs.CompletedTasks(logger)
					}, 5*convergeRepeatInterval).Should(HaveLen(1))
				})
			})
		})
	})

	Describe("signal handling", func() {
		BeforeEach(func() {
			startConverger()
		})

		Describe("when it receives SIGINT", func() {
			It("exits successfully", func() {
				runner.Session.Command.Process.Signal(syscall.SIGINT)
				Eventually(runner.Session, exitDuration).Should(gexec.Exit(0))
			})
		})

		Describe("when it receives SIGTERM", func() {
			It("exits successfully", func() {
				runner.Session.Command.Process.Signal(syscall.SIGTERM)
				Eventually(runner.Session, exitDuration).Should(gexec.Exit(0))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/Symantec/Dominator/lib/constants"
	"github.com/Symantec/Dominator/lib/filegen"
	"github.com/Symantec/Dominator/lib/filegen/httpd"
	"github.com/Symantec/Dominator/lib/logbuf"
	"github.com/Symantec/tricorder/go/tricorder"
	"log"
	"os"
)

var (
	caFile = flag.String("CAfile", "/etc/ssl/CA.pem",
		"Name of file containing the root of trust")
	certFile = flag.String("certFile", "/etc/ssl/filegen-server/cert.pem",
		"Name of file containing the SSL certificate")
	logbufLines = flag.Uint("logbufLines", 1024,
		"Number of lines to store in the log buffer")
	keyFile = flag.String("keyFile", "/etc/ssl/filegen-server/key.pem",
		"Name of file containing the SSL key")
	portNum = flag.Uint("portNum", constants.BasicFileGenServerPortNumber,
		"Port number to allocate and listen on for HTTP/RPC")
)

func printUsage() {
	fmt.Fprintln(os.Stderr,
		"Usage: filegen-server [flags...] directory...")
	fmt.Fprintln(os.Stderr, "Common flags:")
	flag.PrintDefaults()
	fmt.Fprintln(os.Stderr, "directory: tree of source files")
}

func main() {
	flag.Usage = printUsage
	flag.Parse()
	tricorder.RegisterFlags()
	if os.Geteuid() == 0 {
		fmt.Fprintln(os.Stderr, "Do not run the filegen server as root")
		os.Exit(1)
	}
	setupTls(*caFile, *certFile, *keyFile)
	circularBuffer := logbuf.New(*logbufLines)
	logger := log.New(circularBuffer, "", log.LstdFlags)
	manager := filegen.New(logger)
	httpd.AddHtmlWriter(manager)
	for _, pathname := range flag.Args() {
		if err := registerSourceDirectory(manager, pathname, "/"); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}
	if err := httpd.StartServer(*portNum, manager, false); err != nil {
		fmt.Fprintf(os.Stderr, "Unable to create http server\t%s\n", err)
		os.Exit(1)
	}
}
<commit_msg>Show logs on main status page of filegen-server.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/Symantec/Dominator/lib/constants"
	"github.com/Symantec/Dominator/lib/filegen"
	"github.com/Symantec/Dominator/lib/filegen/httpd"
	"github.com/Symantec/Dominator/lib/logbuf"
	"github.com/Symantec/tricorder/go/tricorder"
	"log"
	"os"
)

var (
	caFile = flag.String("CAfile", "/etc/ssl/CA.pem",
		"Name of file containing the root of trust")
	certFile = flag.String("certFile", "/etc/ssl/filegen-server/cert.pem",
		"Name of file containing the SSL certificate")
	logbufLines = flag.Uint("logbufLines", 1024,
		"Number of lines to store in the log buffer")
	keyFile = flag.String("keyFile", "/etc/ssl/filegen-server/key.pem",
		"Name of file containing the SSL key")
	portNum = flag.Uint("portNum", constants.BasicFileGenServerPortNumber,
		"Port number to allocate and listen on for HTTP/RPC")
)

func printUsage() {
	fmt.Fprintln(os.Stderr,
		"Usage: filegen-server [flags...] directory...")
	fmt.Fprintln(os.Stderr, "Common flags:")
	flag.PrintDefaults()
	fmt.Fprintln(os.Stderr, "directory: tree of source files")
}

func main() {
	flag.Usage = printUsage
	flag.Parse()
	tricorder.RegisterFlags()
	if os.Geteuid() == 0 {
		fmt.Fprintln(os.Stderr, "Do not run the filegen server as root")
		os.Exit(1)
	}
	setupTls(*caFile, *certFile, *keyFile)
	circularBuffer := logbuf.New(*logbufLines)
	logger := log.New(circularBuffer, "", log.LstdFlags)
	manager := filegen.New(logger)
	httpd.AddHtmlWriter(manager)
	httpd.AddHtmlWriter(circularBuffer)
	for _, pathname := range flag.Args() {
		if err := registerSourceDirectory(manager, pathname, "/"); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}
	if err := httpd.StartServer(*portNum, manager, false); err != nil {
		fmt.Fprintf(os.Stderr, "Unable to create http server\t%s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"compress/flate"
	"fmt"
	"gnd.la/admin"
	"gnd.la/mux"
	"go/build"
	"go/format"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func MakeAssets(ctx *mux.Context) {
	var dir string
	var name string
	extensions := map[string]struct{}{
		".html": struct{}{},
		".css":  struct{}{},
		".js":   struct{}{},
	}
	ctx.ParseParamValue("dir", &dir)
	if dir == "" {
		fmt.Fprintf(os.Stderr, "dir can't be empty\n")
		return
	}
	ctx.ParseParamValue("name", &name)
	if name == "" {
		fmt.Fprintf(os.Stderr, "name can't be empty\n")
		return
	}
	var exts string
	ctx.ParseParamValue("extensions", &exts)
	if exts != "" {
		for _, v := range strings.Split(exts, ",") {
			e := strings.ToLower(strings.TrimSpace(v))
			if e != "" {
				if e[0] != '.' {
					e = "." + e
				}
				extensions[e] = struct{}{}
			}
		}
	}
	var out string
	ctx.ParseParamValue("out", &out)
	var useFlate bool
	ctx.ParseParamValue("flate", &useFlate)
	var buf bytes.Buffer
	if out != "" {
		// Try to guess package name. Do it before writing the file, otherwise the package becomes invalid.
		odir := filepath.Dir(out)
		p, err := build.ImportDir(odir, 0)
		if err == nil {
			buf.WriteString(fmt.Sprintf("package %s\n", p.Name))
		}
	}
	buf.WriteString("import \"gnd.la/loaders\"\n")
	buf.WriteString(fmt.Sprintf("// AUTOMATICALLY GENERATED WITH %s. DO NOT EDIT!\n", strings.Join(os.Args, " ")))
	if useFlate {
		buf.WriteString(fmt.Sprintf("var %s = loaders.FlateLoader(loaders.MapLoader(map[string][]byte{\n", name))
	} else {
		buf.WriteString(fmt.Sprintf("var %s = loaders.MapLoader(map[string][]byte{\n", name))
	}
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.Mode().IsRegular() {
			if _, ok := extensions[strings.ToLower(filepath.Ext(path))]; ok {
				contents, err := ioutil.ReadFile(path)
				if err != nil {
					return fmt.Errorf("error reading %s: %s", path, err)
				}
				if useFlate {
					var cbuf bytes.Buffer
					w, err := flate.NewWriter(&cbuf, flate.BestCompression)
					if err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					if _, err := w.Write(contents); err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					if err := w.Close(); err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					contents = cbuf.Bytes()
				}
				rel := path[len(dir):]
				if rel[0] == '/' {
					rel = rel[1:]
				}
				buf.WriteString(fmt.Sprintf("%q", rel))
				buf.WriteByte(':')
				buf.WriteString(" []byte{")
				for ii, v := range contents {
					buf.WriteString(fmt.Sprintf("0x%02X", v))
					buf.WriteByte(',')
					if ii%8 == 0 {
						buf.WriteByte('\n')
					}
				}
				buf.Truncate(buf.Len() - 1)
				buf.WriteString("},\n")
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}
	buf.WriteString("})")
	if useFlate {
		buf.WriteString(")")
	}
	buf.WriteString("\n")
	b, err := format.Source(buf.Bytes())
	if err != nil {
		panic(err)
	}
	var w io.Writer
	if out != "" {
		flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
		var force bool
		ctx.ParseParamValue("f", &force)
		if !force {
			flags |= os.O_EXCL
		}
		f, err := os.OpenFile(out, flags, 0644)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error creating output file %q: %s\n", out, err)
			return
		}
		defer f.Close()
		w = f
	} else {
		w = os.Stdout
	}
	_, err = w.Write(b)
	if err != nil {
		panic(err)
	}
}

func init() {
	admin.Register(MakeAssets, &admin.Options{
		Help: "Converts all assets in <dir> into Go code and generates a Loader named with <name>",
		Flags: admin.Flags(
			admin.StringFlag("dir", "", "Directory with the html templates"),
			admin.StringFlag("name", "", "Name of the generated MapLoader"),
			admin.StringFlag("out", "", "Output filename. If empty, output is printed to standard output"),
			admin.BoolFlag("flate", false, "Compress resources with flate when generating the code"),
			admin.BoolFlag("f", false, "When creating the output file, overwrite any existing file with the same name"),
			admin.StringFlag("extensions", "", "Additional extensions (besides html, css and js) to include, separated by commas"),
		),
	})
}
<commit_msg>Use util.WriteFile to write the assets file.<commit_after>package main

import (
	"bytes"
	"compress/flate"
	"fmt"
	"gnd.la/admin"
	"gnd.la/mux"
	"gnd.la/util"
	"go/build"
	"go/format"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func MakeAssets(ctx *mux.Context) {
	var dir string
	var name string
	extensions := map[string]struct{}{
		".html": struct{}{},
		".css":  struct{}{},
		".js":   struct{}{},
	}
	ctx.ParseParamValue("dir", &dir)
	if dir == "" {
		fmt.Fprintf(os.Stderr, "dir can't be empty\n")
		return
	}
	ctx.ParseParamValue("name", &name)
	if name == "" {
		fmt.Fprintf(os.Stderr, "name can't be empty\n")
		return
	}
	var exts string
	ctx.ParseParamValue("extensions", &exts)
	if exts != "" {
		for _, v := range strings.Split(exts, ",") {
			e := strings.ToLower(strings.TrimSpace(v))
			if e != "" {
				if e[0] != '.' {
					e = "." + e
				}
				extensions[e] = struct{}{}
			}
		}
	}
	var out string
	ctx.ParseParamValue("out", &out)
	var useFlate bool
	ctx.ParseParamValue("flate", &useFlate)
	var buf bytes.Buffer
	if out != "" {
		// Try to guess package name. Do it before writing the file, otherwise the package becomes invalid.
		odir := filepath.Dir(out)
		p, err := build.ImportDir(odir, 0)
		if err == nil {
			buf.WriteString(fmt.Sprintf("package %s\n", p.Name))
		}
	}
	buf.WriteString("import \"gnd.la/loaders\"\n")
	buf.WriteString(fmt.Sprintf("// AUTOMATICALLY GENERATED WITH %s. DO NOT EDIT!\n", strings.Join(os.Args, " ")))
	if useFlate {
		buf.WriteString(fmt.Sprintf("var %s = loaders.FlateLoader(loaders.MapLoader(map[string][]byte{\n", name))
	} else {
		buf.WriteString(fmt.Sprintf("var %s = loaders.MapLoader(map[string][]byte{\n", name))
	}
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.Mode().IsRegular() {
			if _, ok := extensions[strings.ToLower(filepath.Ext(path))]; ok {
				contents, err := ioutil.ReadFile(path)
				if err != nil {
					return fmt.Errorf("error reading %s: %s", path, err)
				}
				if useFlate {
					var cbuf bytes.Buffer
					w, err := flate.NewWriter(&cbuf, flate.BestCompression)
					if err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					if _, err := w.Write(contents); err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					if err := w.Close(); err != nil {
						return fmt.Errorf("error compressing %s: %s", path, err)
					}
					contents = cbuf.Bytes()
				}
				rel := path[len(dir):]
				if rel[0] == '/' {
					rel = rel[1:]
				}
				buf.WriteString(fmt.Sprintf("%q", rel))
				buf.WriteByte(':')
				buf.WriteString(" []byte{")
				for ii, v := range contents {
					buf.WriteString(fmt.Sprintf("0x%02X", v))
					buf.WriteByte(',')
					if ii%8 == 0 {
						buf.WriteByte('\n')
					}
				}
				buf.Truncate(buf.Len() - 1)
				buf.WriteString("},\n")
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}
	buf.WriteString("})")
	if useFlate {
		buf.WriteString(")")
	}
	buf.WriteString("\n")
	b, err := format.Source(buf.Bytes())
	if err != nil {
		panic(err)
	}
	var force bool
	ctx.ParseParamValue("f", &force)
	if err := util.WriteFile(out, b, force, 0644); err != nil {
		panic(err)
	}
}

func init() {
	admin.Register(MakeAssets, &admin.Options{
		Help: "Converts all assets in <dir> into Go code and generates a Loader named with <name>",
		Flags: admin.Flags(
			admin.StringFlag("dir", "", "Directory with the html templates"),
			admin.StringFlag("name", "", "Name of the generated MapLoader"),
			admin.StringFlag("out", "", "Output filename. If empty, output is printed to standard output"),
			admin.BoolFlag("flate", false, "Compress resources with flate when generating the code"),
			admin.BoolFlag("f", false, "When creating the output file, overwrite any existing file with the same name"),
			admin.StringFlag("extensions", "", "Additional extensions (besides html, css and js) to include, separated by commas"),
		),
	})
}
<|endoftext|>


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

// Command issuelock locks Github issues.
package main

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
)

func main() {
	tokenFile := filepath.Join(os.Getenv("HOME"), "keys", "github-gobot")
	slurp, err := ioutil.ReadFile(tokenFile)
	if err != nil {
		log.Fatal(err)
	}
	f := strings.SplitN(strings.TrimSpace(string(slurp)), ":", 2)
	if len(f) != 2 || f[0] == "" || f[1] == "" {
		log.Fatalf("Expected token file %s to be of form <username>:<token>", tokenFile)
	}
	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: f[1]})
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	tooOld := time.Now().Add(-365 * 24 * time.Hour).Format("2006-01-02")
	log.Printf("Freezing closed issues before %v", tooOld)
	for {
		result, response, err := client.Search.Issues("repo:golang/go is:closed -label:FrozenDueToAge updated:<="+tooOld, &github.SearchOptions{
			Sort:  "created",
			Order: "asc",
			ListOptions: github.ListOptions{
				PerPage: 500,
			},
		})
		if err != nil {
			log.Fatal(err)
		}

		if *result.Total == 0 {
			return
		}
		log.Printf("Matches: %d, Res: %#v", *result.Total, response)
		for _, is := range result.Issues {
			num := *is.Number
			log.Printf("Freezing issue: %d", *is.Number)
			if err := freeze(client, num); err != nil {
				log.Fatal(err)
			}
			time.Sleep(500 * time.Millisecond) // be nice to github
		}
	}
}

func freeze(client *github.Client, issueNum int) error {
	_, err := client.Issues.Lock("golang", "go", issueNum)
	if err != nil {
		return err
	}
	_, _, err = client.Issues.AddLabelsToIssue("golang", "go", issueNum, []string{"FrozenDueToAge"})
	return err
}
<commit_msg>cmd/issuelock: support locking a specific issue<commit_after>// Copyright 2016 The 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.

// Command issuelock locks Github issues.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: issuelock [<issue>]\n")
	flag.PrintDefaults()
	os.Exit(1)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	tokenFile := filepath.Join(os.Getenv("HOME"), "keys", "github-gobot")
	slurp, err := ioutil.ReadFile(tokenFile)
	if err != nil {
		log.Fatal(err)
	}
	f := strings.SplitN(strings.TrimSpace(string(slurp)), ":", 2)
	if len(f) != 2 || f[0] == "" || f[1] == "" {
		log.Fatalf("Expected token file %s to be of form <username>:<token>", tokenFile)
	}
	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: f[1]})
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	if flag.NArg() == 1 {
		issueNum, err := strconv.Atoi(flag.Arg(0))
		if err != nil {
			usage()
		}
		if err := freeze(client, issueNum); err != nil {
			log.Fatal(err)
		}
		return
	}
	if flag.NArg() > 1 {
		usage()
	}

	tooOld := time.Now().Add(-365 * 24 * time.Hour).Format("2006-01-02")
	log.Printf("Freezing closed issues before %v", tooOld)
	for {
		result, response, err := client.Search.Issues("repo:golang/go is:closed -label:FrozenDueToAge updated:<="+tooOld, &github.SearchOptions{
			Sort:  "created",
			Order: "asc",
			ListOptions: github.ListOptions{
				PerPage: 500,
			},
		})
		if err != nil {
			log.Fatal(err)
		}

		if *result.Total == 0 {
			return
		}
		log.Printf("Matches: %d, Res: %#v", *result.Total, response)
		for _, is := range result.Issues {
			num := *is.Number
			log.Printf("Freezing issue: %d", *is.Number)
			if err := freeze(client, num); err != nil {
				log.Fatal(err)
			}
			time.Sleep(500 * time.Millisecond) // be nice to github
		}
	}
}

func freeze(client *github.Client, issueNum int) error {
	_, err := client.Issues.Lock("golang", "go", issueNum)
	if err != nil {
		return err
	}
	_, _, err = client.Issues.AddLabelsToIssue("golang", "go", issueNum, []string{"FrozenDueToAge"})
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"

	"github.com/openshift/origin/pkg/test/ginkgo"

	_ "github.com/openshift/origin/test/extended"
)

// staticSuites are all known test suites this binary should run
var staticSuites = []*ginkgo.TestSuite{
	{
		Name: "openshift/conformance",
		Description: templates.LongDesc(`
		Tests that ensure an OpenShift cluster and components are working properly.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/")
		},
		Parallelism: 30,
	},
	{
		Name: "openshift/conformance/parallel",
		Description: templates.LongDesc(`
		Only the portion of the openshift/conformance test suite that run in parallel.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/parallel")
		},
		Parallelism:          30,
		MaximumAllowedFlakes: 5,
	},
	{
		Name: "openshift/conformance/serial",
		Description: templates.LongDesc(`
		Only the portion of the openshift/conformance test suite that run serially.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/serial")
		},
	},
	{
		Name: "kubernetes/conformance",
		Description: templates.LongDesc(`
		The default Kubernetes conformance suite.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:k8s]") && strings.Contains(name, "[Conformance]")
		},
		Parallelism: 30,
	},
	{
		Name: "openshift/build",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift build functionality.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Feature:Builds]")
		},
		Parallelism: 7,
		// TODO: Builds are really flaky right now, remove when we land perf updates and fix io on workers
		MaximumAllowedFlakes: 3,
		// Jenkins tests can take a really long time
		TestTimeout: 60 * time.Minute,
	},
	{
		Name: "openshift/image-registry",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift image-registry functionality.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[registry]") && !strings.Contains(name, "[Local]")
		},
	},
	{
		Name: "openshift/image-ecosystem",
		Description: templates.LongDesc(`
		Tests that exercise language and tooling images shipped as part of OpenShift.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[image_ecosystem]") && !strings.Contains(name, "[Local]")
		},
		Parallelism: 7,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/jenkins-e2e",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift / Jenkins integrations provided by the OpenShift Jenkins image/plugins and the Pipeline Build Strategy.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "openshift pipeline")
		},
		Parallelism: 3,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/scalability",
		Description: templates.LongDesc(`
		Tests that verify the scalability characteristics of the cluster. Currently this is focused on core performance behaviors and preventing regressions.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/scalability]")
		},
		Parallelism: 1,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/conformance-excluded",
		Description: templates.LongDesc(`
		Run only tests that are excluded from conformance. Makes identifying omitted tests easier.
		`),
		Matches: func(name string) bool { return !strings.Contains(name, "[Suite:openshift/conformance/") },
	},
	{
		Name: "all",
		Description: templates.LongDesc(`
		Run all tests.
		`),
		Matches: func(name string) bool { return true },
	},
}
<commit_msg>Bump allowed flake number for openshift/conformance/parallel to 15<commit_after>package main

import (
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"

	"github.com/openshift/origin/pkg/test/ginkgo"

	_ "github.com/openshift/origin/test/extended"
)

// staticSuites are all known test suites this binary should run
var staticSuites = []*ginkgo.TestSuite{
	{
		Name: "openshift/conformance",
		Description: templates.LongDesc(`
		Tests that ensure an OpenShift cluster and components are working properly.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/")
		},
		Parallelism: 30,
	},
	{
		Name: "openshift/conformance/parallel",
		Description: templates.LongDesc(`
		Only the portion of the openshift/conformance test suite that run in parallel.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/parallel")
		},
		Parallelism:          30,
		MaximumAllowedFlakes: 15,
	},
	{
		Name: "openshift/conformance/serial",
		Description: templates.LongDesc(`
		Only the portion of the openshift/conformance test suite that run serially.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/conformance/serial")
		},
	},
	{
		Name: "kubernetes/conformance",
		Description: templates.LongDesc(`
		The default Kubernetes conformance suite.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:k8s]") && strings.Contains(name, "[Conformance]")
		},
		Parallelism: 30,
	},
	{
		Name: "openshift/build",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift build functionality.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Feature:Builds]")
		},
		Parallelism: 7,
		// TODO: Builds are really flaky right now, remove when we land perf updates and fix io on workers
		MaximumAllowedFlakes: 3,
		// Jenkins tests can take a really long time
		TestTimeout: 60 * time.Minute,
	},
	{
		Name: "openshift/image-registry",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift image-registry functionality.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[registry]") && !strings.Contains(name, "[Local]")
		},
	},
	{
		Name: "openshift/image-ecosystem",
		Description: templates.LongDesc(`
		Tests that exercise language and tooling images shipped as part of OpenShift.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[image_ecosystem]") && !strings.Contains(name, "[Local]")
		},
		Parallelism: 7,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/jenkins-e2e",
		Description: templates.LongDesc(`
		Tests that exercise the OpenShift / Jenkins integrations provided by the OpenShift Jenkins image/plugins and the Pipeline Build Strategy.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "openshift pipeline")
		},
		Parallelism: 3,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/scalability",
		Description: templates.LongDesc(`
		Tests that verify the scalability characteristics of the cluster. Currently this is focused on core performance behaviors and preventing regressions.
		`),
		Matches: func(name string) bool {
			return strings.Contains(name, "[Suite:openshift/scalability]")
		},
		Parallelism: 1,
		TestTimeout: 20 * time.Minute,
	},
	{
		Name: "openshift/conformance-excluded",
		Description: templates.LongDesc(`
		Run only tests that are excluded from conformance. Makes identifying omitted tests easier.
		`),
		Matches: func(name string) bool { return !strings.Contains(name, "[Suite:openshift/conformance/") },
	},
	{
		Name: "all",
		Description: templates.LongDesc(`
		Run all tests.
		`),
		Matches: func(name string) bool { return true },
	},
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	ppg "github.com/beyang/pypigraph"
	"os"
	"strings"
)

func main() {
	flag.Parse()
	file := flag.Arg(0)
	pkg := ppg.NormalizedPkgName(flag.Arg(1))

	requires := make(map[string][]string)
	requiredBy := make(map[string][]string)

	f, _ := os.Open(file)
	reader := bufio.NewReader(f)
	for {
		lineB, _, err := reader.ReadLine()
		if err != nil {
			break
		}
		line := string(lineB)

		if strings.Contains(line, ":") {
			lineSplit := strings.Split(line, ":")
			if len(lineSplit) == 2 {
				pkg, dep := lineSplit[0], lineSplit[1]

				if _, in := requires[pkg]; !in {
					requires[pkg] = make([]string, 0)
				}
				requires[pkg] = append(requires[pkg], dep)

				if _, in := requiredBy[dep]; !in {
					requiredBy[dep] = make([]string, 0)
				}
				requiredBy[dep] = append(requiredBy[dep], pkg)
			}
		} else if line != "" {
			if _, in := requires[pkg]; !in {
				requires[pkg] = make([]string, 0)
			}
			if _, in := requiredBy[pkg]; !in {
				requiredBy[pkg] = make([]string, 0)
			}
		}
	}

	fmt.Printf("pkg %s uses:\n  %s\nand is used by:\n  %s\n", pkg, strings.Join(requires[pkg], " "), strings.Join(requiredBy[pkg], " "))
}
<commit_msg>use cached data by default<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	ppg "github.com/beyang/pypigraph"
	"os"
	"path/filepath"
	"strings"
)

var file = flag.String("graphfile", "", "Path to graph file.  Defaults to $GOPATH/src/github.com/beyang/pypigraph/data/pypi_graph")

func main() {
	flag.Parse()
	pkg := ppg.NormalizedPkgName(flag.Arg(0))

	if *file == "" {
		*file = filepath.Join(os.Getenv("GOPATH"), "src/github.com/beyang/pypigraph/data/pypi_graph")
	}

	requires := make(map[string][]string)
	requiredBy := make(map[string][]string)

	f, _ := os.Open(*file)
	reader := bufio.NewReader(f)
	for {
		lineB, _, err := reader.ReadLine()
		if err != nil {
			break
		}
		line := string(lineB)

		if strings.Contains(line, ":") {
			lineSplit := strings.Split(line, ":")
			if len(lineSplit) == 2 {
				pkg, dep := lineSplit[0], lineSplit[1]

				if _, in := requires[pkg]; !in {
					requires[pkg] = make([]string, 0)
				}
				requires[pkg] = append(requires[pkg], dep)

				if _, in := requiredBy[dep]; !in {
					requiredBy[dep] = make([]string, 0)
				}
				requiredBy[dep] = append(requiredBy[dep], pkg)
			}
		} else if line != "" {
			if _, in := requires[pkg]; !in {
				requires[pkg] = make([]string, 0)
			}
			if _, in := requiredBy[pkg]; !in {
				requiredBy[pkg] = make([]string, 0)
			}
		}
	}

	uses := requires[pkg]
	usedBy := requiredBy[pkg]
	fmt.Printf("pkg %s uses (%d):\n  %s\nand is used by (%d):\n  %s\n", pkg, len(uses), strings.Join(uses, " "), len(usedBy), strings.Join(usedBy, " "))
}
<|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
//
//     https://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.

/*
Transform invokes the transformer library on a given input doc to
generate and output transformed AMP HTML. This does not validate the
document.

See flag.Usage in main() for usage instructions.
*/
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	rpb "github.com/ampproject/amppackager/transformer/request"
	t "github.com/ampproject/amppackager/transformer"
)

var documentURLFlag = flag.String("url", "", "The URL of the document being processed, e.g. https://example.com/amphtml/article1234")

func checkErr(e error) {
	if e != nil {
		log.Fatal(e)
	}
}

func main() {
	// Custom usage message.
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "\nUsage %s [OPTION] [FILE]\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, `
Examples:

# Execute with filename
$GOPATH/bin/transform /path/to/input.html

# Execute with pipe
cat /path/to/input.html | $GOPATH/bin/transform
`)
	}

	flag.Parse()
	var data []byte
	var err error
	switch flag.NArg() {
	case 0:
		data, err = ioutil.ReadAll(os.Stdin)
	case 1:
		data, err = ioutil.ReadFile(flag.Arg(0))
	default:
		log.Fatal("Input must be from stdin or file.")
	}
	checkErr(err)
	r := &rpb.Request{Html: string(data), DocumentUrl: *documentURLFlag}
	o, err := t.Process(r)
	checkErr(err)
	fmt.Println(o)
}
<commit_msg>Fix cmd/transform, broken by the change to the Process() function signature.<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
//
//     https://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.

/*
Transform invokes the transformer library on a given input doc to
generate and output transformed AMP HTML. This does not validate the
document.

See flag.Usage in main() for usage instructions.
*/
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	rpb "github.com/ampproject/amppackager/transformer/request"
	t "github.com/ampproject/amppackager/transformer"
)

var documentURLFlag = flag.String("url", "", "The URL of the document being processed, e.g. https://example.com/amphtml/article1234")

func checkErr(e error) {
	if e != nil {
		log.Fatal(e)
	}
}

func main() {
	// Custom usage message.
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "\nUsage %s [OPTION] [FILE]\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, `
Examples:

# Execute with filename
$GOPATH/bin/transform /path/to/input.html

# Execute with pipe
cat /path/to/input.html | $GOPATH/bin/transform
`)
	}

	flag.Parse()
	var data []byte
	var err error
	switch flag.NArg() {
	case 0:
		data, err = ioutil.ReadAll(os.Stdin)
	case 1:
		data, err = ioutil.ReadFile(flag.Arg(0))
	default:
		log.Fatal("Input must be from stdin or file.")
	}
	checkErr(err)
	r := &rpb.Request{Html: string(data), DocumentUrl: *documentURLFlag}
	o, _, err := t.Process(r)
	checkErr(err)
	fmt.Println(o)
}
<|endoftext|>


<commit_before>package g

import (
	"time"
)

// changelog:
// 3.1.3: code refactor
// 3.1.4: bugfix ignore configuration
// 5.0.0: 支持通过配置控制是否开启/run接口；收集udp流量数据；du某个目录的大小
// 5.1.0: 同步插件的时候不再使用checksum机制
// 5.1.3: Fix config syntax error when deploying
// 5.1.4: Only trustable ip could access the webpage
// 5.1.5: New policy and plugin mechanism
// 5.1.6: Update cfg.json in release package. Program file is same as 5.1.5.
// 5.1.7: Fix failure of plugin updating.
// 5.1.8: Fix failure of plugin updating.
// 5.1.9: Fix command syntax error when collecting port status.
const (
	VERSION          = "5.1.9"
	COLLECT_INTERVAL = time.Second
	URL_CHECK_HEALTH = "url.check.health"
	NET_PORT_LISTEN  = "net.port.listen"
	DU_BS            = "du.bs"
	PROC_NUM         = "proc.num"
)
<commit_msg>[agent] version 5.1.10<commit_after>package g

import (
	"time"
)

// changelog:
// 3.1.3: code refactor
// 3.1.4: bugfix ignore configuration
// 5.0.0: 支持通过配置控制是否开启/run接口；收集udp流量数据；du某个目录的大小
// 5.1.0: 同步插件的时候不再使用checksum机制
// 5.1.3: Fix config syntax error when deploying
// 5.1.4: Only trustable ip could access the webpage
// 5.1.5: New policy and plugin mechanism
// 5.1.6: Update cfg.json in release package. Program file is same as 5.1.5.
// 5.1.7: Fix failure of plugin updating.
// 5.1.8: Fix failure of plugin updating.
// 5.1.9: Fix command syntax error when collecting port status.
// 5.1.10: Fix and modify builtin metrics.
const (
	VERSION          = "5.1.10"
	COLLECT_INTERVAL = time.Second
	URL_CHECK_HEALTH = "url.check.health"
	NET_PORT_LISTEN  = "net.port.listen"
	DU_BS            = "du.bs"
	PROC_NUM         = "proc.num"
)
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"time"

	"mig.ninja/mig"
	"mig.ninja/mig/client"
	"mig.ninja/mig/modules"
)

func usage() {
	fmt.Printf(`%s - Mozilla InvestiGator command line client
usage: %s <module> <global options> <module parameters>

--- Global options ---

-c <path>	path to an alternative confiig file. If not set, use ~/.migrc

-e <duration>	time after which the action expires. 60 seconds by default.
		example: -e 300s (5 minutes)

-i <file>	load and run action from a file. supersedes other action flags.

-p <bool>       display action json that would be used and exit

-show <mode>	type of results to show. if not set, default is 'found'.
		* found: 	only print positive results
		* notfound: 	only print negative results
		* all: 		print all results

-render <mode>	defines how results should be rendered:
		* text (default):	results are printed to the console
		* map:			results are geolocated and a google map is generated

-t <target>	target to launch the action on. A target must be specified.
		examples:
		* linux agents:          -t "queueloc LIKE 'linux.%%'"
		* agents named *mysql*:  -t "name like '%%mysql%%'"
		* proxied linux agents:  -t "queueloc LIKE 'linux.%%' AND environment->>'isproxied' = 'true'"
		* agents operated by IT: -t "tags#>>'{operator}'='IT'"
		* run on local system:	 -t local
		* use a migrc macro:     -t mymacroname

-targetfound <action ID>
-targetnotfound <action ID>
		targets agents that have eiher found or not found results in a previous action.
		example: -target-found 123456

-v		verbose output, includes debug information and raw queries

-V		print version

-z <bool>       compress action before sending it to agents

Progress information is sent to stderr, silence it with "2>/dev/null".
Results are sent to stdout, redirect them with "1>/path/to/file".

--- Modules documentation ---
Each module provides its own set of parameters. Module parameters must be set *after*
global options. Help is available by calling "<module> help". Available modules are:
`, os.Args[0], os.Args[0])
	for module, _ := range modules.Available {
		fmt.Printf("* %s\n", module)
	}
	fmt.Printf("To access a module documentation, use: %s <module> help\n", os.Args[0])
	os.Exit(1)
}

func continueOnFlagError() {
	return
}

func main() {
	var (
		conf                                    client.Configuration
		cli                                     client.Client
		err                                     error
		op                                      mig.Operation
		a                                       mig.Action
		migrc, show, render, target, expiration string
		afile, targetfound, targetnotfound      string
		printAndExit                            bool
		verbose, showversion                    bool
		compressAction                          bool
		modargs                                 []string
		run                                     interface{}
	)
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "%v\n", e)
		}
	}()
	homedir := client.FindHomedir()
	fs := flag.NewFlagSet("mig flag", flag.ContinueOnError)
	fs.Usage = continueOnFlagError
	fs.BoolVar(&printAndExit, "p", false, "display action json that would be used and exit")
	fs.StringVar(&migrc, "c", homedir+"/.migrc", "alternative configuration file")
	fs.StringVar(&show, "show", "found", "type of results to show")
	fs.StringVar(&render, "render", "text", "results rendering mode")
	fs.StringVar(&target, "t", "", "action target")
	fs.StringVar(&targetfound, "target-found", "", "targets agents that have found results in a previous action.")
	fs.StringVar(&targetnotfound, "target-notfound", "", "targets agents that haven't found results in a previous action.")
	fs.StringVar(&expiration, "e", "300s", "expiration")
	fs.StringVar(&afile, "i", "/path/to/file", "Load action from file")
	fs.BoolVar(&verbose, "v", false, "Enable verbose output")
	fs.BoolVar(&showversion, "V", false, "Show version")
	fs.BoolVar(&compressAction, "z", false, "Request compression of action parameters")

	// if first argument is missing, or is help, print help
	// otherwise, pass the remainder of the arguments to the module for parsing
	// this client is agnostic to module parameters
	if len(os.Args) < 2 || os.Args[1] == "help" || os.Args[1] == "-h" || os.Args[1] == "--help" {
		usage()
	}

	if showversion || (len(os.Args) > 1 && (os.Args[1] == "-V" || os.Args[1] == "version")) {
		fmt.Println(mig.Version)
		os.Exit(0)
	}

	// instantiate an API client
	conf, err = client.ReadConfiguration(migrc)
	if err != nil {
		panic(err)
	}
	cli, err = client.NewClient(conf, "cmd-"+mig.Version)
	if err != nil {
		panic(err)
	}
	if verbose {
		cli.EnableDebug()
	}

	// when reading the action from a file, go directly to launch
	if os.Args[1] == "-i" {
		err = fs.Parse(os.Args[1:])
		if err != nil {
			panic(err)
		}
		if afile == "/path/to/file" {
			panic("-i flag must take an action file path as argument")
		}
		a, err = mig.ActionFromFile(afile)
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "[info] launching action from file, all flags are ignored\n")
		if printAndExit {
			actionstr, err := a.IndentedString()
			if err != nil {
				panic(err)
			}
			fmt.Fprintf(os.Stdout, "%v\n", actionstr)
			os.Exit(0)
		}
		goto readytolaunch
	}

	// arguments parsing works as follow:
	// * os.Args[1] must contain the name of the module to launch. we first verify
	//   that a module exist for this name and then continue parsing
	// * os.Args[2:] contains both global options and module parameters. We parse the
	//   whole []string to extract global options, and module parameters will be left
	//   unparsed in fs.Args()
	// * fs.Args() with the module parameters is passed as a string to the module parser
	//   which will return a module operation to store in the action
	op.Module = os.Args[1]
	if _, ok := modules.Available[op.Module]; !ok {
		panic("Unknown module " + op.Module)
	}

	// -- Ugly hack Warning --
	// Parse() will fail on the first flag that is not defined, but in our case module flags
	// are defined in the module packages and not in this program. Therefore, the flag parse error
	// is expected. Unfortunately, Parse() writes directly to stderr and displays the error to
	// the user, which confuses them. The right fix would be to prevent Parse() from writing to
	// stderr, since that's really the job of the calling program, but in the meantime we work around
	// it by redirecting stderr to null before calling Parse(), and put it back to normal afterward.
	// for ref, issue is at https://github.com/golang/go/blob/master/src/flag/flag.go#L793
	fs.SetOutput(os.NewFile(uintptr(87592), os.DevNull))
	err = fs.Parse(os.Args[2:])
	fs.SetOutput(nil)
	if err != nil {
		// ignore the flag not defined error, which is expected because
		// module parameters are defined in modules and not in main
		if len(err.Error()) > 30 && err.Error()[0:29] == "flag provided but not defined" {
			// requeue the parameter that failed
			modargs = append(modargs, err.Error()[31:])
		} else {
			// if it's another error, panic
			panic(err)
		}
	}
	for _, arg := range fs.Args() {
		modargs = append(modargs, arg)
	}
	run = modules.Available[op.Module].NewRun()
	if _, ok := run.(modules.HasParamsParser); !ok {
		fmt.Fprintf(os.Stderr, "[error] module '%s' does not support command line invocation\n", op.Module)
		os.Exit(2)
	}
	op.Parameters, err = run.(modules.HasParamsParser).ParamsParser(modargs)
	if err != nil || op.Parameters == nil {
		panic(err)
	}
	// If compression has been enabled, flag it in the operation.
	if compressAction {
		op.WantCompressed = true
	}
	// Make sure a target value was specified
	if target == "" {
		fmt.Fprintf(os.Stderr, "[error] No target was specified with -t after the module name\n\n"+
			"See MIG documentation on target strings and creating target macros\n"+
			"for help. If you are sure you want to target everything online, you\n"+
			"can use \"status='online'\" as the argument to -t. See the usage\n"+
			"output for the mig command for more examples.\n")
		os.Exit(2)
	}
	// If running against the local target, don't post the action to the MIG API
	// but run it locally instead.
	if target == "local" {
		msg, err := modules.MakeMessage(modules.MsgClassParameters, op.Parameters, false)
		if err != nil {
			panic(err)
		}
		out := run.(modules.Runner).Run(bytes.NewBuffer(msg))
		if len(out) == 0 {
			panic("got empty results, run failed")
		}
		if _, ok := run.(modules.HasResultsPrinter); ok {
			var modres modules.Result
			err := json.Unmarshal([]byte(out), &modres)
			if err != nil {
				panic(err)
			}
			outRes, err := run.(modules.HasResultsPrinter).PrintResults(modres, true)
			if err != nil {
				panic(err)
			}
			for _, resLine := range outRes {
				fmt.Println(resLine)
			}
		} else {
			out = fmt.Sprintf("%s\n", out)
		}
		os.Exit(0)
	}

	a.Operations = append(a.Operations, op)

	for _, arg := range os.Args[1:] {
		a.Name += arg + " "
	}

	// Determine if the specified target was a macro, and if so get the correct
	// target string
	target = cli.ResolveTargetMacro(target)
	if targetfound != "" && targetnotfound != "" {
		panic("Both -target-found and -target-foundnothing cannot be used simultaneously")
	}
	if targetfound != "" {
		targetQuery := fmt.Sprintf(`id IN (select agentid from commands, json_array_elements(commands.results) as `+
			`r where actionid=%s and r#>>'{foundanything}' = 'true')`, targetfound)
		target = targetQuery + " AND " + target
	}
	if targetnotfound != "" {
		targetQuery := fmt.Sprintf(`id NOT IN (select agentid from commands, json_array_elements(commands.results) as `+
			`r where actionid=%s and r#>>'{foundanything}' = 'false')`, targetnotfound)
		target = targetQuery + " AND " + target
	}
	a.Target = target

	if printAndExit {
		actionstr, err := a.IndentedString()
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stdout, "%v\n", actionstr)
		os.Exit(0)
	}

readytolaunch:
	// set the validity 60 second in the past to deal with clock skew
	a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
	period, err := time.ParseDuration(expiration)
	if err != nil {
		panic(err)
	}
	a.ExpireAfter = a.ValidFrom.Add(period)
	// add extra 60 seconds taken for clock skew
	a.ExpireAfter = a.ExpireAfter.Add(60 * time.Second).UTC()

	a, err = cli.CompressAction(a)
	if err != nil {
		panic(err)
	}
	asig, err := cli.SignAction(a)
	if err != nil {
		panic(err)
	}
	a = asig

	// evaluate target before launch, give a change to cancel before going out to agents
	agents, err := cli.EvaluateAgentTarget(a.Target)
	if err != nil {
		panic(err)
	}
	fmt.Fprintf(os.Stderr, "\x1b[33m%d agents will be targeted. ctrl+c to cancel. launching in \x1b[0m", len(agents))
	for i := 5; i > 0; i-- {
		time.Sleep(1 * time.Second)
		fmt.Fprintf(os.Stderr, "\x1b[33m%d\x1b[0m ", i)
	}
	fmt.Fprintf(os.Stderr, "\x1b[33mGO\n\x1b[0m")

	// launch and follow
	a, err = cli.PostAction(a)
	if err != nil {
		panic(err)
	}
	c := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		err = cli.FollowAction(a, len(agents))
		if err != nil {
			panic(err)
		}
		done <- true
	}()
	select {
	case <-c:
		fmt.Fprintf(os.Stderr, "stop following action. agents may still be running. printing available results:\n")
		goto printresults
	case <-done:
		goto printresults
	}
printresults:
	err = cli.PrintActionResults(a, show, render)
	if err != nil {
		panic(err)
	}
}
<commit_msg>[minor/bug] reference correct flags in cmd usage<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"time"

	"mig.ninja/mig"
	"mig.ninja/mig/client"
	"mig.ninja/mig/modules"
)

func usage() {
	fmt.Printf(`%s - Mozilla InvestiGator command line client
usage: %s <module> <global options> <module parameters>

--- Global options ---

-c <path>	path to an alternative confiig file. If not set, use ~/.migrc

-e <duration>	time after which the action expires. 60 seconds by default.
		example: -e 300s (5 minutes)

-i <file>	load and run action from a file. supersedes other action flags.

-p <bool>       display action json that would be used and exit

-show <mode>	type of results to show. if not set, default is 'found'.
		* found: 	only print positive results
		* notfound: 	only print negative results
		* all: 		print all results

-render <mode>	defines how results should be rendered:
		* text (default):	results are printed to the console
		* map:			results are geolocated and a google map is generated

-t <target>	target to launch the action on. A target must be specified.
		examples:
		* linux agents:          -t "queueloc LIKE 'linux.%%'"
		* agents named *mysql*:  -t "name like '%%mysql%%'"
		* proxied linux agents:  -t "queueloc LIKE 'linux.%%' AND environment->>'isproxied' = 'true'"
		* agents operated by IT: -t "tags#>>'{operator}'='IT'"
		* run on local system:	 -t local
		* use a migrc macro:     -t mymacroname

-target-found    <action ID>
-target-notfound <action ID>
		targets agents that have eiher found or not found results in a previous action.
		example: -target-found 123456

-v		verbose output, includes debug information and raw queries

-V		print version

-z <bool>       compress action before sending it to agents

Progress information is sent to stderr, silence it with "2>/dev/null".
Results are sent to stdout, redirect them with "1>/path/to/file".

--- Modules documentation ---
Each module provides its own set of parameters. Module parameters must be set *after*
global options. Help is available by calling "<module> help". Available modules are:
`, os.Args[0], os.Args[0])
	for module, _ := range modules.Available {
		fmt.Printf("* %s\n", module)
	}
	fmt.Printf("To access a module documentation, use: %s <module> help\n", os.Args[0])
	os.Exit(1)
}

func continueOnFlagError() {
	return
}

func main() {
	var (
		conf                                    client.Configuration
		cli                                     client.Client
		err                                     error
		op                                      mig.Operation
		a                                       mig.Action
		migrc, show, render, target, expiration string
		afile, targetfound, targetnotfound      string
		printAndExit                            bool
		verbose, showversion                    bool
		compressAction                          bool
		modargs                                 []string
		run                                     interface{}
	)
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "%v\n", e)
		}
	}()
	homedir := client.FindHomedir()
	fs := flag.NewFlagSet("mig flag", flag.ContinueOnError)
	fs.Usage = continueOnFlagError
	fs.BoolVar(&printAndExit, "p", false, "display action json that would be used and exit")
	fs.StringVar(&migrc, "c", homedir+"/.migrc", "alternative configuration file")
	fs.StringVar(&show, "show", "found", "type of results to show")
	fs.StringVar(&render, "render", "text", "results rendering mode")
	fs.StringVar(&target, "t", "", "action target")
	fs.StringVar(&targetfound, "target-found", "", "targets agents that have found results in a previous action.")
	fs.StringVar(&targetnotfound, "target-notfound", "", "targets agents that haven't found results in a previous action.")
	fs.StringVar(&expiration, "e", "300s", "expiration")
	fs.StringVar(&afile, "i", "/path/to/file", "Load action from file")
	fs.BoolVar(&verbose, "v", false, "Enable verbose output")
	fs.BoolVar(&showversion, "V", false, "Show version")
	fs.BoolVar(&compressAction, "z", false, "Request compression of action parameters")

	// if first argument is missing, or is help, print help
	// otherwise, pass the remainder of the arguments to the module for parsing
	// this client is agnostic to module parameters
	if len(os.Args) < 2 || os.Args[1] == "help" || os.Args[1] == "-h" || os.Args[1] == "--help" {
		usage()
	}

	if showversion || (len(os.Args) > 1 && (os.Args[1] == "-V" || os.Args[1] == "version")) {
		fmt.Println(mig.Version)
		os.Exit(0)
	}

	// instantiate an API client
	conf, err = client.ReadConfiguration(migrc)
	if err != nil {
		panic(err)
	}
	cli, err = client.NewClient(conf, "cmd-"+mig.Version)
	if err != nil {
		panic(err)
	}
	if verbose {
		cli.EnableDebug()
	}

	// when reading the action from a file, go directly to launch
	if os.Args[1] == "-i" {
		err = fs.Parse(os.Args[1:])
		if err != nil {
			panic(err)
		}
		if afile == "/path/to/file" {
			panic("-i flag must take an action file path as argument")
		}
		a, err = mig.ActionFromFile(afile)
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "[info] launching action from file, all flags are ignored\n")
		if printAndExit {
			actionstr, err := a.IndentedString()
			if err != nil {
				panic(err)
			}
			fmt.Fprintf(os.Stdout, "%v\n", actionstr)
			os.Exit(0)
		}
		goto readytolaunch
	}

	// arguments parsing works as follow:
	// * os.Args[1] must contain the name of the module to launch. we first verify
	//   that a module exist for this name and then continue parsing
	// * os.Args[2:] contains both global options and module parameters. We parse the
	//   whole []string to extract global options, and module parameters will be left
	//   unparsed in fs.Args()
	// * fs.Args() with the module parameters is passed as a string to the module parser
	//   which will return a module operation to store in the action
	op.Module = os.Args[1]
	if _, ok := modules.Available[op.Module]; !ok {
		panic("Unknown module " + op.Module)
	}

	// -- Ugly hack Warning --
	// Parse() will fail on the first flag that is not defined, but in our case module flags
	// are defined in the module packages and not in this program. Therefore, the flag parse error
	// is expected. Unfortunately, Parse() writes directly to stderr and displays the error to
	// the user, which confuses them. The right fix would be to prevent Parse() from writing to
	// stderr, since that's really the job of the calling program, but in the meantime we work around
	// it by redirecting stderr to null before calling Parse(), and put it back to normal afterward.
	// for ref, issue is at https://github.com/golang/go/blob/master/src/flag/flag.go#L793
	fs.SetOutput(os.NewFile(uintptr(87592), os.DevNull))
	err = fs.Parse(os.Args[2:])
	fs.SetOutput(nil)
	if err != nil {
		// ignore the flag not defined error, which is expected because
		// module parameters are defined in modules and not in main
		if len(err.Error()) > 30 && err.Error()[0:29] == "flag provided but not defined" {
			// requeue the parameter that failed
			modargs = append(modargs, err.Error()[31:])
		} else {
			// if it's another error, panic
			panic(err)
		}
	}
	for _, arg := range fs.Args() {
		modargs = append(modargs, arg)
	}
	run = modules.Available[op.Module].NewRun()
	if _, ok := run.(modules.HasParamsParser); !ok {
		fmt.Fprintf(os.Stderr, "[error] module '%s' does not support command line invocation\n", op.Module)
		os.Exit(2)
	}
	op.Parameters, err = run.(modules.HasParamsParser).ParamsParser(modargs)
	if err != nil || op.Parameters == nil {
		panic(err)
	}
	// If compression has been enabled, flag it in the operation.
	if compressAction {
		op.WantCompressed = true
	}
	// Make sure a target value was specified
	if target == "" {
		fmt.Fprintf(os.Stderr, "[error] No target was specified with -t after the module name\n\n"+
			"See MIG documentation on target strings and creating target macros\n"+
			"for help. If you are sure you want to target everything online, you\n"+
			"can use \"status='online'\" as the argument to -t. See the usage\n"+
			"output for the mig command for more examples.\n")
		os.Exit(2)
	}
	// If running against the local target, don't post the action to the MIG API
	// but run it locally instead.
	if target == "local" {
		msg, err := modules.MakeMessage(modules.MsgClassParameters, op.Parameters, false)
		if err != nil {
			panic(err)
		}
		out := run.(modules.Runner).Run(bytes.NewBuffer(msg))
		if len(out) == 0 {
			panic("got empty results, run failed")
		}
		if _, ok := run.(modules.HasResultsPrinter); ok {
			var modres modules.Result
			err := json.Unmarshal([]byte(out), &modres)
			if err != nil {
				panic(err)
			}
			outRes, err := run.(modules.HasResultsPrinter).PrintResults(modres, true)
			if err != nil {
				panic(err)
			}
			for _, resLine := range outRes {
				fmt.Println(resLine)
			}
		} else {
			out = fmt.Sprintf("%s\n", out)
		}
		os.Exit(0)
	}

	a.Operations = append(a.Operations, op)

	for _, arg := range os.Args[1:] {
		a.Name += arg + " "
	}

	// Determine if the specified target was a macro, and if so get the correct
	// target string
	target = cli.ResolveTargetMacro(target)
	if targetfound != "" && targetnotfound != "" {
		panic("Both -target-found and -target-foundnothing cannot be used simultaneously")
	}
	if targetfound != "" {
		targetQuery := fmt.Sprintf(`id IN (select agentid from commands, json_array_elements(commands.results) as `+
			`r where actionid=%s and r#>>'{foundanything}' = 'true')`, targetfound)
		target = targetQuery + " AND " + target
	}
	if targetnotfound != "" {
		targetQuery := fmt.Sprintf(`id NOT IN (select agentid from commands, json_array_elements(commands.results) as `+
			`r where actionid=%s and r#>>'{foundanything}' = 'false')`, targetnotfound)
		target = targetQuery + " AND " + target
	}
	a.Target = target

	if printAndExit {
		actionstr, err := a.IndentedString()
		if err != nil {
			panic(err)
		}
		fmt.Fprintf(os.Stdout, "%v\n", actionstr)
		os.Exit(0)
	}

readytolaunch:
	// set the validity 60 second in the past to deal with clock skew
	a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
	period, err := time.ParseDuration(expiration)
	if err != nil {
		panic(err)
	}
	a.ExpireAfter = a.ValidFrom.Add(period)
	// add extra 60 seconds taken for clock skew
	a.ExpireAfter = a.ExpireAfter.Add(60 * time.Second).UTC()

	a, err = cli.CompressAction(a)
	if err != nil {
		panic(err)
	}
	asig, err := cli.SignAction(a)
	if err != nil {
		panic(err)
	}
	a = asig

	// evaluate target before launch, give a change to cancel before going out to agents
	agents, err := cli.EvaluateAgentTarget(a.Target)
	if err != nil {
		panic(err)
	}
	fmt.Fprintf(os.Stderr, "\x1b[33m%d agents will be targeted. ctrl+c to cancel. launching in \x1b[0m", len(agents))
	for i := 5; i > 0; i-- {
		time.Sleep(1 * time.Second)
		fmt.Fprintf(os.Stderr, "\x1b[33m%d\x1b[0m ", i)
	}
	fmt.Fprintf(os.Stderr, "\x1b[33mGO\n\x1b[0m")

	// launch and follow
	a, err = cli.PostAction(a)
	if err != nil {
		panic(err)
	}
	c := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		err = cli.FollowAction(a, len(agents))
		if err != nil {
			panic(err)
		}
		done <- true
	}()
	select {
	case <-c:
		fmt.Fprintf(os.Stderr, "stop following action. agents may still be running. printing available results:\n")
		goto printresults
	case <-done:
		goto printresults
	}
printresults:
	err = cli.PrintActionResults(a, show, render)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"fmt"
	"testing"

	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFailingTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Usual failures
////////////////////////////////////////////////////////////////////////

type FailingTest struct {
}

var _ TearDownInterface = &FailingTest{}
var _ TearDownTestSuiteInterface = &FailingTest{}

func init() { RegisterTestSuite(&FailingTest{}) }

func (t *FailingTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *FailingTest) TearDownTestSuite() {
	fmt.Println("TearDownTestSuite running.")
}

func (t *FailingTest) PassingMethod() {
}

func (t *FailingTest) Equals() {
	ExpectThat(17, Equals(17.5))
	ExpectThat(17, Equals("taco"))
}

func (t *FailingTest) LessThan() {
	ExpectThat(18, LessThan(17))
	ExpectThat(18, LessThan("taco"))
}

func (t *FailingTest) HasSubstr() {
	ExpectThat("taco", HasSubstr("ac"))
	ExpectThat(17, HasSubstr("ac"))
}

func (t *FailingTest) ExpectWithUserErrorMessages() {
	ExpectThat(17, Equals(19), "foo bar: %d", 112)
	ExpectEq(17, 17.5, "foo bar: %d", 112)
	ExpectLe(17, 16.9, "foo bar: %d", 112)
	ExpectLt(17, 16.9, "foo bar: %d", 112)
	ExpectGe(17, 17.1, "foo bar: %d", 112)
	ExpectGt(17, "taco", "foo bar: %d", 112)
	ExpectNe(17, 17.0, "foo bar: %d", 112)
	ExpectFalse(true, "foo bar: %d", 112)
	ExpectTrue(false, "foo bar: %d", 112)
}

func (t *FailingTest) AssertWithUserErrorMessages() {
	AssertThat(17, Equals(19), "foo bar: %d", 112)
}

func (t *FailingTest) ExpectationAliases() {
	ExpectEq(17, 17.5)
	ExpectEq("taco", 17.5)

	ExpectLe(17, 16.9)
	ExpectLt(17, 16.9)
	ExpectLt(17, "taco")

	ExpectGe(17, 17.1)
	ExpectGt(17, 17.1)
	ExpectGt(17, "taco")

	ExpectNe(17, 17.0)
	ExpectNe(17, "taco")

	ExpectFalse(true)
	ExpectFalse("taco")

	ExpectTrue(false)
	ExpectTrue("taco")
}

func (t *FailingTest) AssertThatFailure() {
	AssertThat(17, Equals(19))
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertEqFailure() {
	AssertEq(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertNeFailure() {
	AssertNe(19, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertLeFailure() {
	AssertLe(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertLtFailure() {
	AssertLt(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertGeFailure() {
	AssertGe(17, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertGtFailure() {
	AssertGt(17, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertTrueFailure() {
	AssertTrue("taco")
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertFalseFailure() {
	AssertFalse("taco")
	panic("Shouldn't get here.")
}

func (t *FailingTest) AddFailureRecord() {
	r := FailureRecord{
		FileName:   "foo.go",
		LineNumber: 17,
		"taco\nburrito",
	}

	AddFailureRecord(r)
}

func (t *FailingTest) AddFailure() {
	AddFailure("taco")
	AddFailure("burrito: %d", 17)
}

func (t *FailingTest) AddFailureThenAbortTest() {
	AddFailure("enchilada")
	AbortTest()
}

////////////////////////////////////////////////////////////////////////
// Expectation failure during SetUp
////////////////////////////////////////////////////////////////////////

type ExpectFailDuringSetUpTest struct {
}

func init() { RegisterTestSuite(&ExpectFailDuringSetUpTest{}) }

func (t *ExpectFailDuringSetUpTest) SetUp(i *TestInfo) {
	ExpectFalse(true)
}

func (t *ExpectFailDuringSetUpTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *ExpectFailDuringSetUpTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Assertion failure during SetUp
////////////////////////////////////////////////////////////////////////

type AssertFailDuringSetUpTest struct {
}

func init() { RegisterTestSuite(&AssertFailDuringSetUpTest{}) }

func (t *AssertFailDuringSetUpTest) SetUp(i *TestInfo) {
	AssertFalse(true)
}

func (t *AssertFailDuringSetUpTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *AssertFailDuringSetUpTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Expectation failure during TearDown
////////////////////////////////////////////////////////////////////////

type ExpectFailDuringTearDownTest struct {
}

func init() { RegisterTestSuite(&ExpectFailDuringTearDownTest{}) }

func (t *ExpectFailDuringTearDownTest) SetUp(i *TestInfo) {
	fmt.Println("SetUp running.")
}

func (t *ExpectFailDuringTearDownTest) TearDown() {
	ExpectFalse(true)
}

func (t *ExpectFailDuringTearDownTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Assertion failure during TearDown
////////////////////////////////////////////////////////////////////////

type AssertFailDuringTearDownTest struct {
}

func init() { RegisterTestSuite(&AssertFailDuringTearDownTest{}) }

func (t *AssertFailDuringTearDownTest) SetUp(i *TestInfo) {
	fmt.Println("SetUp running.")
}

func (t *AssertFailDuringTearDownTest) TearDown() {
	AssertFalse(true)
}

func (t *AssertFailDuringTearDownTest) PassingMethod() {
	fmt.Println("Method running.")
}
<commit_msg>Fixed a build error.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"fmt"
	"testing"

	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFailingTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Usual failures
////////////////////////////////////////////////////////////////////////

type FailingTest struct {
}

var _ TearDownInterface = &FailingTest{}
var _ TearDownTestSuiteInterface = &FailingTest{}

func init() { RegisterTestSuite(&FailingTest{}) }

func (t *FailingTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *FailingTest) TearDownTestSuite() {
	fmt.Println("TearDownTestSuite running.")
}

func (t *FailingTest) PassingMethod() {
}

func (t *FailingTest) Equals() {
	ExpectThat(17, Equals(17.5))
	ExpectThat(17, Equals("taco"))
}

func (t *FailingTest) LessThan() {
	ExpectThat(18, LessThan(17))
	ExpectThat(18, LessThan("taco"))
}

func (t *FailingTest) HasSubstr() {
	ExpectThat("taco", HasSubstr("ac"))
	ExpectThat(17, HasSubstr("ac"))
}

func (t *FailingTest) ExpectWithUserErrorMessages() {
	ExpectThat(17, Equals(19), "foo bar: %d", 112)
	ExpectEq(17, 17.5, "foo bar: %d", 112)
	ExpectLe(17, 16.9, "foo bar: %d", 112)
	ExpectLt(17, 16.9, "foo bar: %d", 112)
	ExpectGe(17, 17.1, "foo bar: %d", 112)
	ExpectGt(17, "taco", "foo bar: %d", 112)
	ExpectNe(17, 17.0, "foo bar: %d", 112)
	ExpectFalse(true, "foo bar: %d", 112)
	ExpectTrue(false, "foo bar: %d", 112)
}

func (t *FailingTest) AssertWithUserErrorMessages() {
	AssertThat(17, Equals(19), "foo bar: %d", 112)
}

func (t *FailingTest) ExpectationAliases() {
	ExpectEq(17, 17.5)
	ExpectEq("taco", 17.5)

	ExpectLe(17, 16.9)
	ExpectLt(17, 16.9)
	ExpectLt(17, "taco")

	ExpectGe(17, 17.1)
	ExpectGt(17, 17.1)
	ExpectGt(17, "taco")

	ExpectNe(17, 17.0)
	ExpectNe(17, "taco")

	ExpectFalse(true)
	ExpectFalse("taco")

	ExpectTrue(false)
	ExpectTrue("taco")
}

func (t *FailingTest) AssertThatFailure() {
	AssertThat(17, Equals(19))
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertEqFailure() {
	AssertEq(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertNeFailure() {
	AssertNe(19, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertLeFailure() {
	AssertLe(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertLtFailure() {
	AssertLt(19, 17)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertGeFailure() {
	AssertGe(17, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertGtFailure() {
	AssertGt(17, 19)
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertTrueFailure() {
	AssertTrue("taco")
	panic("Shouldn't get here.")
}

func (t *FailingTest) AssertFalseFailure() {
	AssertFalse("taco")
	panic("Shouldn't get here.")
}

func (t *FailingTest) AddFailureRecord() {
	r := FailureRecord{
		FileName:   "foo.go",
		LineNumber: 17,
		Error:      "taco\nburrito",
	}

	AddFailureRecord(r)
}

func (t *FailingTest) AddFailure() {
	AddFailure("taco")
	AddFailure("burrito: %d", 17)
}

func (t *FailingTest) AddFailureThenAbortTest() {
	AddFailure("enchilada")
	AbortTest()
}

////////////////////////////////////////////////////////////////////////
// Expectation failure during SetUp
////////////////////////////////////////////////////////////////////////

type ExpectFailDuringSetUpTest struct {
}

func init() { RegisterTestSuite(&ExpectFailDuringSetUpTest{}) }

func (t *ExpectFailDuringSetUpTest) SetUp(i *TestInfo) {
	ExpectFalse(true)
}

func (t *ExpectFailDuringSetUpTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *ExpectFailDuringSetUpTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Assertion failure during SetUp
////////////////////////////////////////////////////////////////////////

type AssertFailDuringSetUpTest struct {
}

func init() { RegisterTestSuite(&AssertFailDuringSetUpTest{}) }

func (t *AssertFailDuringSetUpTest) SetUp(i *TestInfo) {
	AssertFalse(true)
}

func (t *AssertFailDuringSetUpTest) TearDown() {
	fmt.Println("TearDown running.")
}

func (t *AssertFailDuringSetUpTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Expectation failure during TearDown
////////////////////////////////////////////////////////////////////////

type ExpectFailDuringTearDownTest struct {
}

func init() { RegisterTestSuite(&ExpectFailDuringTearDownTest{}) }

func (t *ExpectFailDuringTearDownTest) SetUp(i *TestInfo) {
	fmt.Println("SetUp running.")
}

func (t *ExpectFailDuringTearDownTest) TearDown() {
	ExpectFalse(true)
}

func (t *ExpectFailDuringTearDownTest) PassingMethod() {
	fmt.Println("Method running.")
}

////////////////////////////////////////////////////////////////////////
// Assertion failure during TearDown
////////////////////////////////////////////////////////////////////////

type AssertFailDuringTearDownTest struct {
}

func init() { RegisterTestSuite(&AssertFailDuringTearDownTest{}) }

func (t *AssertFailDuringTearDownTest) SetUp(i *TestInfo) {
	fmt.Println("SetUp running.")
}

func (t *AssertFailDuringTearDownTest) TearDown() {
	AssertFalse(true)
}

func (t *AssertFailDuringTearDownTest) PassingMethod() {
	fmt.Println("Method running.")
}
<|endoftext|>