<commit_before>// Command glow generates Go OpenGL bindings. See http://github.com/errcw/glow.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var specURL = "https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api"
var specRegexp = regexp.MustCompile(`^(gl|glx|egl|wgl)\.xml$`)

var docURLs = []string{
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man2",
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man3",
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man4"}
var docRegexp = regexp.MustCompile(`^[ew]?gl[^u_].*\.xml$`)

func download(name string, args []string) {
	flags := flag.NewFlagSet(name, flag.ExitOnError)
	xmlDir := flags.String("d", "xml", "XML directory")
	flags.Parse(args)

	specDir := filepath.Join(*xmlDir, "spec")
	if err := os.MkdirAll(specDir, 0755); err != nil {
		log.Fatalln("error creating specification output directory:", err)
	}

	docDir := filepath.Join(*xmlDir, "doc")
	if err := os.MkdirAll(docDir, 0755); err != nil {
		log.Fatalln("error creating documentation output directory:", err)
	}

	rev, err := DownloadSvnDir(specURL, specRegexp, specDir)
	if err != nil {
		log.Fatalln("error downloading specification files:", err)
	}

	specVersionFile := filepath.Join(specDir, "REVISION")
	if err := ioutil.WriteFile(specVersionFile, []byte(rev), 0644); err != nil {
		log.Fatalln("error writing spec revision metadata file:", err)
	}

	for _, url := range docURLs {
		if _, err := DownloadSvnDir(url, docRegexp, docDir); err != nil {
			log.Fatalln("error downloading documentation files:", err)
		}
	}
}

func generate(name string, args []string) {
	flags := flag.NewFlagSet(name, flag.ExitOnError)
	var (
		xmlDir      = flags.String("xml", importPathToDir("github.com/go-gl/glow/xml"), "XML directory")
		tmplDir     = flags.String("tmpl", importPathToDir("github.com/go-gl/glow/tmpl"), "Template directory")
		outDir      = flags.String("out", "gl", "Output directory")
		api         = flags.String("api", "", "API to generate (e.g., gl)")
		ver         = flags.String("version", "", "API version to generate (e.g., 4.1)")
		profile     = flags.String("profile", "", "API profile to generate (e.g., core)")
		addext      = flags.String("addext", "", "Regular expression of extensions to include (e.g., .*)")
		remext      = flags.String("remext", "", "Regular expression of extensions to exclude (e.g., .*)")
		restrict    = flags.String("restrict", "", "JSON file of symbols to restrict symbol generation")
		lenientInit = flags.Bool("lenientInit", false, "When true missing functions do not fail Init")
	)
	flags.Parse(args)

	version, err := ParseVersion(*ver)
	if err != nil {
		log.Fatalln("error parsing version:", err)
	}

	var addExtRegexp *regexp.Regexp = nil
	if *addext != "" {
		addExtRegexp, err = regexp.Compile(*addext)
		if err != nil {
			log.Fatalln("error parsing extension inclusion regexp:", err)
		}
	}

	var remExtRegexp *regexp.Regexp = nil
	if *remext != "" {
		remExtRegexp, err = regexp.Compile(*remext)
		if err != nil {
			log.Fatalln("error parsing extension exclusion regexp:", err)
		}
	}

	packageSpec := &PackageSpec{
		API:          *api,
		Version:      version,
		Profile:      *profile,
		TmplDir:      *tmplDir,
		AddExtRegexp: addExtRegexp,
		RemExtRegexp: remExtRegexp,
		LenientInit:  *lenientInit,
	}

	specs, rev := parseSpecifications(*xmlDir)
	docs := parseDocumentation(*xmlDir)

	var pkg *Package
	for _, spec := range specs {
		if spec.HasPackage(packageSpec) {
			pkg = spec.ToPackage(packageSpec)
			pkg.SpecRev = rev
			docs.AddDocs(pkg)
			if len(*restrict) > 0 {
				performRestriction(pkg, *restrict)
			}
			if err := pkg.GeneratePackage(*outDir); err != nil {
				log.Fatalln("error generating package:", err)
			}
			break
		}
	}
	if pkg == nil {
		log.Fatalln("unable to generate package:", packageSpec)
	}
	log.Println("generated package in", *outDir)
}

// Converts a slice string into a simple lookup map.
func lookupMap(s []string) map[string]bool {
	lookup := make(map[string]bool, len(s))
	for _, str := range s {
		lookup[str] = true
	}
	return lookup
}

type jsonRestriction struct {
	Enums     []string
	Functions []string
}

// Reads the given JSON file path into jsonRestriction and filters the package
// accordingly.
func performRestriction(pkg *Package, jsonPath string) {
	data, err := ioutil.ReadFile(jsonPath)
	if err != nil {
		log.Fatalln("error reading JSON restriction file:", err)
	}
	var r jsonRestriction
	if err = json.Unmarshal(data, &r); err != nil {
		log.Fatalln("error parsing JSON restriction file:", err)
	}
	pkg.Filter(lookupMap(r.Enums), lookupMap(r.Functions))
}

func parseSpecifications(xmlDir string) ([]*Specification, string) {
	specDir := filepath.Join(xmlDir, "spec")
	specFiles, err := ioutil.ReadDir(specDir)
	if err != nil {
		log.Fatalln("error reading spec file entries:", err)
	}

	specs := make([]*Specification, 0, len(specFiles))
	for _, specFile := range specFiles {
		if !strings.HasSuffix(specFile.Name(), "xml") {
			continue
		}
		spec, err := NewSpecification(filepath.Join(specDir, specFile.Name()))
		if err != nil {
			log.Fatalln("error parsing specification:", specFile.Name(), err)
		}
		specs = append(specs, spec)
	}

	rev, err := ioutil.ReadFile(filepath.Join(specDir, "REVISION"))
	if err != nil {
		log.Fatalln("error reading spec revision file:", err)
	}

	return specs, string(rev)
}

func parseDocumentation(xmlDir string) Documentation {
	docDir := filepath.Join(xmlDir, "doc")
	docFiles, err := ioutil.ReadDir(docDir)
	if err != nil {
		log.Fatalln("error reading doc file entries:", err)
	}

	docs := make([]string, 0, len(docFiles))
	for _, docFile := range docFiles {
		docs = append(docs, filepath.Join(docDir, docFile.Name()))
	}

	doc, err := NewDocumentation(docs)
	if err != nil {
		log.Fatalln("error parsing documentation:", err)
	}

	return doc
}

// PackageSpec describes a package to be generated.
type PackageSpec struct {
	API          string
	Version      Version
	Profile      string // If "all" overrides the version spec
	TmplDir      string
	AddExtRegexp *regexp.Regexp
	RemExtRegexp *regexp.Regexp
	LenientInit  bool
}

func printUsage(name string) {
	fmt.Printf("Usage: %s command [arguments]\n", name)
	fmt.Println("Commands:")
	fmt.Println("  download  Downloads specification and documentation XML files")
	fmt.Println("  generate  Generates bindings")
	fmt.Printf("Use %s <command> -help for a detailed command description\n", name)
}

func main() {
	name := os.Args[0]
	args := os.Args[1:]

	if len(args) < 1 {
		printUsage(name)
		os.Exit(-1)
	}

	command := args[0]
	switch command {
	case "download":
		download("download", args[1:])
	case "generate":
		generate("generate", args[1:])
	default:
		fmt.Printf("Unknown command: '%s'\n", command)
		printUsage(name)
		os.Exit(-1)
	}
}
<commit_msg>Update flag docs to be consistent with README. (#84)<commit_after>// Command glow generates Go OpenGL bindings. See http://github.com/errcw/glow.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var specURL = "https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api"
var specRegexp = regexp.MustCompile(`^(gl|glx|egl|wgl)\.xml$`)

var docURLs = []string{
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man2",
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man3",
	"https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man4"}
var docRegexp = regexp.MustCompile(`^[ew]?gl[^u_].*\.xml$`)

func download(name string, args []string) {
	flags := flag.NewFlagSet(name, flag.ExitOnError)
	xmlDir := flags.String("d", "xml", "XML directory")
	flags.Parse(args)

	specDir := filepath.Join(*xmlDir, "spec")
	if err := os.MkdirAll(specDir, 0755); err != nil {
		log.Fatalln("error creating specification output directory:", err)
	}

	docDir := filepath.Join(*xmlDir, "doc")
	if err := os.MkdirAll(docDir, 0755); err != nil {
		log.Fatalln("error creating documentation output directory:", err)
	}

	rev, err := DownloadSvnDir(specURL, specRegexp, specDir)
	if err != nil {
		log.Fatalln("error downloading specification files:", err)
	}

	specVersionFile := filepath.Join(specDir, "REVISION")
	if err := ioutil.WriteFile(specVersionFile, []byte(rev), 0644); err != nil {
		log.Fatalln("error writing spec revision metadata file:", err)
	}

	for _, url := range docURLs {
		if _, err := DownloadSvnDir(url, docRegexp, docDir); err != nil {
			log.Fatalln("error downloading documentation files:", err)
		}
	}
}

func generate(name string, args []string) {
	flags := flag.NewFlagSet(name, flag.ExitOnError)
	var (
		xmlDir      = flags.String("xml", importPathToDir("github.com/go-gl/glow/xml"), "XML directory")
		tmplDir     = flags.String("tmpl", importPathToDir("github.com/go-gl/glow/tmpl"), "Template directory")
		outDir      = flags.String("out", "gl", "Output directory")
		api         = flags.String("api", "", "API to generate (e.g., gl)")
		ver         = flags.String("version", "", "API version to generate (e.g., 4.1)")
		profile     = flags.String("profile", "", "API profile to generate (e.g., core)")
		addext      = flags.String("addext", "", "If non-empty, a regular expression describing which extensions to include in addition to those supported by the selected profile; takes precedence over explicit removal")
		remext      = flags.String("remext", "", "If non-empty, a regular expression describing which extensions to exclude")
		restrict    = flags.String("restrict", "", "JSON file of symbols to restrict symbol generation")
		lenientInit = flags.Bool("lenientInit", false, "When true missing functions do not fail Init")
	)
	flags.Parse(args)

	version, err := ParseVersion(*ver)
	if err != nil {
		log.Fatalln("error parsing version:", err)
	}

	var addExtRegexp *regexp.Regexp = nil
	if *addext != "" {
		addExtRegexp, err = regexp.Compile(*addext)
		if err != nil {
			log.Fatalln("error parsing extension inclusion regexp:", err)
		}
	}

	var remExtRegexp *regexp.Regexp = nil
	if *remext != "" {
		remExtRegexp, err = regexp.Compile(*remext)
		if err != nil {
			log.Fatalln("error parsing extension exclusion regexp:", err)
		}
	}

	packageSpec := &PackageSpec{
		API:          *api,
		Version:      version,
		Profile:      *profile,
		TmplDir:      *tmplDir,
		AddExtRegexp: addExtRegexp,
		RemExtRegexp: remExtRegexp,
		LenientInit:  *lenientInit,
	}

	specs, rev := parseSpecifications(*xmlDir)
	docs := parseDocumentation(*xmlDir)

	var pkg *Package
	for _, spec := range specs {
		if spec.HasPackage(packageSpec) {
			pkg = spec.ToPackage(packageSpec)
			pkg.SpecRev = rev
			docs.AddDocs(pkg)
			if len(*restrict) > 0 {
				performRestriction(pkg, *restrict)
			}
			if err := pkg.GeneratePackage(*outDir); err != nil {
				log.Fatalln("error generating package:", err)
			}
			break
		}
	}
	if pkg == nil {
		log.Fatalln("unable to generate package:", packageSpec)
	}
	log.Println("generated package in", *outDir)
}

// Converts a slice string into a simple lookup map.
func lookupMap(s []string) map[string]bool {
	lookup := make(map[string]bool, len(s))
	for _, str := range s {
		lookup[str] = true
	}
	return lookup
}

type jsonRestriction struct {
	Enums     []string
	Functions []string
}

// Reads the given JSON file path into jsonRestriction and filters the package
// accordingly.
func performRestriction(pkg *Package, jsonPath string) {
	data, err := ioutil.ReadFile(jsonPath)
	if err != nil {
		log.Fatalln("error reading JSON restriction file:", err)
	}
	var r jsonRestriction
	if err = json.Unmarshal(data, &r); err != nil {
		log.Fatalln("error parsing JSON restriction file:", err)
	}
	pkg.Filter(lookupMap(r.Enums), lookupMap(r.Functions))
}

func parseSpecifications(xmlDir string) ([]*Specification, string) {
	specDir := filepath.Join(xmlDir, "spec")
	specFiles, err := ioutil.ReadDir(specDir)
	if err != nil {
		log.Fatalln("error reading spec file entries:", err)
	}

	specs := make([]*Specification, 0, len(specFiles))
	for _, specFile := range specFiles {
		if !strings.HasSuffix(specFile.Name(), "xml") {
			continue
		}
		spec, err := NewSpecification(filepath.Join(specDir, specFile.Name()))
		if err != nil {
			log.Fatalln("error parsing specification:", specFile.Name(), err)
		}
		specs = append(specs, spec)
	}

	rev, err := ioutil.ReadFile(filepath.Join(specDir, "REVISION"))
	if err != nil {
		log.Fatalln("error reading spec revision file:", err)
	}

	return specs, string(rev)
}

func parseDocumentation(xmlDir string) Documentation {
	docDir := filepath.Join(xmlDir, "doc")
	docFiles, err := ioutil.ReadDir(docDir)
	if err != nil {
		log.Fatalln("error reading doc file entries:", err)
	}

	docs := make([]string, 0, len(docFiles))
	for _, docFile := range docFiles {
		docs = append(docs, filepath.Join(docDir, docFile.Name()))
	}

	doc, err := NewDocumentation(docs)
	if err != nil {
		log.Fatalln("error parsing documentation:", err)
	}

	return doc
}

// PackageSpec describes a package to be generated.
type PackageSpec struct {
	API          string
	Version      Version
	Profile      string // If "all" overrides the version spec
	TmplDir      string
	AddExtRegexp *regexp.Regexp
	RemExtRegexp *regexp.Regexp
	LenientInit  bool
}

func printUsage(name string) {
	fmt.Printf("Usage: %s command [arguments]\n", name)
	fmt.Println("Commands:")
	fmt.Println("  download  Downloads specification and documentation XML files")
	fmt.Println("  generate  Generates bindings")
	fmt.Printf("Use %s <command> -help for a detailed command description\n", name)
}

func main() {
	name := os.Args[0]
	args := os.Args[1:]

	if len(args) < 1 {
		printUsage(name)
		os.Exit(-1)
	}

	command := args[0]
	switch command {
	case "download":
		download("download", args[1:])
	case "generate":
		generate("generate", args[1:])
	default:
		fmt.Printf("Unknown command: '%s'\n", command)
		printUsage(name)
		os.Exit(-1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/streadway/amqp"
)

var (
	uri          = flag.String("uri", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	insecure_tls = flag.Bool("insecure-tls", false, "Insecure TLS mode: don't check certificates")
	queue        = flag.String("queue", "", "AMQP queue name")
	maxMessages  = flag.Uint("max-messages", 1000, "Maximum number of messages to dump")
	outputDir    = flag.String("output-dir", ".", "Directory in which to save the dumped messages")
	full         = flag.Bool("full", false, "Dump the message, its properties and headers")
	verbose      = flag.Bool("verbose", false, "Print progress")
)

func main() {
	flag.Parse()
	if flag.NArg() > 0 {
		fmt.Fprintf(os.Stderr, "Error: Unused command line arguments detected.\n")
		flag.Usage();
		os.Exit(2)
	}
	err := DumpMessagesFromQueue(*uri, *queue, *maxMessages, *outputDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}

func dial(amqpURI string) (*amqp.Connection, error) {
	VerboseLog(fmt.Sprintf("Dialing %q", amqpURI))
	if *insecure_tls && strings.HasPrefix(amqpURI, "amqps://") {
		tlsConfig := new(tls.Config)
		tlsConfig.InsecureSkipVerify = true
		conn, err := amqp.DialTLS(amqpURI, tlsConfig)
		return conn, err
	}
	conn, err := amqp.Dial(amqpURI)
	return conn, err
}

func DumpMessagesFromQueue(amqpURI string, queueName string, maxMessages uint, outputDir string) error {
	if queueName == "" {
		return fmt.Errorf("Must supply queue name")
	}

	conn, err := dial(amqpURI)
	if err != nil {
		return fmt.Errorf("Dial: %s", err)
	}

	defer func() {
		conn.Close()
		VerboseLog("AMQP connection closed")
	}()

	channel, err := conn.Channel()
	if err != nil {
		return fmt.Errorf("Channel: %s", err)
	}

	VerboseLog(fmt.Sprintf("Pulling messages from queue %q", queueName))
	for messagesReceived := uint(0); messagesReceived < maxMessages; messagesReceived++ {
		msg, ok, err := channel.Get(queueName,
			false, // autoAck
		)
		if err != nil {
			return fmt.Errorf("Queue get: %s", err)
		}

		if !ok {
			VerboseLog("No more messages in queue")
			break
		}

		err = SaveMessageToFile(msg.Body, outputDir, messagesReceived)
		if err != nil {
			return fmt.Errorf("Save message: %s", err)
		}

		if *full {
			err = SavePropsAndHeadersToFile(msg, outputDir, messagesReceived)
			if err != nil {
				return fmt.Errorf("Save props and headers: %s", err)
			}
		}
	}

	return nil
}

func SaveMessageToFile(body []byte, outputDir string, counter uint) error {
	filePath := GenerateFilePath(outputDir, counter)
	err := ioutil.WriteFile(filePath, body, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func GetProperties(msg amqp.Delivery) map[string]interface{} {
	props := map[string]interface{}{
		"app_id":           msg.AppId,
		"content_encoding": msg.ContentEncoding,
		"content_type":     msg.ContentType,
		"correlation_id":   msg.CorrelationId,
		"delivery_mode":    msg.DeliveryMode,
		"expiration":       msg.Expiration,
		"message_id":       msg.MessageId,
		"priority":         msg.Priority,
		"reply_to":         msg.ReplyTo,
		"type":             msg.Type,
		"user_id":          msg.UserId,
	}

	if !msg.Timestamp.IsZero() {
		props["timestamp"] = msg.Timestamp.String()
	}

	for k, v := range props {
		if v == "" {
			delete(props, k)
		}
	}

	return props
}

func SavePropsAndHeadersToFile(msg amqp.Delivery, outputDir string, counter uint) error {
	extras := make(map[string]interface{})
	extras["properties"] = GetProperties(msg)
	extras["headers"] = msg.Headers

	data, err := json.MarshalIndent(extras, "", "  ")
	if err != nil {
		return err
	}

	filePath := GenerateFilePath(outputDir, counter) + "-headers+properties.json"
	err = ioutil.WriteFile(filePath, data, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func GenerateFilePath(outputDir string, counter uint) string {
	return path.Join(outputDir, fmt.Sprintf("msg-%04d", counter))
}

func VerboseLog(msg string) {
	if *verbose {
		fmt.Println("*", msg)
	}
}
<commit_msg>Update main.go<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/streadway/amqp"
)

var (
	uri          = flag.String("uri", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	insecure_tls = flag.Bool("insecure-tls", false, "Insecure TLS mode: don't check certificates")
	queue        = flag.String("queue", "", "AMQP queue name")
        ack          = flag.Bool("ack", false, "Acknowledge messages")
	maxMessages  = flag.Uint("max-messages", 1000, "Maximum number of messages to dump")
	outputDir    = flag.String("output-dir", ".", "Directory in which to save the dumped messages")
	full         = flag.Bool("full", false, "Dump the message, its properties and headers")
	verbose      = flag.Bool("verbose", false, "Print progress")
)

func main() {
	flag.Parse()
	if flag.NArg() > 0 {
		fmt.Fprintf(os.Stderr, "Error: Unused command line arguments detected.\n")
		flag.Usage();
		os.Exit(2)
	}
	err := DumpMessagesFromQueue(*uri, *queue, *maxMessages, *outputDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}

func dial(amqpURI string) (*amqp.Connection, error) {
	VerboseLog(fmt.Sprintf("Dialing %q", amqpURI))
	if *insecure_tls && strings.HasPrefix(amqpURI, "amqps://") {
		tlsConfig := new(tls.Config)
		tlsConfig.InsecureSkipVerify = true
		conn, err := amqp.DialTLS(amqpURI, tlsConfig)
		return conn, err
	}
	conn, err := amqp.Dial(amqpURI)
	return conn, err
}

func DumpMessagesFromQueue(amqpURI string, queueName string, maxMessages uint, outputDir string) error {
	if queueName == "" {
		return fmt.Errorf("Must supply queue name")
	}

	conn, err := dial(amqpURI)
	if err != nil {
		return fmt.Errorf("Dial: %s", err)
	}

	defer func() {
		conn.Close()
		VerboseLog("AMQP connection closed")
	}()

	channel, err := conn.Channel()
	if err != nil {
		return fmt.Errorf("Channel: %s", err)
	}

	VerboseLog(fmt.Sprintf("Pulling messages from queue %q", queueName))
	for messagesReceived := uint(0); messagesReceived < maxMessages; messagesReceived++ {
		msg, ok, err := channel.Get(queueName,
			*ack, // autoAck
		)
		if err != nil {
			return fmt.Errorf("Queue get: %s", err)
		}

		if !ok {
			VerboseLog("No more messages in queue")
			break
		}

		err = SaveMessageToFile(msg.Body, outputDir, messagesReceived)
		if err != nil {
			return fmt.Errorf("Save message: %s", err)
		}

		if *full {
			err = SavePropsAndHeadersToFile(msg, outputDir, messagesReceived)
			if err != nil {
				return fmt.Errorf("Save props and headers: %s", err)
			}
		}
	}

	return nil
}

func SaveMessageToFile(body []byte, outputDir string, counter uint) error {
	filePath := GenerateFilePath(outputDir, counter)
	err := ioutil.WriteFile(filePath, body, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func GetProperties(msg amqp.Delivery) map[string]interface{} {
	props := map[string]interface{}{
		"app_id":           msg.AppId,
		"content_encoding": msg.ContentEncoding,
		"content_type":     msg.ContentType,
		"correlation_id":   msg.CorrelationId,
		"delivery_mode":    msg.DeliveryMode,
		"expiration":       msg.Expiration,
		"message_id":       msg.MessageId,
		"priority":         msg.Priority,
		"reply_to":         msg.ReplyTo,
		"type":             msg.Type,
		"user_id":          msg.UserId,
	}

	if !msg.Timestamp.IsZero() {
		props["timestamp"] = msg.Timestamp.String()
	}

	for k, v := range props {
		if v == "" {
			delete(props, k)
		}
	}

	return props
}

func SavePropsAndHeadersToFile(msg amqp.Delivery, outputDir string, counter uint) error {
	extras := make(map[string]interface{})
	extras["properties"] = GetProperties(msg)
	extras["headers"] = msg.Headers

	data, err := json.MarshalIndent(extras, "", "  ")
	if err != nil {
		return err
	}

	filePath := GenerateFilePath(outputDir, counter) + "-headers+properties.json"
	err = ioutil.WriteFile(filePath, data, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func GenerateFilePath(outputDir string, counter uint) string {
	return path.Join(outputDir, fmt.Sprintf("msg-%04d", counter))
}

func VerboseLog(msg string) {
	if *verbose {
		fmt.Println("*", msg)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
)

func Missing(paths ...string) bool {
	for _, path := range paths {
		if _, err := os.Stat(path); os.IsNotExist(err) {
			return true
		}
	}
	return false
}

func main() {
	caCrt := "cacert.crt"
	caKey := "cacert.key"
	/* If doesn't exist, create the CA  */

	commonName := flag.String("common-name", "", "CN of the cert")
	org := flag.String("org", "Widgets, Inc", "Org of the cert")
	certType := flag.String("type", "client", "client or server")
	flag.Parse()

	if *commonName == "" {
		flag.Usage()
		return
	}

	if Missing(caCrt, caKey) {
		fmt.Printf("CA Cert missing, re-creating\n\n")
		if err := GenerateCACertificate(
			caCrt, caKey,
			*org, "minica.example.com",
			2048,
		); err != nil {
			panic(err)
		}
	}

	isClientCert := false
	switch *certType {
	case "client":
		isClientCert = true
	case "server":
		isClientCert = false
	default:
		panic(fmt.Errorf("Unknown type"))
	}

	cn := *commonName
	newCrt := fmt.Sprintf("%s.crt", cn)
	newKey := fmt.Sprintf("%s.key", cn)

	fmt.Printf(`Creating a %s cert:

Common Name: %s
Org:         %s
Cert Flavor: %s
Output crt:  %s
Output key:  %s
`, *certType, *commonName, *org, *certType, newCrt, newKey)

	if err := GenerateCert(
		[]string{cn},
		newCrt, newKey, caCrt, caKey,
		*org, cn,
		2048,
		isClientCert,
	); err != nil {
		panic(err)
	}
}
<commit_msg>use config<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"pault.ag/go/config"
)

func Missing(paths ...string) bool {
	for _, path := range paths {
		if _, err := os.Stat(path); os.IsNotExist(err) {
			return true
		}
	}
	return false
}

type MiniCA struct {
	KeySize      int    `flag:"key-size"       description:"Key Size"`
	CommonName   string `flag:"common-name"    description:"Common Name of the Cert"`
	Org          string `flag:"conf.Org"       description:"Organization of the Cert"`
	Type         string `flag:"type"           description:"Cert Type (client or server)"`
	CaCommonName string `flag:"ca-common-name" description:"Common Name of the CA Cert"`
	CaCert       string `flag:"ca-cert"        description:"Path to the CA Cert"`
	CaKey        string `flag:"ca-key"         description:"Path to the CA Key"`
	CaKeySize    int    `flag:"ca-key-size"    description:"CA Key Size"`
}

func main() {

	conf := MiniCA{}
	flags, err := config.LoadFlags("minica", &conf)
	if err != nil {
		panic(err)
	}

	flags.Parse(os.Args[1:])

	if conf.CommonName == "" {
		flag.Usage()
		return
	}

	if Missing(conf.CaCert, conf.CaKey) {
		if err := GenerateCACertificate(
			conf.CaCert, conf.CaKey,
			conf.Org, conf.CaCommonName,
			conf.CaKeySize,
		); err != nil {
			panic(err)
		}
	}

	isClientCert := false
	switch conf.Type {
	case "client":
		isClientCert = true
	case "server":
		isClientCert = false
	default:
		panic(fmt.Errorf("Unknown type"))
	}

	cn := conf.CommonName
	newCrt := fmt.Sprintf("%s.crt", cn)
	newKey := fmt.Sprintf("%s.key", cn)

	fmt.Printf(`Creating a %s cert:

Common Name: %s
Org:         %s
Cert Flavor: %s
Output crt:  %s
Output key:  %s
`, conf.Type, conf.CommonName, conf.Org, conf.Type, newCrt, newKey)

	if err := GenerateCert(
		[]string{cn},
		newCrt, newKey, conf.CaCert, conf.CaKey,
		conf.Org, cn,
		conf.KeySize,
		isClientCert,
	); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
  "net/http"
  "os"
  "os/exec"
  "log"
  "fmt"
  "strings"
)

/*
 * POST /build/:host/:user/:name
 */
func JekyllBuild(rw http.ResponseWriter, r *http.Request) {
  // webhook must be POST
  if r.Method != "POST" {
    rw.WriteHeader(http.StatusNotFound)
    return
  }

  url := strings.Split(r.URL.Path, "/")
  host, user, name := url[2], url[3], url[4]
  tmp := "/tmp"

  dir  := tmp + "/src/" + name
  dest := tmp + "/build/" + name
  repo := "git@" + host + ":" + user + "/" + name + ".git"

  cmd := []string{
    "git clone %[2]s %[1]s &&",
    "cd %[1]s;",
    // "git checkout master",
    "[ -f Gemfile ] && bundle install;",
    "jekyll build -s %[1]s -d %[3]s;",
    "rm -Rf %[1]s;"}

  log.Println("-----> Cloning " + repo)
  log.Println("-----> Building Jekyll site ...")
  out, err := exec.Command("sh", "-c", fmt.Sprintf(strings.Join(cmd, " "), dir, repo, dest)).Output()
  log.Println(string(out))
  if err != nil {
    log.Println("ERROR: %s", err)
    rw.WriteHeader(http.StatusInternalServerError)
    return
  }
  log.Println("-----> Jekyll site built successfully.")

  status, message := JekyllPublish(dest)
  log.Println(message)

  rw.WriteHeader(status)
}

func JekyllPublish(dir string) (int, string) {

  // Find S3 Bucket location from the BUCKET file
  bucket, err := exec.Command("sh", "-c", fmt.Sprintf("cd %s && cat BUCKET", dir)).Output()
  if err != nil {
    return 500, "No bucket specified"
  }

  // Sync files to S3
  log.Println("-----> Publishing to Amazon S3 Bucket %s...\n", bucket)
  out, err := exec.Command(
    "s3cmd",
    "sync",
    dir + "/",
    "s3://" + string(bucket),
    "--delete-removed",
    "--acl-public",
    "--add-header=Cache-Control:max-age=60",
  ).CombinedOutput()
  log.Println("%s", out)
  if err != nil {
    log.Println("%s", err)
    return 500, "Problem syncing"
  }

  // TODO Optional - Use rsync to remote web server
  // rsync -avz --delete _site/ location:/var/www/html/jekyll

  // remove build
  os.RemoveAll(dir)

  return 200, "Success"
}

func main() {
  http.HandleFunc("/build/", JekyllBuild)
  port := os.Getenv("PORT")
  if port == "" {
      port = "8080"
  }
  http.ListenAndServe(":"+port, nil)
}

<commit_msg>cleaned up loggin<commit_after>package main

import (
  "net/http"
  "os"
  "os/exec"
  "log"
  "fmt"
  "strings"
)

/*
 * POST /build/:host/:user/:name
 */
func JekyllBuild(rw http.ResponseWriter, r *http.Request) {
  // webhook must be POST
  if r.Method != "POST" {
    rw.WriteHeader(http.StatusNotFound)
    return
  }

  url := strings.Split(r.URL.Path, "/")
  host, user, name := url[2], url[3], url[4]
  tmp := "/tmp"

  dir  := tmp + "/src/" + name
  dest := tmp + "/build/" + name
  repo := "git@" + host + ":" + user + "/" + name + ".git"

  cmd := []string{
    "git clone %[2]s %[1]s &&",
    "cd %[1]s;",
    // "git checkout master",
    "[ -f Gemfile ] && bundle install;",
    "jekyll build -s %[1]s -d %[3]s;",
    "rm -Rf %[1]s;"}

  log.Println("-----> Cloning " + repo)
  log.Println("-----> Building Jekyll site ...")
  out, err := exec.Command("sh", "-c", fmt.Sprintf(strings.Join(cmd, " "), dir, repo, dest)).Output()
  log.Printf("%s\n", out)
  if err != nil {
    log.Printf("ERROR: %s\n", err)
    rw.WriteHeader(http.StatusInternalServerError)
    return
  }
  log.Println("-----> Jekyll site built successfully.")

  status, message := JekyllPublish(dest)
  log.Println(message)

  rw.WriteHeader(status)
}

func JekyllPublish(dir string) (int, string) {

  // Find S3 Bucket location from the BUCKET file
  bucket, err := exec.Command("sh", "-c", fmt.Sprintf("cd %s && cat BUCKET", dir)).Output()
  if err != nil {
    return 500, "No bucket specified"
  }

  // Sync files to S3
  log.Printf("-----> Publishing to Amazon S3 Bucket %s...\n", bucket)
  out, err := exec.Command(
    "s3cmd",
    "sync",
    dir + "/",
    "s3://" + string(bucket),
    "--delete-removed",
    "--acl-public",
    "--add-header=Cache-Control:max-age=60",
  ).CombinedOutput()
  log.Printf("%s\n", out)
  if err != nil {
    log.Printf("%s\n", err)
    return 500, "Problem syncing"
  }

  // TODO Optional - Use rsync to remote web server
  // rsync -avz --delete _site/ location:/var/www/html/jekyll

  // remove build
  os.RemoveAll(dir)

  return 200, "Success"
}

func main() {
  http.HandleFunc("/build/", JekyllBuild)
  port := os.Getenv("PORT")
  if port == "" {
      port = "8080"
  }
  http.ListenAndServe(":"+port, nil)
}

<|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/

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/st3fan/moz-storageserver/storageserver"
	"log"
	"net/http"
)

const (
	DEFAULT_API_PREFIX         = "/storage"
	DEFAULT_API_LISTEN_ADDRESS = "0.0.0.0"
	DEFAULT_API_LISTEN_PORT    = 8124
)

func VersionHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`{"version":"1.0"}`)) // TODO: How can we easily embed the git rev and tag in here?
}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/version", VersionHandler)

	config := storageserver.DefaultConfig() // TODO: Get this from command line options

	_, err := storageserver.SetupRouter(router.PathPrefix(DEFAULT_API_PREFIX).Subrouter(), config)
	if err != nil {
		log.Fatal(err)
	}

	addr := fmt.Sprintf("%s:%d", DEFAULT_API_LISTEN_ADDRESS, DEFAULT_API_LISTEN_PORT)
	log.Printf("Starting storage server on http://%s", addr)
	http.Handle("/", router)
	err = http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Forcing a build<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/

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/st3fan/moz-storageserver/storageserver"
	"log"
	"net/http"
)

const (
	DEFAULT_API_PREFIX         = "/storage"
	DEFAULT_API_LISTEN_ADDRESS = "0.0.0.0"
	DEFAULT_API_LISTEN_PORT    = 8124
)

func VersionHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`{"version":"1.0"}`)) // TODO: How can we easily embed the git rev and tag in here?
}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/version", VersionHandler)

	config := storageserver.DefaultConfig()

	_, err := storageserver.SetupRouter(router.PathPrefix(DEFAULT_API_PREFIX).Subrouter(), config)
	if err != nil {
		log.Fatal(err)
	}

	addr := fmt.Sprintf("%s:%d", DEFAULT_API_LISTEN_ADDRESS, DEFAULT_API_LISTEN_PORT)
	log.Printf("Starting storage server on http://%s", addr)
	http.Handle("/", router)
	err = http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

//go:generate ./gen-license.sh

import (
	"fmt"
	"io"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"github.com/alexflint/go-arg"

	"github.com/knq/usql/drivers"
	"github.com/knq/usql/handler"
	"github.com/knq/usql/rline"
)

func main() {
	// circumvent all logic to determine if usql was built with support for a specific driver
	if len(os.Args) == 2 &&
		strings.HasPrefix(os.Args[1], "--has-") &&
		strings.HasSuffix(os.Args[1], "-support") {

		n := os.Args[1][6 : len(os.Args[1])-8]
		if v, ok := drivers.KnownDrivers[n]; ok {
			n = v
		}

		var out int
		if _, ok := drivers.Drivers[n]; ok {
			out = 1
		}
		fmt.Fprintf(os.Stdout, "%d", out)
		return
	}

	var err error

	// load current user
	cur, err := user.Current()
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	// parse args
	args := &Args{
		Username:    cur.Username,
		HistoryFile: filepath.Join(cur.HomeDir, ".usql_history"),
	}
	arg.MustParse(args)

	// run
	err = run(args, cur)
	if err != nil && err != io.EOF && err != rline.ErrInterrupt {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)

		// extra output for when the oracle driver is not available
		if e, ok := err.(*handler.Error); ok && e.Err == handler.ErrDriverNotAvailable {
			tag := e.Driver
			if _, ok := drivers.KnownDrivers[tag]; !ok {
				for k, v := range drivers.KnownDrivers {
					if v == tag {
						tag = k
						break
					}
				}
			}

			fmt.Fprint(os.Stderr, "\ntry:\n\n  go get -u -tags "+tag+" github.com/knq/usql\n\n")
		}
		os.Exit(1)
	}
}

// run processes args, processing args.Commands if non-empty, or args.File if
// specified, otherwise launch an interactive readline from stdin.
func run(args *Args, u *user.User) error {
	var err error

	// get working directory
	wd, err := os.Getwd()
	if err != nil {
		return err
	}

	// setup input/output
	l, err := setup(args, u)
	if err != nil {
		return err
	}

	// create handler
	h := handler.New(l, u, wd)

	// open dsn
	err = h.Open(args.DSN)
	if err != nil {
		return err
	}

	return h.Run()
}

// setup sets up the input/output based on args.
func setup(args *Args, u *user.User) (rline.IO, error) {
	if len(args.Commands) != 0 {
		return rline.Commands(args.Commands)
	}

	// create readline instance
	return rline.New(args.File, args.Out, args.HistoryFile)
}
<commit_msg>Adding missing Close() call<commit_after>package main

//go:generate ./gen-license.sh

import (
	"fmt"
	"io"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"github.com/alexflint/go-arg"

	"github.com/knq/usql/drivers"
	"github.com/knq/usql/handler"
	"github.com/knq/usql/rline"
)

func main() {
	// circumvent all logic to determine if usql was built with support for a specific driver
	if len(os.Args) == 2 &&
		strings.HasPrefix(os.Args[1], "--has-") &&
		strings.HasSuffix(os.Args[1], "-support") {

		n := os.Args[1][6 : len(os.Args[1])-8]
		if v, ok := drivers.KnownDrivers[n]; ok {
			n = v
		}

		var out int
		if _, ok := drivers.Drivers[n]; ok {
			out = 1
		}
		fmt.Fprintf(os.Stdout, "%d", out)
		return
	}

	var err error

	// load current user
	cur, err := user.Current()
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	// parse args
	args := &Args{
		Username:    cur.Username,
		HistoryFile: filepath.Join(cur.HomeDir, ".usql_history"),
	}
	arg.MustParse(args)

	// run
	err = run(args, cur)
	if err != nil && err != io.EOF && err != rline.ErrInterrupt {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)

		// extra output for when the oracle driver is not available
		if e, ok := err.(*handler.Error); ok && e.Err == handler.ErrDriverNotAvailable {
			tag := e.Driver
			if _, ok := drivers.KnownDrivers[tag]; !ok {
				for k, v := range drivers.KnownDrivers {
					if v == tag {
						tag = k
						break
					}
				}
			}

			fmt.Fprint(os.Stderr, "\ntry:\n\n  go get -u -tags "+tag+" github.com/knq/usql\n\n")
		}
		os.Exit(1)
	}
}

// run processes args, processing args.Commands if non-empty, or args.File if
// specified, otherwise launch an interactive readline from stdin.
func run(args *Args, u *user.User) error {
	var err error

	// get working directory
	wd, err := os.Getwd()
	if err != nil {
		return err
	}

	// setup input/output
	l, err := setup(args, u)
	if err != nil {
		return err
	}
	defer l.Close()

	// create handler
	h := handler.New(l, u, wd)

	// open dsn
	err = h.Open(args.DSN)
	if err != nil {
		return err
	}

	return h.Run()
}

// setup sets up the input/output based on args.
func setup(args *Args, u *user.User) (rline.IO, error) {
	if len(args.Commands) != 0 {
		return rline.Commands(args.Commands)
	}

	// create readline instance
	return rline.New(args.File, args.Out, args.HistoryFile)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"sort"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/jessevdk/go-flags"
	"github.com/yosisa/craft/config"
	"github.com/yosisa/craft/docker"
	"github.com/yosisa/craft/filter"
	"github.com/yosisa/craft/rpc"
)

type GlobalOptions struct {
	Config string `short:"c" long:"config" description:"Configuration file"`
	Agents string `long:"agents" description:"Comma separated agent list" env:"CRAFT_AGENTS"`
	Filter string `short:"F" long:"filter" description:"Filter target agents" env:"CRAFT_FILTER"`
	conf   *config.Config
}

func (opts *GlobalOptions) ParseConfig() *config.Config {
	var err error
	if opts.conf, err = config.Parse(opts.Config); err != nil {
		log.WithField("error", err).Fatal("Could not parse config file")
	}
	if opts.Agents != "" {
		opts.conf.Agents = strings.Split(opts.Agents, ",")
	}
	return opts.conf
}

func (opts *GlobalOptions) agents() []string {
	if opts.conf == nil {
		opts.ParseConfig()
	}
	v, err := filterAgents(opts.conf.Agents, opts.Filter)
	if err != nil {
		log.WithField("error", err).Fatal("Failed to filter target agents")
	}
	return v
}

func filterAgents(agents []string, s string) ([]string, error) {
	if s == "" {
		return agents, nil
	}
	expr, err := filter.Parse(s)
	if err != nil {
		return nil, err
	}
	caps := gatherCapabilities(agents)
	caps.Filter(func(cap *rpc.Capability) bool {
		return expr.Eval(cap)
	})
	var out []string
	for agent := range caps {
		out = append(out, agent)
	}
	return out, nil
}

var (
	gopts  GlobalOptions
	parser = flags.NewParser(&gopts, flags.Default|flags.IgnoreUnknown)
)

func main() {
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU())
	}
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}
}

type Capabilities map[string]*rpc.Capability

func (c Capabilities) Filter(f func(*rpc.Capability) bool) {
	for agent, cap := range c {
		if !f(cap) {
			delete(c, agent)
		}
	}
}

func (c Capabilities) Copy() Capabilities {
	caps := make(Capabilities, len(c))
	for agent, cap := range c {
		caps[agent] = cap
	}
	return caps
}

func (c Capabilities) Agents() []string {
	out := make([]string, 0, len(c))
	for agent := range c {
		out = append(out, agent)
	}
	return out
}

func gatherCapabilities(agents []string) Capabilities {
	var wg sync.WaitGroup
	wg.Add(len(agents))
	caps := make(Capabilities)
	for _, agent := range agents {
		func(agent string) {
			defer wg.Done()
			c, err := rpc.Dial("tcp", agent)
			if err != nil {
				log.WithFields(log.Fields{"error": err, "agent": agent}).Error("Failed to connect agent")
				return
			}
			defer c.Close()

			var cap rpc.Capability
			if err = c.Call("Craft.Capability", rpc.Empty{}, &cap); err != nil {
				log.WithFields(log.Fields{"error": err, "method": "Craft.Capability"}).Error("RPC failed")
				return
			}
			if !cap.Available {
				log.WithField("agent", agent).Info("Temporary unavailable")
				return
			}
			caps[agent] = &cap
		}(agent)
	}
	wg.Wait()
	return caps
}

func findBestAgent(m *docker.Manifest, caps Capabilities) string {
	// Check existence of a container to be replaced
	if m.Replace != "" {
		caps.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.AllNames).Contains(m.Replace)
		})
	}

	// Check availability of name
	caps2 := caps.Copy()
	caps.Filter(func(cap *rpc.Capability) bool {
		return !stringSlice(cap.UsedNames).Contains(m.Name)
	})
	if len(caps) == 0 && m.Name == m.Replace {
		caps = caps2
	}

	// Check availability of ports
	caps.Filter(func(cap *rpc.Capability) bool {
		for _, p := range m.Ports {
			becomeAvailable, ok := cap.Containers[m.Replace]
			if ok && portSpecSlice(becomeAvailable.Ports).Contains(p.HostPort) {
				continue
			}
			if int64Slice(cap.UsedPorts).Contains(p.HostPort) {
				return false
			}
		}
		return true
	})

	// Check existence of containers to be linked
	caps.Filter(func(cap *rpc.Capability) bool {
		for _, link := range m.Links {
			if !stringSlice(cap.UsedNames).Contains(link.Name) {
				return false
			}
		}
		return true
	})

	// Check existence of volume containers
	if len(m.VolumesFrom) > 0 {
		for _, volume := range m.VolumesFrom {
			caps.Filter(func(cap *rpc.Capability) bool {
				return stringSlice(cap.AllNames).Contains(volume)
			})
		}
	}

	// Check existence of a network container
	if strings.HasPrefix(m.NetworkMode, "container:") {
		name := m.NetworkMode[10:]
		caps.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.UsedNames).Contains(name)
		})
	}

	// Agent name restriction
	if m.Restrict.Agent != "" {
		re := regexp.MustCompile(m.Restrict.Agent)
		caps.Filter(func(cap *rpc.Capability) bool {
			return re.MatchString(cap.Agent)
		})
	}

	// Conflicts restriction
	for _, conflict := range m.Restrict.Conflicts {
		re := regexp.MustCompile(conflict)
		caps.Filter(func(cap *rpc.Capability) bool {
			return !stringSlice(cap.UsedNames).Match(re)
		})
	}

	// Choice agent that has least active containers
	running := 1024 * 1024 * 1024 // it's large enough
	var agent string
	for addr, cap := range caps {
		if n := len(cap.UsedNames); n < running {
			running = n
			agent = addr
		}
	}
	return agent
}

func resolveExLinks(m *docker.Manifest, caps Capabilities) ([]*rpc.ExLink, error) {
	var out []*rpc.ExLink
	for _, l := range m.ExLinks {
		caps2 := caps.Copy()
		caps2.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.UsedNames).Contains(l.Name) &&
				len(cap.IPAddrs) > 0
		})
		if len(caps2) == 0 {
			return nil, errors.New("No linkable containers")
		}
		_, cap := choice(caps2)
		ci := cap.Containers[l.Name]
		for _, port := range ci.Ports {
			addr := port.HostIP
			if addr == "0.0.0.0" {
				addr = cap.IPAddrs[0]
			}
			out = append(out, &rpc.ExLink{
				Name:    l.Alias,
				Exposed: string(port.Exposed),
				Addr:    addr,
				Port:    int(port.HostPort),
			})
		}
	}
	return out, nil
}

func choice(caps Capabilities) (string, *rpc.Capability) {
	var keys []string
	for k := range caps {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	n := rand.Intn(len(keys))
	return keys[n], caps[keys[n]]
}

type stringSlice []string

func (ss stringSlice) Contains(s string) bool {
	for _, v := range ss {
		if v == s {
			return true
		}
	}
	return false
}

func (ss stringSlice) Match(re *regexp.Regexp) bool {
	for _, v := range ss {
		if re.MatchString(v) {
			return true
		}
	}
	return false
}

type int64Slice []int64

func (is int64Slice) Contains(n int64) bool {
	for _, v := range is {
		if v == n {
			return true
		}
	}
	return false
}

type portSpecSlice []*docker.PortSpec

func (ps portSpecSlice) Contains(n int64) bool {
	for _, v := range ps {
		if v.HostPort == n {
			return true
		}
	}
	return false
}

func logRPCError(err error) {
	if err == nil {
		return
	}
	if re, ok := err.(rpc.Error); ok {
		re.Each(func(addr string, err error) {
			fields := log.Fields{"error": strings.TrimSpace(err.Error()), "agent": addr}
			log.WithFields(fields).Error("RPC error")
		})
	} else {
		log.WithField("error", err).Error("RPC error")
	}
}
<commit_msg>Fix name checking in case of non-running container exists<commit_after>package main

import (
	"errors"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"sort"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/jessevdk/go-flags"
	"github.com/yosisa/craft/config"
	"github.com/yosisa/craft/docker"
	"github.com/yosisa/craft/filter"
	"github.com/yosisa/craft/rpc"
)

type GlobalOptions struct {
	Config string `short:"c" long:"config" description:"Configuration file"`
	Agents string `long:"agents" description:"Comma separated agent list" env:"CRAFT_AGENTS"`
	Filter string `short:"F" long:"filter" description:"Filter target agents" env:"CRAFT_FILTER"`
	conf   *config.Config
}

func (opts *GlobalOptions) ParseConfig() *config.Config {
	var err error
	if opts.conf, err = config.Parse(opts.Config); err != nil {
		log.WithField("error", err).Fatal("Could not parse config file")
	}
	if opts.Agents != "" {
		opts.conf.Agents = strings.Split(opts.Agents, ",")
	}
	return opts.conf
}

func (opts *GlobalOptions) agents() []string {
	if opts.conf == nil {
		opts.ParseConfig()
	}
	v, err := filterAgents(opts.conf.Agents, opts.Filter)
	if err != nil {
		log.WithField("error", err).Fatal("Failed to filter target agents")
	}
	return v
}

func filterAgents(agents []string, s string) ([]string, error) {
	if s == "" {
		return agents, nil
	}
	expr, err := filter.Parse(s)
	if err != nil {
		return nil, err
	}
	caps := gatherCapabilities(agents)
	caps.Filter(func(cap *rpc.Capability) bool {
		return expr.Eval(cap)
	})
	var out []string
	for agent := range caps {
		out = append(out, agent)
	}
	return out, nil
}

var (
	gopts  GlobalOptions
	parser = flags.NewParser(&gopts, flags.Default|flags.IgnoreUnknown)
)

func main() {
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU())
	}
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}
}

type Capabilities map[string]*rpc.Capability

func (c Capabilities) Filter(f func(*rpc.Capability) bool) {
	for agent, cap := range c {
		if !f(cap) {
			delete(c, agent)
		}
	}
}

func (c Capabilities) Copy() Capabilities {
	caps := make(Capabilities, len(c))
	for agent, cap := range c {
		caps[agent] = cap
	}
	return caps
}

func (c Capabilities) Agents() []string {
	out := make([]string, 0, len(c))
	for agent := range c {
		out = append(out, agent)
	}
	return out
}

func gatherCapabilities(agents []string) Capabilities {
	var wg sync.WaitGroup
	wg.Add(len(agents))
	caps := make(Capabilities)
	for _, agent := range agents {
		func(agent string) {
			defer wg.Done()
			c, err := rpc.Dial("tcp", agent)
			if err != nil {
				log.WithFields(log.Fields{"error": err, "agent": agent}).Error("Failed to connect agent")
				return
			}
			defer c.Close()

			var cap rpc.Capability
			if err = c.Call("Craft.Capability", rpc.Empty{}, &cap); err != nil {
				log.WithFields(log.Fields{"error": err, "method": "Craft.Capability"}).Error("RPC failed")
				return
			}
			if !cap.Available {
				log.WithField("agent", agent).Info("Temporary unavailable")
				return
			}
			caps[agent] = &cap
		}(agent)
	}
	wg.Wait()
	return caps
}

func findBestAgent(m *docker.Manifest, caps Capabilities) string {
	if m.Replace == "" {
		// Check availability of name
		caps.Filter(func(cap *rpc.Capability) bool {
			return !stringSlice(cap.AllNames).Contains(m.Name)
		})
	} else {
		// Check existence of a container to be replaced
		caps.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.AllNames).Contains(m.Replace)
		})
		if m.Name == m.Replace {
			// Already satisfied but prefer non-running container
			caps2 := caps.Copy()
			caps.Filter(func(cap *rpc.Capability) bool {
				return !stringSlice(cap.UsedNames).Contains(m.Name)
			})
			if len(caps) == 0 {
				caps = caps2
			}
		} else {
			caps.Filter(func(cap *rpc.Capability) bool {
				return !stringSlice(cap.AllNames).Contains(m.Name)
			})
		}
	}

	// Check availability of ports
	caps.Filter(func(cap *rpc.Capability) bool {
		for _, p := range m.Ports {
			becomeAvailable, ok := cap.Containers[m.Replace]
			if ok && portSpecSlice(becomeAvailable.Ports).Contains(p.HostPort) {
				continue
			}
			if int64Slice(cap.UsedPorts).Contains(p.HostPort) {
				return false
			}
		}
		return true
	})

	// Check existence of containers to be linked
	caps.Filter(func(cap *rpc.Capability) bool {
		for _, link := range m.Links {
			if !stringSlice(cap.UsedNames).Contains(link.Name) {
				return false
			}
		}
		return true
	})

	// Check existence of volume containers
	if len(m.VolumesFrom) > 0 {
		for _, volume := range m.VolumesFrom {
			caps.Filter(func(cap *rpc.Capability) bool {
				return stringSlice(cap.AllNames).Contains(volume)
			})
		}
	}

	// Check existence of a network container
	if strings.HasPrefix(m.NetworkMode, "container:") {
		name := m.NetworkMode[10:]
		caps.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.UsedNames).Contains(name)
		})
	}

	// Agent name restriction
	if m.Restrict.Agent != "" {
		re := regexp.MustCompile(m.Restrict.Agent)
		caps.Filter(func(cap *rpc.Capability) bool {
			return re.MatchString(cap.Agent)
		})
	}

	// Conflicts restriction
	for _, conflict := range m.Restrict.Conflicts {
		re := regexp.MustCompile(conflict)
		caps.Filter(func(cap *rpc.Capability) bool {
			return !stringSlice(cap.UsedNames).Match(re)
		})
	}

	// Choice agent that has least active containers
	running := 1024 * 1024 * 1024 // it's large enough
	var agent string
	for addr, cap := range caps {
		if n := len(cap.UsedNames); n < running {
			running = n
			agent = addr
		}
	}
	return agent
}

func resolveExLinks(m *docker.Manifest, caps Capabilities) ([]*rpc.ExLink, error) {
	var out []*rpc.ExLink
	for _, l := range m.ExLinks {
		caps2 := caps.Copy()
		caps2.Filter(func(cap *rpc.Capability) bool {
			return stringSlice(cap.UsedNames).Contains(l.Name) &&
				len(cap.IPAddrs) > 0
		})
		if len(caps2) == 0 {
			return nil, errors.New("No linkable containers")
		}
		_, cap := choice(caps2)
		ci := cap.Containers[l.Name]
		for _, port := range ci.Ports {
			addr := port.HostIP
			if addr == "0.0.0.0" {
				addr = cap.IPAddrs[0]
			}
			out = append(out, &rpc.ExLink{
				Name:    l.Alias,
				Exposed: string(port.Exposed),
				Addr:    addr,
				Port:    int(port.HostPort),
			})
		}
	}
	return out, nil
}

func choice(caps Capabilities) (string, *rpc.Capability) {
	var keys []string
	for k := range caps {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	n := rand.Intn(len(keys))
	return keys[n], caps[keys[n]]
}

type stringSlice []string

func (ss stringSlice) Contains(s string) bool {
	for _, v := range ss {
		if v == s {
			return true
		}
	}
	return false
}

func (ss stringSlice) Match(re *regexp.Regexp) bool {
	for _, v := range ss {
		if re.MatchString(v) {
			return true
		}
	}
	return false
}

type int64Slice []int64

func (is int64Slice) Contains(n int64) bool {
	for _, v := range is {
		if v == n {
			return true
		}
	}
	return false
}

type portSpecSlice []*docker.PortSpec

func (ps portSpecSlice) Contains(n int64) bool {
	for _, v := range ps {
		if v.HostPort == n {
			return true
		}
	}
	return false
}

func logRPCError(err error) {
	if err == nil {
		return
	}
	if re, ok := err.(rpc.Error); ok {
		re.Each(func(addr string, err error) {
			fields := log.Fields{"error": strings.TrimSpace(err.Error()), "agent": addr}
			log.WithFields(fields).Error("RPC error")
		})
	} else {
		log.WithField("error", err).Error("RPC error")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/boltdb/bolt"
	homedir "github.com/mitchellh/go-homedir"

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

var (
	verbose = kingpin.Flag("verbose", "Verbose mode").Short('v').Bool()

	set        = kingpin.Command("set", "initialise rest session")
	setService = set.Arg("service", "the service to set values for").Required().String()
	setHost    = set.Flag("host", "hostname for the servicpe").String()
	setPort    = set.Flag("port", "port to access the service").Int()
	setScheme  = set.Flag("scheme", "scheme used to access the service eg. http, https").String()
	setHeaders = set.Flag("header", "header to set for each request").StringMap()

	use          = kingpin.Command("use", "switch service")
	serviceToUse = use.Arg("service", "the service to use").Required().String()

	config        = kingpin.Command("config", "show and alter service configs")
	configService = config.Arg("service", "service to display").String()
	configKey     = config.Arg("key", "specific service setting").String()
	configValue   = config.Arg("value", "set the config key to this value").String()

	get     = kingpin.Command("get", "Perform a GET request")
	getPath = get.Arg("url", "url to perform request on").Required().String()

	post     = kingpin.Command("post", "Perform a POST request")
	postPath = post.Arg("url", "url to perform request on").Required().String()
	postData = post.Arg("data", "data to send in the POST request").Required().String()

	put     = kingpin.Command("put", "Perform a PUT request")
	putPath = put.Arg("url", "url to perform request on").Required().String()
	putData = put.Arg("data", "data to send in the PUT request").Required().String()

	delete     = kingpin.Command("delete", "Performa DELETE request")
	deletePath = delete.Arg("url", "url to perform request on").Required().String()

	dbFile string
)

func init() {
	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")
}

func main() {
	command := kingpin.Parse()
	switch command {
	case "set":
		if err := setValues(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "use":
		if err := useService(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "config":
		if err := displayConfig(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "get", "post", "put", "delete":
		resp, err := makeRequest(command)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		fmt.Print(string(body))
	}
}

func displayConfig() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		switch {
		case *configService == "":
			printBucket(tx.Bucket([]byte("info")), 0)
			printBucket(tx.Bucket([]byte("services")), 0)
		case *configKey == "":
			printBucket(getBucket(tx, "services."+*configService), 0)
		case *configValue == "":
			displayServiceKey(tx, *configService, *configKey)
		default:
			if err := setConfig(tx, *configService, *configKey, *configValue); err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

func displayServiceKey(tx *bolt.Tx, service, key string) {
	b := getBucket(tx, "services."+service)
	if b == nil {
		return
	}
	if v := b.Get([]byte(key)); v == nil {
		printBucket(b.Bucket([]byte(key)), 0)
	} else {
		fmt.Println(string(v))
	}
}

func setConfig(tx *bolt.Tx, service, key, value string) error {
	return tx.Bucket([]byte("services")).Bucket([]byte(service)).Put([]byte(key), []byte(value))
}

func useService() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		if b := serviceBucket.Bucket([]byte(*serviceToUse)); b == nil {
			return ErrNoService{Name: *serviceToUse}
		}

		info, err := tx.CreateBucketIfNotExists([]byte("info"))
		if err != nil {
			return err
		}

		err = info.Put([]byte("current"), []byte(*serviceToUse))
		if err != nil {
			return err
		}

		return nil
	})

	return err
}

func setValues() error {
	if *verbose {
		fmt.Println("opening database", ".rest.db")
	}

	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket, err := tx.CreateBucketIfNotExists([]byte("services"))
		if err != nil {
			return err
		}

		b, err := serviceBucket.CreateBucketIfNotExists([]byte(*setService))
		if err != nil {
			return err
		}

		if err := setString(b, "scheme", setScheme, "http"); err != nil {
			return err
		}

		if err := setString(b, "host", setHost, "localhost"); err != nil {
			return err
		}

		if err := setInt(b, "port", setPort, 80); err != nil {
			return err
		}

		for header, value := range *setHeaders {
			h, err := b.CreateBucketIfNotExists([]byte("headers"))
			if err != nil {
				return err
			}

			if err := h.Put([]byte(header), []byte(value)); err != nil {
				return err
			}

		}

		// if this is the first service to be set then set then also make it current service
		if info := tx.Bucket([]byte("info")); info == nil {
			ib, err := tx.CreateBucket([]byte("info"))
			if err != nil {
				return err
			}

			if err := ib.Put([]byte("current"), []byte(*setService)); err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

func getValues() (*url.URL, map[string]string, error) {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return nil, nil, err
	}
	defer db.Close()

	u := &url.URL{}
	headers := make(map[string]string)
	err = db.View(func(tx *bolt.Tx) error {
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return ErrNoInfoBucket
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return ErrNoServiceSet
		}

		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		b := serviceBucket.Bucket(current)
		if b == nil {
			return ErrNoService{Name: string(current)}
		}

		u.Scheme = string(b.Get([]byte("scheme")))
		hostname := string(b.Get([]byte("host")))
		port, err := binary.ReadVarint(bytes.NewReader(b.Get([]byte("port"))))
		if err != nil {
			return err
		}
		u.Host = fmt.Sprintf("%s:%d", hostname, port)

		if h := b.Bucket([]byte("headers")); h != nil {
			c := h.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				headers[string(k)] = string(v)
			}
		}

		return nil
	})

	return u, nil, err
}

func makeRequest(reqType string) (*http.Response, error) {
	u, headers, err := getValues()
	if err != nil {
		return nil, err
	}

	u.Path = path()
	if *verbose {
		fmt.Println(u)
	}

	client := &http.Client{}

	req, err := http.NewRequest(strings.ToUpper(reqType), u.String(), data())

	for key, value := range headers {
		req.Header.Set(key, value)
	}

	if err != nil {
		return nil, err
	}

	return client.Do(req)
}

func path() string {
	for _, p := range []*string{getPath, postPath, putPath, deletePath} {
		if *p != "" {
			return *p
		}
	}

	return ""
}

func data() io.Reader {
	for _, d := range []*string{postData, putData} {
		if d != nil {
			return strings.NewReader(*d)
		}
	}

	return nil
}
<commit_msg>Fix headers not being set in request<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/boltdb/bolt"
	homedir "github.com/mitchellh/go-homedir"

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

var (
	verbose = kingpin.Flag("verbose", "Verbose mode").Short('v').Bool()

	set        = kingpin.Command("set", "initialise rest session")
	setService = set.Arg("service", "the service to set values for").Required().String()
	setHost    = set.Flag("host", "hostname for the servicpe").String()
	setPort    = set.Flag("port", "port to access the service").Int()
	setScheme  = set.Flag("scheme", "scheme used to access the service eg. http, https").String()
	setHeaders = set.Flag("header", "header to set for each request").StringMap()

	use          = kingpin.Command("use", "switch service")
	serviceToUse = use.Arg("service", "the service to use").Required().String()

	config        = kingpin.Command("config", "show and alter service configs")
	configService = config.Arg("service", "service to display").String()
	configKey     = config.Arg("key", "specific service setting").String()
	configValue   = config.Arg("value", "set the config key to this value").String()

	get     = kingpin.Command("get", "Perform a GET request")
	getPath = get.Arg("url", "url to perform request on").Required().String()

	post     = kingpin.Command("post", "Perform a POST request")
	postPath = post.Arg("url", "url to perform request on").Required().String()
	postData = post.Arg("data", "data to send in the POST request").Required().String()

	put     = kingpin.Command("put", "Perform a PUT request")
	putPath = put.Arg("url", "url to perform request on").Required().String()
	putData = put.Arg("data", "data to send in the PUT request").Required().String()

	delete     = kingpin.Command("delete", "Performa DELETE request")
	deletePath = delete.Arg("url", "url to perform request on").Required().String()

	dbFile string
)

func init() {
	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")
}

func main() {
	command := kingpin.Parse()
	switch command {
	case "set":
		if err := setValues(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "use":
		if err := useService(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "config":
		if err := displayConfig(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "get", "post", "put", "delete":
		resp, err := makeRequest(command)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		fmt.Print(string(body))
	}
}

func displayConfig() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		switch {
		case *configService == "":
			printBucket(tx.Bucket([]byte("info")), 0)
			printBucket(tx.Bucket([]byte("services")), 0)
		case *configKey == "":
			printBucket(getBucket(tx, "services."+*configService), 0)
		case *configValue == "":
			displayServiceKey(tx, *configService, *configKey)
		default:
			if err := setConfig(tx, *configService, *configKey, *configValue); err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

func displayServiceKey(tx *bolt.Tx, service, key string) {
	b := getBucket(tx, "services."+service)
	if b == nil {
		return
	}
	if v := b.Get([]byte(key)); v == nil {
		printBucket(b.Bucket([]byte(key)), 0)
	} else {
		fmt.Println(string(v))
	}
}

func setConfig(tx *bolt.Tx, service, key, value string) error {
	return tx.Bucket([]byte("services")).Bucket([]byte(service)).Put([]byte(key), []byte(value))
}

func useService() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		if b := serviceBucket.Bucket([]byte(*serviceToUse)); b == nil {
			return ErrNoService{Name: *serviceToUse}
		}

		info, err := tx.CreateBucketIfNotExists([]byte("info"))
		if err != nil {
			return err
		}

		err = info.Put([]byte("current"), []byte(*serviceToUse))
		if err != nil {
			return err
		}

		return nil
	})

	return err
}

func setValues() error {
	if *verbose {
		fmt.Println("opening database", ".rest.db")
	}

	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket, err := tx.CreateBucketIfNotExists([]byte("services"))
		if err != nil {
			return err
		}

		b, err := serviceBucket.CreateBucketIfNotExists([]byte(*setService))
		if err != nil {
			return err
		}

		if err := setString(b, "scheme", setScheme, "http"); err != nil {
			return err
		}

		if err := setString(b, "host", setHost, "localhost"); err != nil {
			return err
		}

		if err := setInt(b, "port", setPort, 80); err != nil {
			return err
		}

		for header, value := range *setHeaders {
			h, err := b.CreateBucketIfNotExists([]byte("headers"))
			if err != nil {
				return err
			}

			if err := h.Put([]byte(header), []byte(value)); err != nil {
				return err
			}

		}

		// if this is the first service to be set then set then also make it current service
		if info := tx.Bucket([]byte("info")); info == nil {
			ib, err := tx.CreateBucket([]byte("info"))
			if err != nil {
				return err
			}

			if err := ib.Put([]byte("current"), []byte(*setService)); err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

func getValues() (*url.URL, map[string]string, error) {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return nil, nil, err
	}
	defer db.Close()

	u := &url.URL{}
	headers := make(map[string]string)
	err = db.View(func(tx *bolt.Tx) error {
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return ErrNoInfoBucket
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return ErrNoServiceSet
		}

		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		b := serviceBucket.Bucket(current)
		if b == nil {
			return ErrNoService{Name: string(current)}
		}

		u.Scheme = string(b.Get([]byte("scheme")))
		hostname := string(b.Get([]byte("host")))
		port, err := binary.ReadVarint(bytes.NewReader(b.Get([]byte("port"))))
		if err != nil {
			return err
		}
		u.Host = fmt.Sprintf("%s:%d", hostname, port)

		if h := b.Bucket([]byte("headers")); h != nil {
			c := h.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				headers[string(k)] = string(v)
			}
		}

		return nil
	})

	return u, headers, err
}

func makeRequest(reqType string) (*http.Response, error) {
	u, headers, err := getValues()
	if err != nil {
		return nil, err
	}

	u.Path = path()
	if *verbose {
		fmt.Println(u)
	}

	client := &http.Client{}

	req, err := http.NewRequest(strings.ToUpper(reqType), u.String(), data())

	for key, value := range headers {
		req.Header.Set(key, value)
	}

	if err != nil {
		return nil, err
	}

	return client.Do(req)
}

func path() string {
	for _, p := range []*string{getPath, postPath, putPath, deletePath} {
		if *p != "" {
			return *p
		}
	}

	return ""
}

func data() io.Reader {
	for _, d := range []*string{postData, putData} {
		if d != nil {
			return strings.NewReader(*d)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

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

func main() {
	// Parse the command line flag values into variables for later use
	args := flagInit()

	// set up buffer characters
	var buffer []string
	if *args.bufferChars != "" {
		buffer = []string{*args.bufferChars, *args.bufferChars}
	} else if *args.bufferCharsLeft != "" || *args.bufferCharsRight != "" {
		buffer = []string{*args.bufferCharsLeft, *args.bufferCharsRight}
	} else {
		buffer = []string{"", ""}
	}

	// load tokenized document into memory
	// but first, check that the file exists
	ensureFileExists(*args.inputPath, "--input")
	input := loadFile(*args.inputPath)

	var output []byte
	if *args.extract {
		// tokens are being extracted in this block
		tokens := extractTokens(input, buffer)

		if strings.HasSuffix(*args.outputPath, ".json") {
			// if the output file ends in json, format it as a json file with { "key": "" }
			output = convertToJSON(tokens, buffer)
		} else {
			// just spit out the keys
			for i, t := range tokens {
				if i > 0 {
					output = append(output, []byte("\n")...)
				}
				output = append(output, t...)
			}
		}
	} else {
		// we are detokenizing in this block
		if *args.dataBag != "" {
			// parse tokens from data bags
			blobs := listDataBagEntries(*args.dataBag)
			if len(blobs) == 0 {
				fmt.Println("Data bag shows no entries.  Ensure you are able to view a list of data bags with the command: knife show data bags {your_databag_here}")
				os.Exit(1)
			}
			var blobsBytes [][]byte
			for _, b := range blobs {
				if *args.dataBagSecret == "" {
					blobsBytes = append(blobsBytes, collectDataBagJSON(*args.dataBag, b))
				} else {
					blobsBytes = append(blobsBytes, collectEncrytpedDataBagJSON(*args.dataBag, b, *args.dataBagSecret))
				}
			}
			var tokens []map[string][]byte
			tokens = mapKeyPairs(blobsBytes, buffer)
			output = detokenize(input, tokens)

		} else {
			paths := strings.Split(*args.tokensPath, ",")
			tokenInputs := [][]byte{}
			for _, path := range paths {
				ensureFileExists(path, "--tokens")
				tokenInputs = append(tokenInputs, loadFile(path))
			}
			// parse tokens from json file(s)
			tokens := mapKeyPairs(tokenInputs, buffer)

			// store final product for later use
			output = detokenize(input, tokens)
		}
		if !*args.unsafe {
			bufferBuilder := buffer[0] + "(.*?)" + buffer[1]
			rex := regexp.MustCompile(bufferBuilder)

			if len(rex.FindAll(output, -1)) > 0 {
				fmt.Println("Safety Error: Not all tokens were replaced.  If you're okay with this, pass the --unsafe flag when calling fasturtle.")
				os.Exit(1)
			}
		}
	}

	if *args.outputPath != "" {
		outputToFile(*args.outputPath, output)
	} else {
		outputToStdout(output)
	}
}

func ensureFileExists(file, use string) {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		fmt.Printf("Error: File \"%s\" does not exist. Please provide a valid file path for %s.\n", file, use)
		os.Exit(1)
	}
}

func checkError(err error) {
	if err != nil {
		log.Panic(err)
	}
}
<commit_msg>if a token is missed, and unsafe flag not passed, the tokens will be returned in stdout<commit_after>package main

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

func main() {
	// Parse the command line flag values into variables for later use
	args := flagInit()

	// set up buffer characters
	var buffer []string
	if *args.bufferChars != "" {
		buffer = []string{*args.bufferChars, *args.bufferChars}
	} else if *args.bufferCharsLeft != "" || *args.bufferCharsRight != "" {
		buffer = []string{*args.bufferCharsLeft, *args.bufferCharsRight}
	} else {
		buffer = []string{"", ""}
	}

	// load tokenized document into memory
	// but first, check that the file exists
	ensureFileExists(*args.inputPath, "--input")
	input := loadFile(*args.inputPath)

	var output []byte
	if *args.extract {
		// tokens are being extracted in this block
		tokens := extractTokens(input, buffer)

		if strings.HasSuffix(*args.outputPath, ".json") {
			// if the output file ends in json, format it as a json file with { "key": "" }
			output = convertToJSON(tokens, buffer)
		} else {
			// just spit out the keys
			for i, t := range tokens {
				if i > 0 {
					output = append(output, []byte("\n")...)
				}
				output = append(output, t...)
			}
		}
	} else {
		// we are detokenizing in this block
		if *args.dataBag != "" {
			// parse tokens from data bags
			blobs := listDataBagEntries(*args.dataBag)
			if len(blobs) == 0 {
				fmt.Println("Data bag shows no entries.  Ensure you are able to view a list of data bags with the command: knife show data bags {your_databag_here}")
				os.Exit(1)
			}
			var blobsBytes [][]byte
			for _, b := range blobs {
				if *args.dataBagSecret == "" {
					blobsBytes = append(blobsBytes, collectDataBagJSON(*args.dataBag, b))
				} else {
					blobsBytes = append(blobsBytes, collectEncrytpedDataBagJSON(*args.dataBag, b, *args.dataBagSecret))
				}
			}
			var tokens []map[string][]byte
			tokens = mapKeyPairs(blobsBytes, buffer)
			output = detokenize(input, tokens)

		} else {
			paths := strings.Split(*args.tokensPath, ",")
			tokenInputs := [][]byte{}
			for _, path := range paths {
				ensureFileExists(path, "--tokens")
				tokenInputs = append(tokenInputs, loadFile(path))
			}
			// parse tokens from json file(s)
			tokens := mapKeyPairs(tokenInputs, buffer)

			// store final product for later use
			output = detokenize(input, tokens)
		}
		if !*args.unsafe {
			bufferBuilder := buffer[0] + "(.*?)" + buffer[1]
			rex := regexp.MustCompile(bufferBuilder)

			failVals := rex.FindAll(output, -1)
			if len(failVals) > 0 {
				fmt.Println("Safety Error: Not all tokens were replaced:\n")
				for _, tk := range failVals {
					fmt.Println(string(tk))
				}
				fmt.Println()
				fmt.Println("If you're okay with this, pass the --unsafe flag when calling fasturtle.")
				os.Exit(1)
			}
		}
	}

	if *args.outputPath != "" {
		outputToFile(*args.outputPath, output)
	} else {
		outputToStdout(output)
	}
}

func ensureFileExists(file, use string) {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		fmt.Printf("Error: File \"%s\" does not exist. Please provide a valid file path for %s.\n", file, use)
		os.Exit(1)
	}
}

func checkError(err error) {
	if err != nil {
		log.Panic(err)
	}
}
<|endoftext|>


<commit_before>/*
	Watches the current directory for changes, and runs the command you supply as arguments
	in response to changes.

	This is my first go project, suggestions welcome!
*/

package main

import (
	"flag"
	"fmt"
	"github.com/howeyc/fsnotify"
	"net/http"
	"os"
	"regexp"
)

var (
	verbose       = flag.Bool("v", false, "Verbose")
	verboseQuiet  = flag.Bool("q", false, "Quiet, only warnings and errors.")

	watchDir      = flag.String("dir", "", "Directory to watch, defaults to current")
	buildCmd      = flag.String("cmd", "", "Bash command to run on change. Wabo will wait for this command to finish.")
	daemonCmd     = flag.String("daemon", "", "Bash command that starts a daemon. Wago will halt if the daemon exits before the trigger or timer.")
	daemonTrigger = flag.String("trigger", "", "A string the daemon will output that indicates it has started successfuly. Wago will continue on this trigger.")
	daemonTimer   = flag.Int("timer", 0, "Miliseconds to wait after starting daemon before continuing.")
	webServer     = flag.String("web", "", "Start a web server at this address, e.g. :8420")
	postCmd       = flag.String("pcmd", "", "Bash command to run after the daemon has successfully started.")
	url           = flag.String("url", "", "URL to open")
	watchRegex    = flag.String("watch", `/\w[\w\.]*": (CREATE|MODIFY)`, "Regex to match watch event. Use -v to see all events.")

	daemon = &Daemon{}
	cmd = &Cmd{}
)

func help() {
	fmt.Println("WaGo (Wait, Go) build watcher")
}

func event() {
	if cmd.Cmd != nil && cmd.ProcessState == nil {
		cmd.Kill()
	}

	if daemon.Cmd != nil && daemon.ProcessState == nil {
		daemon.Kill()
	}

	// run build command
	if len(*buildCmd) > 0 {
		cmd = NewCmd(*buildCmd)
		ok := cmd.Run()
		if !ok {
			return
		}
	}

	// start the daemon
	if len(*daemonCmd) > 0 {
		daemon = NewDaemon(*daemonCmd)

		if len(*daemonTrigger) > 0 {
			if !daemon.RunTrigger(*daemonTrigger) {
				return
			}
		} else {
			if !daemon.RunTimer(*daemonTimer) {
				return
			}
		}
	}

	// run post command
	if len(*postCmd) > 0 {
		cmd = NewCmd(*postCmd)
		ok := cmd.Run()
		if !ok {
			return
		}
	}

	// open the url
	if *url != "" {
		openUrl()
	}
}

func main() {
	if len(os.Args) < 2 {
		help()
		Fatal("You must specify an action")
	}

	flag.Parse()

	if *watchDir == "" {
		cwd, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		watchDir = &cwd
	}
	Talk("Watching dir:", *watchDir)

	r, err := regexp.Compile(*watchRegex)
	if err != nil {
		Fatal("Watch regex compile error:", err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}
	defer watcher.Close()

	err = watcher.Watch(*watchDir)
	if err != nil {
		panic(err)
	}

	if *webServer != "" {
		go func(){
			Note("Starting web server on port", *webServer)
			err := http.ListenAndServe(*webServer, http.FileServer(http.Dir(*watchDir)))
			if err != nil {
				Fatal("Error starting web server:", err)
			}
		}()
	}

	// trigger event on start
	go event()

	for {
		select {
		case ev := <-watcher.Event:
			if r.MatchString(ev.String()) {
				Note("Matched event:", ev.String())
				go event()
			} else {
				Talk("Ignored event:", ev.String())
			}

		case err = <-watcher.Error:
			panic(err)
		}
	}
}
<commit_msg>added fiddle mode<commit_after>/*
	Watches the current directory for changes, and runs the command you supply as arguments
	in response to changes.

	This is my first go project, suggestions welcome!
*/

package main

import (
	"flag"
	"fmt"
	"github.com/howeyc/fsnotify"
	"net/http"
	"os"
	"regexp"
)

var (
	verbose       = flag.Bool("v", false, "Verbose")
	verboseQuiet  = flag.Bool("q", false, "Quiet, only warnings and errors.")

	fiddle = flag.Bool("fiddle", false, "CLI fiddle mode, starts a web server and opens url to watchDir/index.html")
	watchDir      = flag.String("dir", "", "Directory to watch, defaults to current")
	buildCmd      = flag.String("cmd", "", "Bash command to run on change. Wabo will wait for this command to finish.")
	daemonCmd     = flag.String("daemon", "", "Bash command that starts a daemon. Wago will halt if the daemon exits before the trigger or timer.")
	daemonTrigger = flag.String("trigger", "", "A string the daemon will output that indicates it has started successfuly. Wago will continue on this trigger.")
	daemonTimer   = flag.Int("timer", 0, "Miliseconds to wait after starting daemon before continuing.")
	webServer     = flag.String("web", "", "Start a web server at this address, e.g. :8420")
	postCmd       = flag.String("pcmd", "", "Bash command to run after the daemon has successfully started.")
	url           = flag.String("url", "", "URL to open")
	watchRegex    = flag.String("watch", `/\w[\w\.]*": (CREATE|MODIFY)`, "Regex to match watch event. Use -v to see all events.")

	daemon = &Daemon{}
	cmd = &Cmd{}
)

func help() {
	fmt.Println("WaGo (Wait, Go) build watcher")
}

func event() {
	if cmd.Cmd != nil && cmd.ProcessState == nil {
		cmd.Kill()
	}

	if daemon.Cmd != nil && daemon.ProcessState == nil {
		daemon.Kill()
	}

	// run build command
	if len(*buildCmd) > 0 {
		cmd = NewCmd(*buildCmd)
		ok := cmd.Run()
		if !ok {
			return
		}
	}

	// start the daemon
	if len(*daemonCmd) > 0 {
		daemon = NewDaemon(*daemonCmd)

		if len(*daemonTrigger) > 0 {
			if !daemon.RunTrigger(*daemonTrigger) {
				return
			}
		} else {
			if !daemon.RunTimer(*daemonTimer) {
				return
			}
		}
	}

	// run post command
	if len(*postCmd) > 0 {
		cmd = NewCmd(*postCmd)
		ok := cmd.Run()
		if !ok {
			return
		}
	}

	// open the url
	if *url != "" {
		openUrl()
	}
}

func main() {
	if len(os.Args) < 2 {
		help()
		Fatal("You must specify an action")
	}

	flag.Parse()

	if *fiddle {
		*webServer = ":9933"
		*url = "http://localhost:9933/index.html"
	}

	if *watchDir == "" {
		cwd, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		watchDir = &cwd
	}
	Talk("Watching dir:", *watchDir)

	r, err := regexp.Compile(*watchRegex)
	if err != nil {
		Fatal("Watch regex compile error:", err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}
	defer watcher.Close()

	err = watcher.Watch(*watchDir)
	if err != nil {
		panic(err)
	}

	if *webServer != "" {
		go func(){
			Note("Starting web server on port", *webServer)
			err := http.ListenAndServe(*webServer, http.FileServer(http.Dir(*watchDir)))
			if err != nil {
				Fatal("Error starting web server:", err)
			}
		}()
	}

	// trigger event on start
	go event()

	for {
		select {
		case ev := <-watcher.Event:
			if r.MatchString(ev.String()) {
				Note("Matched event:", ev.String())
				go event()
			} else {
				Talk("Ignored event:", ev.String())
			}

		case err = <-watcher.Error:
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net"
	"time"

	"github.com/dasfoo/i2c"
	"github.com/dasfoo/rover/bb"
	"github.com/dasfoo/rover/mc"
	"golang.org/x/net/context"

	"google.golang.org/grpc"

	pb "github.com/dasfoo/rover/proto"
)

// server is used to implement roverserver.RoverServiceServer.
type server struct{}

var (
	board  *bb.BB
	motors *mc.MC
)

// MoveRover implements
func (s *server) MoveRover(ctx context.Context, in *pb.RoverWheelRequest) (*pb.RoverWheelResponse, error) {
	_ = motors.Left(int8(in.Left)) //TODO error check
	_ = motors.Right(int8(in.Right))
	time.Sleep(1 * time.Second)

	_ = motors.Left(0)
	_ = motors.Right(0)
	return &pb.RoverWheelResponse{
		Status: &pb.Status{
			Code: pb.StatusCode_OK,
		},
	}, nil
}

func (s *server) GetBatteryPercentage(ctx context.Context, in *pb.BatteryPercentageRequest) (*pb.BatteryPercentageResponse, error) {
	var batteryPercentage byte
	var e error
	if batteryPercentage, e = board.GetBatteryPercentage(); e != nil {
		return &pb.BatteryPercentageResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.BatteryPercentageResponse{
		Battery: int32(batteryPercentage),
	}, e
}

func (s *server) GetAmbientLight(ctx context.Context, in *pb.AmbientLightRequest) (*pb.AmbientLightResponse, error) {
	var light uint16
	var e error
	if light, e = board.GetAmbientLight(); e != nil {
		return &pb.AmbientLightResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.AmbientLightResponse{
		Light: int32(light),
	}, e
}

func (s *server) GetTemperatureAndHumidity(ctx context.Context, in *pb.TemperatureAndHumidityRequest) (*pb.TemperatureAndHumidityResponse, error) {
	var t, h byte
	var e error
	if t, h, e = board.GetTemperatureAndHumidity(); e != nil {
		return &pb.TemperatureAndHumidityResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.TemperatureAndHumidityResponse{
		Temperature: int32(t), // TODO: check byte in proto
		Humidity:    int32(h),
	}, e
}

func main() {

	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	var laddr = flag.String("laddr", "", "laddr")
	var test = flag.Bool("test", false, "Flag for startup script")
	flag.Parse()
	log.Println("Properties from command line:", *laddr)
	log.Println("Flag for startup script", *test)
	if bus, err := i2c.NewBus(1); err != nil {
		log.Fatal(err)
	} else {
		// Silence i2c bus log
		//bus.Log = func(string, ...interface{}) {}

		board = bb.NewBB(bus, bb.Address)
		motors = mc.NewMC(bus, mc.Address)
	}
	lis, err := net.Listen("tcp", *laddr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Println("Server started")
	s := grpc.NewServer()
	pb.RegisterRoverServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add Status default initialization<commit_after>package main

import (
	"flag"
	"log"
	"net"
	"time"

	"github.com/dasfoo/i2c"
	"github.com/dasfoo/rover/bb"
	"github.com/dasfoo/rover/mc"
	"golang.org/x/net/context"

	"google.golang.org/grpc"

	pb "github.com/dasfoo/rover/proto"
)

// server is used to implement roverserver.RoverServiceServer.
type server struct{}

var (
	board  *bb.BB
	motors *mc.MC
)

// MoveRover implements
func (s *server) MoveRover(ctx context.Context, in *pb.RoverWheelRequest) (*pb.RoverWheelResponse, error) {
	_ = motors.Left(int8(in.Left)) //TODO error check
	_ = motors.Right(int8(in.Right))
	time.Sleep(1 * time.Second)

	_ = motors.Left(0)
	_ = motors.Right(0)
	return &pb.RoverWheelResponse{
		Status: &pb.Status{
			Code: pb.StatusCode_OK,
		},
	}, nil
}

func (s *server) GetBatteryPercentage(ctx context.Context,
	in *pb.BatteryPercentageRequest) (*pb.BatteryPercentageResponse, error) {
	var batteryPercentage byte
	var e error
	if batteryPercentage, e = board.GetBatteryPercentage(); e != nil {
		return &pb.BatteryPercentageResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.BatteryPercentageResponse{
		Status:  &pb.Status{},
		Battery: int32(batteryPercentage),
	}, e
}

func (s *server) GetAmbientLight(ctx context.Context,
	in *pb.AmbientLightRequest) (*pb.AmbientLightResponse, error) {
	var light uint16
	var e error
	if light, e = board.GetAmbientLight(); e != nil {
		return &pb.AmbientLightResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.AmbientLightResponse{
		Status: &pb.Status{},
		Light:  int32(light),
	}, e
}

func (s *server) GetTemperatureAndHumidity(ctx context.Context,
	in *pb.TemperatureAndHumidityRequest) (*pb.TemperatureAndHumidityResponse, error) {
	var t, h byte
	var e error
	if t, h, e = board.GetTemperatureAndHumidity(); e != nil {
		return &pb.TemperatureAndHumidityResponse{
			Status: &pb.Status{
				Code:    pb.StatusCode_HARDWARE_FAILURE,
				Message: e.Error(),
			},
		}, e
	}
	return &pb.TemperatureAndHumidityResponse{
		Status:      &pb.Status{},
		Temperature: int32(t), // TODO: check byte in proto
		Humidity:    int32(h),
	}, e
}

func main() {

	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	var laddr = flag.String("laddr", "", "laddr")
	var test = flag.Bool("test", false, "Flag for startup script")
	flag.Parse()
	log.Println("Properties from command line:", *laddr)
	log.Println("Flag for startup script", *test)
	if bus, err := i2c.NewBus(1); err != nil {
		log.Fatal(err)
	} else {
		// Silence i2c bus log
		//bus.Log = func(string, ...interface{}) {}

		board = bb.NewBB(bus, bb.Address)
		motors = mc.NewMC(bus, mc.Address)
	}
	lis, err := net.Listen("tcp", *laddr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Println("Server started")
	s := grpc.NewServer()
	pb.RegisterRoverServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"net/http"
	"sort"
	"sync"
	"time"
)

var (
	version   = "0.1.0"
	github    = "https://github.com/ekalinin/awsping"
	useragent = fmt.Sprintf("AwsPing/%s (+%s)", version, github)
)

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func mkRandoString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

// AWSRegion description of the AWS EC2 region
type AWSRegion struct {
	Name    string
	Code    string
	Latency time.Duration
	Error   error
}

// CheckLatency fills internal field Latency
func (r *AWSRegion) CheckLatency(wg *sync.WaitGroup) {
	url := fmt.Sprintf("http://dynamodb.%s.amazonaws.com/ping?x=%s",
		r.Code, mkRandoString(13))
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", useragent)

	start := time.Now()
	resp, err := client.Do(req)
	r.Latency = time.Since(start)

	r.Error = err
	resp.Body.Close()

	wg.Done()
}

// AWSRegions slice of the AWSRegion
type AWSRegions []AWSRegion

func (rs AWSRegions) Len() int {
	return len(rs)
}

func (rs AWSRegions) Less(i, j int) bool {
	return rs[i].Latency < rs[j].Latency
}

func (rs AWSRegions) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
}

func main() {
	regions := AWSRegions{
		{Name: "US-East (Virginia)", Code: "us-east-1"},
		{Name: "US-West (California)", Code: "us-west-1"},
		{Name: "US-West (Oregon)", Code: "us-west-2"},
		{Name: "Asia Pacific (Mumbai)", Code: "ap-south-1"},
		{Name: "Asia Pacific (Seoul)", Code: "ap-northeast-2"},
		{Name: "Asia Pacific (Singapore)", Code: "ap-southeast-1"},
		{Name: "Asia Pacific (Sydney)", Code: "ap-southeast-2"},
		{Name: "Asia Pacific (Tokyo)", Code: "ap-northeast-1"},
		{Name: "Europe (Ireland)", Code: "eu-west-1"},
		{Name: "Europe (Frankfurt)", Code: "eu-central-1"},
		{Name: "South America (São Paulo)", Code: "sa-east-1"},
		//{Name: "China (Beijing)", Code: "cn-north-1"},
	}
	var wg sync.WaitGroup
	wg.Add(len(regions))

	for i := range regions {
		go regions[i].CheckLatency(&wg)
	}

	wg.Wait()

	sort.Sort(regions)

	outFmt := "%5v %-30s %20s\n"
	fmt.Printf(outFmt, "", "Region", "Latency")
	for i, r := range regions {
		ms := fmt.Sprintf("%.2f ms", float64(r.Latency.Nanoseconds())/1000/1000)
		fmt.Printf(outFmt, i, r.Name, ms)
	}
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<commit_msg>added function CalcLatency with the main logic<commit_after>package main

import (
	"fmt"
	"math/rand"
	"net/http"
	"sort"
	"sync"
	"time"
)

var (
	version   = "0.1.0"
	github    = "https://github.com/ekalinin/awsping"
	useragent = fmt.Sprintf("AwsPing/%s (+%s)", version, github)
)

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func mkRandoString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

// AWSRegion description of the AWS EC2 region
type AWSRegion struct {
	Name    string
	Code    string
	Latency time.Duration
	Error   error
}

// CheckLatency fills internal field Latency
func (r *AWSRegion) CheckLatency(wg *sync.WaitGroup) {
	url := fmt.Sprintf("http://dynamodb.%s.amazonaws.com/ping?x=%s",
		r.Code, mkRandoString(13))
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", useragent)

	start := time.Now()
	resp, err := client.Do(req)
	r.Latency = time.Since(start)

	r.Error = err
	resp.Body.Close()

	wg.Done()
}

// AWSRegions slice of the AWSRegion
type AWSRegions []AWSRegion

func (rs AWSRegions) Len() int {
	return len(rs)
}

func (rs AWSRegions) Less(i, j int) bool {
	return rs[i].Latency < rs[j].Latency
}

func (rs AWSRegions) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
}

// CalcLatency returns list of aws regions sorted by Latency
func CalcLatency() *AWSRegions {
	regions := AWSRegions{
		{Name: "US-East (Virginia)", Code: "us-east-1"},
		{Name: "US-West (California)", Code: "us-west-1"},
		{Name: "US-West (Oregon)", Code: "us-west-2"},
		{Name: "Asia Pacific (Mumbai)", Code: "ap-south-1"},
		{Name: "Asia Pacific (Seoul)", Code: "ap-northeast-2"},
		{Name: "Asia Pacific (Singapore)", Code: "ap-southeast-1"},
		{Name: "Asia Pacific (Sydney)", Code: "ap-southeast-2"},
		{Name: "Asia Pacific (Tokyo)", Code: "ap-northeast-1"},
		{Name: "Europe (Ireland)", Code: "eu-west-1"},
		{Name: "Europe (Frankfurt)", Code: "eu-central-1"},
		{Name: "South America (São Paulo)", Code: "sa-east-1"},
		//{Name: "China (Beijing)", Code: "cn-north-1"},
	}
	var wg sync.WaitGroup
	wg.Add(len(regions))

	for i := range regions {
		go regions[i].CheckLatency(&wg)
	}

	wg.Wait()

	sort.Sort(regions)
	return &regions
}

func main() {

	regions := *CalcLatency()

	outFmt := "%5v %-30s %20s\n"
	fmt.Printf(outFmt, "", "Region", "Latency")
	for i, r := range regions {
		ms := fmt.Sprintf("%.2f ms", float64(r.Latency.Nanoseconds())/1000/1000)
		fmt.Printf(outFmt, i, r.Name, ms)
	}
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<|endoftext|>


<commit_before>//  Copyright 2014 Cory Benfield
//
//    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 (
	"encoding/json"
	"fmt"
	"github.com/Lukasa/mkcert/certs"
	"log"
	"net/http"
	"runtime"
	"strings"
	"sync"
	"time"
)

const CERT_URL = "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt"

// Global state! It's evil!
//
// More seriously, this is a performance optimisation. The certificate map
// can be quite large, and copying it around is a stupid waste of everyone's
// time when 99.99% of the time we just want to read from it. Instead, we use
// a RWMutex to ensure that we can always read from this structure, but cannot
// read in the middle of a write.
//
// Arguably this is not idiomatic Go. If someone can show me an idiomatic
// approach that doesn't copy memory like a fifth-grader copies math answers,
// please let me know.
var certificates certs.CertMap = nil
var certMapLock *sync.RWMutex = new(sync.RWMutex)

type CertificateList struct {
	Certificates []string
}

func updateCertificates() {
	// Now, grab the certificates.
	resp, err := http.Get(CERT_URL)
	if err != nil {
		log.Fatalf("Unable to get cert file: %s", err)
	}

	_, _, objects := certs.ParseInput(resp.Body)
	resp.Body.Close()

	certMapLock.Lock()
	certificates = certs.OutputTrustedCerts(objects)
	certMapLock.Unlock()
}

// certUpdateLoop spins in a loop updating the certificates once a day.
func certUpdateLoop() {
	for {
		updateCertificates()
		<-time.After(24 * time.Hour)
	}
}

// Parses the exceptions from the path.
func getExceptions(path string, prefix string) map[string]interface{} {
	// Remove the prefix.
	query := string(path[len(prefix):])

	// Split the query on each '+' character.
	components := strings.Split(query, "+")

	exceptions := make(map[string]interface{})
	for _, component := range components {
		exceptions[component] = nil
	}

	return exceptions
}

// serveBlacklistCertificates serves certificates using a blacklist. The
// expected form of the URL is: /generate/name1+name2+name3, where name1 and
// friends are the labels to exclude from the list.
func serveBlacklistCertificates(w http.ResponseWriter, r *http.Request) {
	exceptions := getExceptions(r.URL.Path, "/generate/")

	certMapLock.RLock()
	certs.WriteCerts(w, certificates, false, exceptions)
	certMapLock.RUnlock()
}

// serveWhitelistCertificates serves certificates using a whitelist. The
// expected form of the URL is: /generate/all/except/name1+name2+name3, where
// name1 and friends are the labels to exclude from the list.
func serveWhitelistCertificates(w http.ResponseWriter, r *http.Request) {
	exceptions := getExceptions(r.URL.Path, "/generate/all/except/")

	certMapLock.RLock()
	certs.WriteCerts(w, certificates, true, exceptions)
	certMapLock.RUnlock()
}

// listAllCerts provides a JSON object that contains a list of all the
// certificates in the bundle. Each key is a value that can be sent on the API.
func listAllCerts(w http.ResponseWriter, r *http.Request) {
	certMapLock.RLock()
	labels := certs.OutputAllLabels(certificates)
	certMapLock.RUnlock()

	b, err := json.Marshal(CertificateList{labels})
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Content-Length", fmt.Sprintf("%v", len(b)))
	w.Write(b)
}

func main() {
	// Before we do anything, TURN ON THE CPUS.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Start the certificate update loop.
	go certUpdateLoop()

	// Start the HTTP server.
	http.HandleFunc("/labels/", listAllCerts)
	http.HandleFunc("/generate/", serveWhitelistCertificates)
	http.HandleFunc("/generate/all/except/", serveBlacklistCertificates)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>CONTENT-TYPES FOR ALL.<commit_after>//  Copyright 2014 Cory Benfield
//
//    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 (
	"encoding/json"
	"fmt"
	"github.com/Lukasa/mkcert/certs"
	"log"
	"net/http"
	"runtime"
	"strings"
	"sync"
	"time"
)

const CERT_URL = "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt"

// Global state! It's evil!
//
// More seriously, this is a performance optimisation. The certificate map
// can be quite large, and copying it around is a stupid waste of everyone's
// time when 99.99% of the time we just want to read from it. Instead, we use
// a RWMutex to ensure that we can always read from this structure, but cannot
// read in the middle of a write.
//
// Arguably this is not idiomatic Go. If someone can show me an idiomatic
// approach that doesn't copy memory like a fifth-grader copies math answers,
// please let me know.
var certificates certs.CertMap = nil
var certMapLock *sync.RWMutex = new(sync.RWMutex)

type CertificateList struct {
	Certificates []string
}

func updateCertificates() {
	// Now, grab the certificates.
	resp, err := http.Get(CERT_URL)
	if err != nil {
		log.Fatalf("Unable to get cert file: %s", err)
	}

	_, _, objects := certs.ParseInput(resp.Body)
	resp.Body.Close()

	certMapLock.Lock()
	certificates = certs.OutputTrustedCerts(objects)
	certMapLock.Unlock()
}

// certUpdateLoop spins in a loop updating the certificates once a day.
func certUpdateLoop() {
	for {
		updateCertificates()
		<-time.After(24 * time.Hour)
	}
}

// Parses the exceptions from the path.
func getExceptions(path string, prefix string) map[string]interface{} {
	// Remove the prefix.
	query := string(path[len(prefix):])

	// Split the query on each '+' character.
	components := strings.Split(query, "+")

	exceptions := make(map[string]interface{})
	for _, component := range components {
		exceptions[component] = nil
	}

	return exceptions
}

// serveBlacklistCertificates serves certificates using a blacklist. The
// expected form of the URL is: /generate/name1+name2+name3, where name1 and
// friends are the labels to exclude from the list.
func serveBlacklistCertificates(w http.ResponseWriter, r *http.Request) {
	exceptions := getExceptions(r.URL.Path, "/generate/")
	w.Header().Set("Content-Type", "application/x-pem-file")

	certMapLock.RLock()
	certs.WriteCerts(w, certificates, false, exceptions)
	certMapLock.RUnlock()
}

// serveWhitelistCertificates serves certificates using a whitelist. The
// expected form of the URL is: /generate/all/except/name1+name2+name3, where
// name1 and friends are the labels to exclude from the list.
func serveWhitelistCertificates(w http.ResponseWriter, r *http.Request) {
	exceptions := getExceptions(r.URL.Path, "/generate/all/except/")
	w.Header().Set("Content-Type", "application/x-pem-file")

	certMapLock.RLock()
	certs.WriteCerts(w, certificates, true, exceptions)
	certMapLock.RUnlock()
}

// listAllCerts provides a JSON object that contains a list of all the
// certificates in the bundle. Each key is a value that can be sent on the API.
func listAllCerts(w http.ResponseWriter, r *http.Request) {
	certMapLock.RLock()
	labels := certs.OutputAllLabels(certificates)
	certMapLock.RUnlock()

	b, err := json.Marshal(CertificateList{labels})
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Content-Length", fmt.Sprintf("%v", len(b)))
	w.Write(b)
}

func main() {
	// Before we do anything, TURN ON THE CPUS.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Start the certificate update loop.
	go certUpdateLoop()

	// Start the HTTP server.
	http.HandleFunc("/labels/", listAllCerts)
	http.HandleFunc("/generate/", serveWhitelistCertificates)
	http.HandleFunc("/generate/all/except/", serveBlacklistCertificates)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<|endoftext|>