<commit_before>package main

import (
  "fmt"
  "log"
  "flag"
  "os"
  "os/exec"
  "time"
  "syscall"
  "strings"
)

func main() {
  var interval int
  flag.IntVar(&interval, "i", 1, "interval")

  var interrupt bool
  flag.BoolVar(&interrupt, "x", false, "interrupt")

  flag.Parse()

  command := flag.Args()

  loop(intervalToTime(interval), func () {
    reset()
    status := run(measure(command))
    if(interrupt && status != 0) {
      os.Exit(status)
    }
  })
}

func intervalToTime(i int) time.Duration {
  return time.Duration(i) * time.Second
}

func reset() {
  run([]string {"clear"})
}

func measure(command []string) []string {
  return append([]string {"time"}, command...)
}

func run(command []string) int {
  cmd := exec.Command(getShell(), wrapForShell(buildArgs(command))...)
  cmd.Env = os.Environ()
  cmd.Stdout = os.Stdout
  cmd.Stderr = os.Stderr
  cmd.Run()
  status, _ := cmd.ProcessState.Sys().(syscall.WaitStatus)
  return status.ExitStatus()
}

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

func buildArgs(command []string) string {
  return strings.Join(command, " ")
}

func wrapForShell(command string) []string {
  return append([]string {"-c"}, fmt.Sprintf("%s; eval %s", sourceFiles(), command))
}

func sourceFiles() string {
  return fmt.Sprintf("%s %s", getShellSourceCmd(), getSourceFilePath())
}

func getSourceFilePath() string {
  return "~/.zshrc"
}

func getShellSourceCmd() string {
  return "."
}

func getShell() string {
  bin, found := syscall.Getenv("SHELL")
  if found == false {
    bin, _ = exec.LookPath("sh")
  }
  return bin
}

func loop(d time.Duration, fn func()) {
  fn()
  select {
  case <- time.After(d):
    loop(d, fn)
  }
}
<commit_msg>Sort deps<commit_after>package main

import (
  "flag"
  "fmt"
  "log"
  "os"
  "os/exec"
  "strings"
  "syscall"
  "time"
)

func main() {
  var interval int
  flag.IntVar(&interval, "i", 1, "interval")

  var interrupt bool
  flag.BoolVar(&interrupt, "x", false, "interrupt")

  flag.Parse()

  command := flag.Args()

  loop(intervalToTime(interval), func () {
    reset()
    status := run(measure(command))
    if(interrupt && status != 0) {
      os.Exit(status)
    }
  })
}

func intervalToTime(i int) time.Duration {
  return time.Duration(i) * time.Second
}

func reset() {
  run([]string {"clear"})
}

func measure(command []string) []string {
  return append([]string {"time"}, command...)
}

func run(command []string) int {
  cmd := exec.Command(getShell(), wrapForShell(buildArgs(command))...)
  cmd.Env = os.Environ()
  cmd.Stdout = os.Stdout
  cmd.Stderr = os.Stderr
  cmd.Run()
  status, _ := cmd.ProcessState.Sys().(syscall.WaitStatus)
  return status.ExitStatus()
}

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

func buildArgs(command []string) string {
  return strings.Join(command, " ")
}

func wrapForShell(command string) []string {
  return append([]string {"-c"}, fmt.Sprintf("%s; eval %s", sourceFiles(), command))
}

func sourceFiles() string {
  return fmt.Sprintf("%s %s", getShellSourceCmd(), getSourceFilePath())
}

func getSourceFilePath() string {
  return "~/.zshrc"
}

func getShellSourceCmd() string {
  return "."
}

func getShell() string {
  bin, found := syscall.Getenv("SHELL")
  if found == false {
    bin, _ = exec.LookPath("sh")
  }
  return bin
}

func loop(d time.Duration, fn func()) {
  fn()
  select {
  case <- time.After(d):
    loop(d, fn)
  }
}
<|endoftext|>


<commit_before>// gogetdoc gets documentation for Go objects given their locations in the source code
package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"strconv"
	"strings"

	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)

var (
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
	pos        = flag.String("pos", "", "Filename and byte offset of item to document, e.g. foo.go:#123")
	modified   = flag.Bool("modified", false, "read an archive of modified files from standard input")
)

const modifiedUsage = `
The archive format for the -modified flag consists of the file name, followed
by a newline, the decimal file size, another newline, and the contents of the file.

This allows editors to supply gogetdoc with the contents of their unsaved buffers.
`

const (
	indent     = ""
	preIndent  = "    "
	lineLength = 80
)

// Doc holds the resulting documentation for a particular item.
type Doc struct {
	Name  string
	Title string
	Doc   string
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, modifiedUsage)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}
	filename, offset, err := parsePos(*pos)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	ctx := &build.Default
	if *modified {
		overlay, err := parseModified(os.Stdin)
		if err != nil {
			log.Fatalln("invalid archive:", err)
		}
		ctx = overlayContext(ctx, overlay)
	}

	d, err := Run(ctx, filename, offset)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// TODO: output format
	fmt.Println(d.Title, "\n")
	doc.ToText(os.Stdout, d.Doc, indent, preIndent, lineLength)
}

// Run is a wrapper for the gogetdoc command.  It is broken out of main for easier testing.
func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.New("gogetdoc: couldn't get working directory")
	}
	bp, err := buildutil.ContainingPackage(ctx, wd, filename)
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
	}
	conf := &loader.Config{
		Build:               ctx,
		ParserMode:          parser.ParseComments,
		TypeCheckFuncBodies: func(pkg string) bool { return pkg == bp.ImportPath },
		AllowErrors:         true,
	}

	seenError := false
	conf.TypeChecker.Error = func(err error) {
		if seenError {
			return
		}
		fmt.Fprintln(os.Stderr, err)
		seenError = true
	}
	conf.ImportWithTests(bp.ImportPath)
	lprog, err := conf.Load()
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: error loading program: %s", err.Error())
	}
	return DocForPos(lprog, filename, offset)
}

// DocForPos attempts to get the documentation for an item given a filename and byte offset.
func DocForPos(lprog *loader.Program, filename string, offset int64) (*Doc, error) {
	tokFile := FileFromProgram(lprog, filename)
	if tokFile == nil {
		return nil, fmt.Errorf("gogetdoc: couldn't find %s in program", filename)
	}
	offPos := tokFile.Pos(int(offset))

	pkgInfo, nodes, _ := lprog.PathEnclosingInterval(offPos, offPos)
	for _, node := range nodes {
		switch i := node.(type) {
		case *ast.ImportSpec:
			return PackageDoc(lprog.Fset, ImportPath(i))
		case *ast.Ident:
			// if we can't find the object denoted by the identifier, keep searching)
			if obj := pkgInfo.ObjectOf(i); obj == nil {
				continue
			}
			return IdentDoc(i, pkgInfo, lprog)
		case *ast.File:
			if i.Doc != nil {
				return &Doc{
					Doc: i.Doc.Text(),
				}, nil
			}
		}
	}
	return nil, errors.New("gogetdoc: no documentation found")
}

// FileFromProgram attempts to locate a token.File from a loaded program.
func FileFromProgram(prog *loader.Program, name string) *token.File {
	for _, info := range prog.AllPackages {
		for _, astFile := range info.Files {
			tokFile := prog.Fset.File(astFile.Pos())
			tokName := tokFile.Name()
			if runtime.GOOS == "windows" {
				tokName = filepath.ToSlash(tokName)
				name = filepath.ToSlash(name)
			}
			if tokName == name {
				return tokFile
			}
			if sameFile(tokName, name) {
				return tokFile
			}
		}
	}
	return nil
}

func parsePos(p string) (filename string, offset int64, err error) {
	// foo.go:#123
	if p == "" {
		err = errors.New("missing required -pos flag")
		return
	}
	sep := strings.LastIndex(p, ":")
	// need at least 2 characters after the ':'
	// (the # sign and the offset)
	if sep == -1 || sep > len(p)-2 || p[sep+1] != '#' {
		err = fmt.Errorf("invalid option: -pos=%s", p)
		return
	}
	filename = p[:sep]
	offset, err = strconv.ParseInt(p[sep+2:], 10, 32)
	return
}

func parseModified(r io.Reader) (map[string][]byte, error) {
	out := map[string][]byte{}
	br := bufio.NewReader(r)
	for {
		name, err := br.ReadString('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("error reading name in archive: %s", err)
		}
		name = filepath.Clean(strings.TrimSpace(name))
		size, err := br.ReadString('\n')
		if err != nil {
			return nil, fmt.Errorf("error reading size in archive: %s", err)
		}
		size = strings.TrimSpace(size)
		n, err := strconv.Atoi(size)
		if err != nil {
			return nil, fmt.Errorf("invalid size in archive: %s", err)
		}
		b := make([]byte, n)
		_, err = io.ReadFull(br, b)
		if err != nil {
			return nil, fmt.Errorf("error reading archive content: %s", err)
		}
		out[name] = b
	}
	return out, nil
}

func overlayContext(ctx *build.Context, overlay map[string][]byte) *build.Context {
	newCtx := *ctx
	newCtx.OpenFile = func(name string) (io.ReadCloser, error) {
		if b, ok := overlay[name]; ok {
			return ioutil.NopCloser(bytes.NewReader(b)), nil
		}

		for path, b := range overlay {
			if sameFile(name, path) {
				return ioutil.NopCloser(bytes.NewReader(b)), nil
			}
		}

		return buildutil.OpenFile(ctx, name)
	}

	return &newCtx
}

func sameFile(a, b string) bool {
	if filepath.Base(a) != filepath.Base(b) {
		// We only care about symlinks for the GOPATH itself. File
		// names need to match.
		return false
	}
	if ai, err := os.Stat(a); err == nil {
		if bi, err := os.Stat(b); err == nil {
			return os.SameFile(ai, bi)
		}
	}
	return false
}
<commit_msg>Only print typecheck error if no documentation found<commit_after>// gogetdoc gets documentation for Go objects given their locations in the source code
package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"strconv"
	"strings"

	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)

var (
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
	pos        = flag.String("pos", "", "Filename and byte offset of item to document, e.g. foo.go:#123")
	modified   = flag.Bool("modified", false, "read an archive of modified files from standard input")
)

const modifiedUsage = `
The archive format for the -modified flag consists of the file name, followed
by a newline, the decimal file size, another newline, and the contents of the file.

This allows editors to supply gogetdoc with the contents of their unsaved buffers.
`

const (
	indent     = ""
	preIndent  = "    "
	lineLength = 80
)

// Doc holds the resulting documentation for a particular item.
type Doc struct {
	Name  string
	Title string
	Doc   string
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, modifiedUsage)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}
	filename, offset, err := parsePos(*pos)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	ctx := &build.Default
	if *modified {
		overlay, err := parseModified(os.Stdin)
		if err != nil {
			log.Fatalln("invalid archive:", err)
		}
		ctx = overlayContext(ctx, overlay)
	}

	d, err := Run(ctx, filename, offset)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// TODO: output format
	fmt.Println(d.Title, "\n")
	doc.ToText(os.Stdout, d.Doc, indent, preIndent, lineLength)
}

// Run is a wrapper for the gogetdoc command.  It is broken out of main for easier testing.
func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.New("gogetdoc: couldn't get working directory")
	}
	bp, err := buildutil.ContainingPackage(ctx, wd, filename)
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
	}
	conf := &loader.Config{
		Build:               ctx,
		ParserMode:          parser.ParseComments,
		TypeCheckFuncBodies: func(pkg string) bool { return pkg == bp.ImportPath },
		AllowErrors:         true,
	}

	var parseError error
	conf.TypeChecker.Error = func(err error) {
		if parseError != nil {
			return
		}
		parseError = err
	}
	conf.ImportWithTests(bp.ImportPath)
	lprog, err := conf.Load()
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: error loading program: %s", err.Error())
	}
	doc, err := DocForPos(lprog, filename, offset)
	if err != nil {
		fmt.Fprintln(os.Stderr, parseError)
	}
	return doc, err
}

// DocForPos attempts to get the documentation for an item given a filename and byte offset.
func DocForPos(lprog *loader.Program, filename string, offset int64) (*Doc, error) {
	tokFile := FileFromProgram(lprog, filename)
	if tokFile == nil {
		return nil, fmt.Errorf("gogetdoc: couldn't find %s in program", filename)
	}
	offPos := tokFile.Pos(int(offset))

	pkgInfo, nodes, _ := lprog.PathEnclosingInterval(offPos, offPos)
	for _, node := range nodes {
		switch i := node.(type) {
		case *ast.ImportSpec:
			return PackageDoc(lprog.Fset, ImportPath(i))
		case *ast.Ident:
			// if we can't find the object denoted by the identifier, keep searching)
			if obj := pkgInfo.ObjectOf(i); obj == nil {
				continue
			}
			return IdentDoc(i, pkgInfo, lprog)
		case *ast.File:
			if i.Doc != nil {
				return &Doc{
					Doc: i.Doc.Text(),
				}, nil
			}
		}
	}
	return nil, errors.New("gogetdoc: no documentation found")
}

// FileFromProgram attempts to locate a token.File from a loaded program.
func FileFromProgram(prog *loader.Program, name string) *token.File {
	for _, info := range prog.AllPackages {
		for _, astFile := range info.Files {
			tokFile := prog.Fset.File(astFile.Pos())
			tokName := tokFile.Name()
			if runtime.GOOS == "windows" {
				tokName = filepath.ToSlash(tokName)
				name = filepath.ToSlash(name)
			}
			if tokName == name {
				return tokFile
			}
			if sameFile(tokName, name) {
				return tokFile
			}
		}
	}
	return nil
}

func parsePos(p string) (filename string, offset int64, err error) {
	// foo.go:#123
	if p == "" {
		err = errors.New("missing required -pos flag")
		return
	}
	sep := strings.LastIndex(p, ":")
	// need at least 2 characters after the ':'
	// (the # sign and the offset)
	if sep == -1 || sep > len(p)-2 || p[sep+1] != '#' {
		err = fmt.Errorf("invalid option: -pos=%s", p)
		return
	}
	filename = p[:sep]
	offset, err = strconv.ParseInt(p[sep+2:], 10, 32)
	return
}

func parseModified(r io.Reader) (map[string][]byte, error) {
	out := map[string][]byte{}
	br := bufio.NewReader(r)
	for {
		name, err := br.ReadString('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("error reading name in archive: %s", err)
		}
		name = filepath.Clean(strings.TrimSpace(name))
		size, err := br.ReadString('\n')
		if err != nil {
			return nil, fmt.Errorf("error reading size in archive: %s", err)
		}
		size = strings.TrimSpace(size)
		n, err := strconv.Atoi(size)
		if err != nil {
			return nil, fmt.Errorf("invalid size in archive: %s", err)
		}
		b := make([]byte, n)
		_, err = io.ReadFull(br, b)
		if err != nil {
			return nil, fmt.Errorf("error reading archive content: %s", err)
		}
		out[name] = b
	}
	return out, nil
}

func overlayContext(ctx *build.Context, overlay map[string][]byte) *build.Context {
	newCtx := *ctx
	newCtx.OpenFile = func(name string) (io.ReadCloser, error) {
		if b, ok := overlay[name]; ok {
			return ioutil.NopCloser(bytes.NewReader(b)), nil
		}

		for path, b := range overlay {
			if sameFile(name, path) {
				return ioutil.NopCloser(bytes.NewReader(b)), nil
			}
		}

		return buildutil.OpenFile(ctx, name)
	}

	return &newCtx
}

func sameFile(a, b string) bool {
	if filepath.Base(a) != filepath.Base(b) {
		// We only care about symlinks for the GOPATH itself. File
		// names need to match.
		return false
	}
	if ai, err := os.Stat(a); err == nil {
		if bi, err := os.Stat(b); err == nil {
			return os.SameFile(ai, bi)
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"strconv"
	"syscall"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/boltdb/bolt"
	"github.com/docker/libcontainer/netlink"
	"github.com/rakyll/globalconf"
)

const (
	appName       = "tentacool"
	addressBucket = "address"
)

var (
	flagSocket = flag.String("socket", "/var/run/"+appName, "Path for unix socket")
	flagOwner  = flag.String("owner", "", "Ownership for socket")
	flagGroup  = flag.Int("group", -1, "Group for socket")
	flagDB     = flag.String("db", "/var/lib/"+appName+"/db", "Path for DB")
	// flagMode   = flag.Int("mode", 0640, "FileMode for socket")

	db *bolt.DB
	ln net.Listener
)

type Address struct {
	ID   string
	Link string
	IP   string
}

func main() {
	conf, err := globalconf.New(appName)
	if err != nil {
		log.Fatal(err)
	}
	conf.ParseAll()

	handler := rest.ResourceHandler{}
	err = handler.SetRoutes(
		&rest.Route{"GET", "/interfaces/:iface", GetIface},
		&rest.Route{"POST", "/address", PostAddress},
		&rest.Route{"Get", "/address/:address", GetAddress},
	)
	if err != nil {
		log.Fatal(err)
	}

	ln, err = net.Listen("unix", *flagSocket)
	if nil != err {
		log.Fatal(err)
	}

	if *flagOwner != "" {
		user, err := user.Lookup(*flagOwner)
		if err != nil {
			log.Fatal(err)
		}
		uid, err := strconv.Atoi(user.Uid)
		var gid int
		if *flagGroup != -1 {
			gid = *flagGroup
		} else {
			gid, err = strconv.Atoi(user.Gid)
		}
		if err := os.Chown(*flagSocket, uid, gid); err != nil {
			log.Fatal(err)
		}
	}

	// Handle common process-killing signals so we can gracefully shut down:
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
	go func(c chan os.Signal) {
		// Wait for a SIGINT or SIGKILL:
		sig := <-c
		log.Printf("Caught signal %s: shutting down.", sig)
		// Stop listening (and unlink the socket if unix type):
		ln.Close()
		db.Close()
		os.Exit(0)
	}(sigc)

	db, err = bolt.Open(*flagDB, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	db.Update(func(tx *bolt.Tx) (err error) {
		_, err = tx.CreateBucketIfNotExists([]byte(addressBucket))
		if err != nil {
			log.Fatal(err)
		}
		return
	})

	log.Fatal(http.Serve(ln, &handler))
	defer ln.Close()
}

func GetIface(w rest.ResponseWriter, req *rest.Request) {
	iface, err := net.InterfaceByName(req.PathParam("iface"))
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, err := iface.Addrs()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(ip)
}

func GetAddress(w rest.ResponseWriter, req *rest.Request) {
	id := req.PathParam("address")

	address := Address{}
	db.View(func(tx *bolt.Tx) (err error) {
		tmp := tx.Bucket([]byte(addressBucket)).Get([]byte(id))
		if err = json.Unmarshal(tmp, &address); err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	})
	w.WriteJson(address)
}

func PostAddress(w rest.ResponseWriter, req *rest.Request) {
	address := Address{}
	if err := req.DecodeJsonPayload(&address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, ipnet, err := net.ParseCIDR(address.IP)
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	iface, err := net.InterfaceByName(address.Link)
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if err := netlink.NetworkLinkAddIp(iface, ip, ipnet); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	db.Update(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		if address.ID == "" {
			int, err := b.NextSequence()
			if err != nil {
				log.Printf(err.Error())
				rest.Error(w, err.Error(), http.StatusInternalServerError)
				return err
			}
			address.ID = strconv.FormatUint(int, 10)
		}
		data, err := json.Marshal(address)
		if err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		err = b.Put([]byte(address.ID), []byte(data))
		return
	})
	db.View(func(tx *bolt.Tx) error {
		value := tx.Bucket([]byte(addressBucket)).Get([]byte(address.ID))
		log.Printf("The value of 'toto' is: %s\n", value)
		return nil
	})
	w.WriteJson(address)
}
<commit_msg>Add GET /interfaces<commit_after>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"strconv"
	"syscall"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/boltdb/bolt"
	"github.com/docker/libcontainer/netlink"
	"github.com/rakyll/globalconf"
)

const (
	appName       = "tentacool"
	addressBucket = "address"
)

var (
	flagSocket = flag.String("socket", "/var/run/"+appName, "Path for unix socket")
	flagOwner  = flag.String("owner", "", "Ownership for socket")
	flagGroup  = flag.Int("group", -1, "Group for socket")
	flagDB     = flag.String("db", "/var/lib/"+appName+"/db", "Path for DB")
	// flagMode   = flag.Int("mode", 0640, "FileMode for socket")

	db *bolt.DB
	ln net.Listener
)

type Address struct {
	ID   string
	Link string
	IP   string
}

func main() {
	conf, err := globalconf.New(appName)
	if err != nil {
		log.Fatal(err)
	}
	conf.ParseAll()

	handler := rest.ResourceHandler{}
	err = handler.SetRoutes(
		&rest.Route{"GET", "/interfaces", GetIfaces},
		&rest.Route{"GET", "/interfaces/:iface", GetIface},
		&rest.Route{"POST", "/address", PostAddress},
		&rest.Route{"Get", "/address/:address", GetAddress},
	)
	if err != nil {
		log.Fatal(err)
	}

	ln, err = net.Listen("unix", *flagSocket)
	if nil != err {
		log.Fatal(err)
	}

	if *flagOwner != "" {
		user, err := user.Lookup(*flagOwner)
		if err != nil {
			log.Fatal(err)
		}
		uid, err := strconv.Atoi(user.Uid)
		var gid int
		if *flagGroup != -1 {
			gid = *flagGroup
		} else {
			gid, err = strconv.Atoi(user.Gid)
		}
		if err := os.Chown(*flagSocket, uid, gid); err != nil {
			log.Fatal(err)
		}
	}

	// Handle common process-killing signals so we can gracefully shut down:
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
	go func(c chan os.Signal) {
		// Wait for a SIGINT or SIGKILL:
		sig := <-c
		log.Printf("Caught signal %s: shutting down.", sig)
		// Stop listening (and unlink the socket if unix type):
		ln.Close()
		db.Close()
		os.Exit(0)
	}(sigc)

	db, err = bolt.Open(*flagDB, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	db.Update(func(tx *bolt.Tx) (err error) {
		_, err = tx.CreateBucketIfNotExists([]byte(addressBucket))
		if err != nil {
			log.Fatal(err)
		}
		return
	})

	log.Fatal(http.Serve(ln, &handler))
	defer ln.Close()
}

func GetIfaces(w rest.ResponseWriter, req *rest.Request) {
	interfaces, err := net.Interfaces()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(interfaces)
}

func GetIface(w rest.ResponseWriter, req *rest.Request) {
	iface, err := net.InterfaceByName(req.PathParam("iface"))
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, err := iface.Addrs()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(ip)
}

func GetAddress(w rest.ResponseWriter, req *rest.Request) {
	id := req.PathParam("address")

	address := Address{}
	db.View(func(tx *bolt.Tx) (err error) {
		tmp := tx.Bucket([]byte(addressBucket)).Get([]byte(id))
		if err = json.Unmarshal(tmp, &address); err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	})
	w.WriteJson(address)
}

func PostAddress(w rest.ResponseWriter, req *rest.Request) {
	address := Address{}
	if err := req.DecodeJsonPayload(&address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, ipnet, err := net.ParseCIDR(address.IP)
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	iface, err := net.InterfaceByName(address.Link)
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if err := netlink.NetworkLinkAddIp(iface, ip, ipnet); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	db.Update(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		if address.ID == "" {
			int, err := b.NextSequence()
			if err != nil {
				log.Printf(err.Error())
				rest.Error(w, err.Error(), http.StatusInternalServerError)
				return err
			}
			address.ID = strconv.FormatUint(int, 10)
		}
		data, err := json.Marshal(address)
		if err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		err = b.Put([]byte(address.ID), []byte(data))
		return
	})
	db.View(func(tx *bolt.Tx) error {
		value := tx.Bucket([]byte(addressBucket)).Get([]byte(address.ID))
		log.Printf("The value of 'toto' is: %s\n", value)
		return nil
	})
	w.WriteJson(address)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"sync"
)

type RunnerOutput struct {
	Command string
	Raw     string
	Json    map[string]interface{}
}

func main() {
	// https://coderwall.com/p/zyxyeg/golang-having-fun-with-os-stdin-and-shell-pipes
	fi, err := os.Stdin.Stat()
	if err != nil {
		log.Fatalf("Failed getting stats from stdin: %s", err)
	}
	if fi.Mode()&os.ModeNamedPipe == 0 {
		// no piped data
		return
	}

	inputStream := bufio.NewScanner(os.Stdin)
	commands := []string{}

	// https://stackoverflow.com/a/12369689
	for inputStream.Scan() {
		inputCommand := inputStream.Text()
		commands = append(commands, inputCommand)
	}

	n := len(commands)
	runnerOutput := make(chan RunnerOutput, n)
	results := []RunnerOutput{}

	var wg sync.WaitGroup
	wg.Add(n)

	for i := 0; i < n; i++ {
		go runner(commands[i], &wg, runnerOutput)
	}

	for i := 0; i < n; i++ {
		results = append(results, <-runnerOutput)
	}

	wg.Wait()

	data, err := json.Marshal(results)
	if err != nil {
		log.Fatalf("JSON marshaling failed: %s", err)
	}

	fmt.Printf("%s\n", data)
}

func runner(cmd string, wg *sync.WaitGroup, output chan RunnerOutput) {
	defer wg.Done()

	out, _ := exec.Command("sh", "-c", cmd).CombinedOutput()

	var rawJson map[string]interface{}
	json.Unmarshal(out, &rawJson)

	output <- RunnerOutput{
		Command: cmd,
		Output:  string(out[:]),
		Json:    rawJson,
	}
}
<commit_msg>Fix typo<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"sync"
)

type RunnerOutput struct {
	Command string
	Raw     string
	Json    map[string]interface{}
}

func main() {
	// https://coderwall.com/p/zyxyeg/golang-having-fun-with-os-stdin-and-shell-pipes
	fi, err := os.Stdin.Stat()
	if err != nil {
		log.Fatalf("Failed getting stats from stdin: %s", err)
	}
	if fi.Mode()&os.ModeNamedPipe == 0 {
		// no piped data
		return
	}

	inputStream := bufio.NewScanner(os.Stdin)
	commands := []string{}

	// https://stackoverflow.com/a/12369689
	for inputStream.Scan() {
		inputCommand := inputStream.Text()
		commands = append(commands, inputCommand)
	}

	n := len(commands)
	runnerOutput := make(chan RunnerOutput, n)
	results := []RunnerOutput{}

	var wg sync.WaitGroup
	wg.Add(n)

	for i := 0; i < n; i++ {
		go runner(commands[i], &wg, runnerOutput)
	}

	for i := 0; i < n; i++ {
		results = append(results, <-runnerOutput)
	}

	wg.Wait()

	data, err := json.Marshal(results)
	if err != nil {
		log.Fatalf("JSON marshaling failed: %s", err)
	}

	fmt.Printf("%s\n", data)
}

func runner(cmd string, wg *sync.WaitGroup, output chan RunnerOutput) {
	defer wg.Done()

	out, _ := exec.Command("sh", "-c", cmd).CombinedOutput()

	var rawJson map[string]interface{}
	json.Unmarshal(out, &rawJson)

	output <- RunnerOutput{
		Command: cmd,
		Raw:     string(out[:]),
		Json:    rawJson,
	}
}
<|endoftext|>


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

package main

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

	"github.com/kelseyhightower/cpic/image"
)

var (
	config string
	output string
)

const version = "0.0.1"

// DefaultConfigPath is the default CoreOS cloud config file path to copy
// into OEM PXE image.
var DefaultConfigPath = "cloud-config.yml"

var help = `
cpic creates an OEM CoreOS PXE image by copying the source PXE
image along with the CoreOS cloud-config.yml into a new PXE image.

The -o flag specifies the output file name. If not specified, the
output file name depends on the arguments and derives from the name
of the source PXE image. If the source PXE image is in the current
working directory it will be overwritten.

The -c flag specifies the cloud-config file name. If not specified,
the cloud-config file name will be set to "cloud-config.yml". The
cloud-config file must exist.
`

func usage() {
	fmt.Fprintf(os.Stderr, "usage: cpic [-c cloud-config] [-o output] coreos_production_pxe_image.cpio.gz\n")
	flag.PrintDefaults()
}

func init() {
	flag.Usage = usage
	flag.StringVar(&config, "c", DefaultConfigPath, "coreos cloud config")
	flag.StringVar(&output, "o", "", "write output to file")
}

func copyConfig(w *image.Writer, path string) error {
	for _, d := range []string{"usr", "usr/share", "usr/share/oem"} {
		if err := w.WriteDir(d); err != nil {
			return err
		}
	}
	if err := w.WriteFile(path, "usr/share/oem/cloud-config.yml"); err != nil {
		return err
	}
	return nil
}

// Customize the CoreOS PXE image by creating the necessary OEM directories
// and copying the cloud-config file in place.
// See the "Adding a Custom OEM" section in the Booting CoreOS via PXE
// documentation - http://goo.gl/QrWvqN.
func customizeImage(in, config string) (temp *os.File, err error) {
	i, err := os.Open(in)
	if err != nil {
		return
	}
	defer i.Close()
	r, err := image.NewReader(i)
	if err != nil {
		return
	}
	defer r.Close()
	temp, err = ioutil.TempFile("", "")
	if err != nil {
		return
	}
	defer temp.Close()
	w, err := image.NewWriter(temp)
	if err != nil {
		return
	}
	if err = copyConfig(w, config); err != nil {
		return
	}
	defer w.Close()
	if err = image.Copy(w, r); err != nil {
		return
	}
	return
}

func Version() string {
	return fmt.Sprintf("cpic version %s", version)
}

func main() {
	flag.Parse()
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "version":
			fmt.Println(Version())
			os.Exit(0)
		case "help":
			usage()
			fmt.Fprintf(os.Stderr, help)
			os.Exit(0)
		}
	}
	if flag.Arg(0) == "" {
		log.Fatal("cpic: no pxe image provided")
	}
	in := flag.Arg(0)
	out := path.Base(in)
	if output != "" {
		out = output
	}
	temp, err := customizeImage(in, config)
	if err != nil {
		log.Fatal(err)
	}
	if err := os.Rename(temp.Name(), out); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>remove help command<commit_after>// Copyright 2014 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

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

	"github.com/kelseyhightower/cpic/image"
)

var (
	config string
	output string
)

const version = "0.0.1"

// DefaultConfigPath is the default CoreOS cloud config file path to copy
// into OEM PXE image.
var DefaultConfigPath = "cloud-config.yml"

func usage() {
	fmt.Fprintf(os.Stderr, "usage: cpic [-c cloud-config] [-o output] coreos_production_pxe_image.cpio.gz\n")
	flag.PrintDefaults()
}

func init() {
	flag.Usage = usage
	flag.StringVar(&config, "c", DefaultConfigPath, "coreos cloud config")
	flag.StringVar(&output, "o", "", "write output to file")
}

func copyConfig(w *image.Writer, path string) error {
	for _, d := range []string{"usr", "usr/share", "usr/share/oem"} {
		if err := w.WriteDir(d); err != nil {
			return err
		}
	}
	if err := w.WriteFile(path, "usr/share/oem/cloud-config.yml"); err != nil {
		return err
	}
	return nil
}

// Customize the CoreOS PXE image by creating the necessary OEM directories
// and copying the cloud-config file in place.
// See the "Adding a Custom OEM" section in the Booting CoreOS via PXE
// documentation - http://goo.gl/QrWvqN.
func customizeImage(in, config string) (temp *os.File, err error) {
	i, err := os.Open(in)
	if err != nil {
		return
	}
	defer i.Close()
	r, err := image.NewReader(i)
	if err != nil {
		return
	}
	defer r.Close()
	temp, err = ioutil.TempFile("", "")
	if err != nil {
		return
	}
	defer temp.Close()
	w, err := image.NewWriter(temp)
	if err != nil {
		return
	}
	if err = copyConfig(w, config); err != nil {
		return
	}
	defer w.Close()
	if err = image.Copy(w, r); err != nil {
		return
	}
	return
}

func versionExit() {
	fmt.Printf("cpic version %s\n", version)
	os.Exit(0)
}

func main() {
	flag.Parse()
	if len(os.Args) > 1 {
		if os.Args[1] == "version" {
			versionExit()
		}
	}
	if flag.Arg(0) == "" {
		log.Fatal("cpic: no pxe image provided")
	}
	in := flag.Arg(0)
	out := path.Base(in)
	if output != "" {
		out = output
	}
	temp, err := customizeImage(in, config)
	if err != nil {
		log.Fatal(err)
	}
	if err := os.Rename(temp.Name(), out); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


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

package main

import (
	"os"
	"bufio"

	"github.com/mwmahlberg/snap/internal"

	dbg "github.com/tj/go-debug"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	unsnap  = kingpin.Flag("unsnap", "uncompress file").Short('u').Bool()
	inFile  = kingpin.Arg("file", "file to (de)compress").Required().File()
//	keep    = kingpin.Flag("keep", "keep original file").Short('k').Default("false").Bool()
	outFile *os.File
)

func init() {

	debug := dbg.Debug("INIT")
	kingpin.Version("0.1")
	kingpin.CommandLine.HelpFlag.Short('h')

	kingpin.Parse()

	if os.Args[0] == "unsnap" {
		debug("Called as 'unsnap'. Decompressing source file")
		*unsnap = true
	}

}

func main() {
	var debug = dbg.Debug("MAIN")
	defer (*inFile).Close()

	var outFileName string

	if *unsnap {
		in := []rune((*inFile).Name())
		outFileName = string(in[:len(in)-3])
		debug("Name: %s", outFileName)
	} else {
		outFileName = (*inFile).Name() + `.sz`
	}

	fi, err := (*inFile).Stat()
	kingpin.FatalIfError(err,"unable to access '%s'", (*inFile).Name())

	outFile, err := os.OpenFile(outFileName, os.O_CREATE|os.O_EXCL|os.O_WRONLY, fi.Mode())
	kingpin.FatalIfError(err,"unable to open '%s'",(*inFile).Name())
	defer outFile.Close()

	inbuf := bufio.NewReader(*inFile)
	outbuf := bufio.NewWriter(outFile)
	defer outbuf.Flush()

	s := internal.NewSnapper(inbuf, outbuf)

	if *unsnap {
		err := s.Unsnap()
		kingpin.FatalIfError(err,"error during decompression")
		return
	}

	err = s.Snap()
	kingpin.FatalIfError(err,"error during compression")

}
<commit_msg>Implemented "keep" flag, expanded help<commit_after>// Copyright ©2016 Markus W Mahlberg <markus@mahlberg.io>
//
//
// 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 (
	"bufio"
	"os"

	"github.com/mwmahlberg/snap/internal"

	dbg "github.com/tj/go-debug"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	unsnap  = kingpin.Flag("unsnap", "uncompress file").Short('u').Bool()
	inFile  = kingpin.Arg("file", "file to (de)compress").Required().File()
	keep    = kingpin.Flag("keep", "keep original file").Short('k').Default("false").Bool()
	outFile *os.File
)

func init() {

	debug := dbg.Debug("INIT")
	kingpin.UsageTemplate(kingpin.DefaultUsageTemplate).Version("0.1").Author("Markus W Mahlberg")
	kingpin.CommandLine.Author("Markus W Mahlberg")
	kingpin.CommandLine.Help="tool to (de-)compress files using snappy algorithm"
	kingpin.CommandLine.HelpFlag.Short('h')

	kingpin.Parse()

	if os.Args[0] == "unsnap" {
		debug("Called as 'unsnap'. Decompressing source file")
		*unsnap = true
	}

}

func main() {

	var debug = dbg.Debug("MAIN")

	var outFileName string

	if *unsnap {
		in := []rune((*inFile).Name())
		outFileName = string(in[:len(in)-3])
	} else {
		outFileName = (*inFile).Name() + `.sz`
	}
	debug("Outfile: %s", outFileName)

	fi, err := (*inFile).Stat()
	kingpin.FatalIfError(err, "unable to access '%s'", (*inFile).Name())

	outFile, err := os.OpenFile(outFileName, os.O_CREATE|os.O_EXCL|os.O_WRONLY, fi.Mode())
	kingpin.FatalIfError(err, "unable to open '%s'", (*inFile).Name())
	defer outFile.Close()

	inbuf := bufio.NewReader(*inFile)
	outbuf := bufio.NewWriter(outFile)
	defer outbuf.Flush()

	s := internal.NewSnapper(inbuf, outbuf)

	if *unsnap {
		err := s.Unsnap()
		kingpin.FatalIfError(err, "error during decompression")
	} else {
		err = s.Snap()
		kingpin.FatalIfError(err, "error during compression")
	}

	(*inFile).Close()

	if !(*keep) {
		debug("Removing source file after completion")
		err := os.Remove((*inFile).Name())
		kingpin.FatalIfError(err, "error while removing '%s': %v", (*inFile).Name(), err)
	}
}
<|endoftext|>


<commit_before>/* {{{ Copyright (c) Paul R. Tagliamonte <paultag@gmail.com>, 2015
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. }}} */

package main

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"pault.ag/go/config"
	"pault.ag/go/debian/control"
	"pault.ag/go/descend/descend"
)

func Missing(flags *flag.FlagSet, values ...string) {
	for _, value := range values {
		if value != "" {
			continue
		}
		flags.Usage()
		os.Exit(0)
	}
}

func main() {
	conf := descend.Descend{
		Host: "localhost",
		Port: 443,
	}
	flags, err := config.LoadFlags("descend", &conf)
	if err != nil {
		panic(err)
	}
	flags.Parse(os.Args[1:])
	Missing(flags, conf.CaCert, conf.Cert, conf.Key)

	caPool := x509.NewCertPool()
	x509CaCrt, err := ioutil.ReadFile(conf.CaCert)
	if err != nil {
		panic(err)
	}
	if ok := caPool.AppendCertsFromPEM(x509CaCrt); !ok {
		panic(fmt.Errorf("Error appending CA cert from PEM!"))
	}
	cert, err := tls.LoadX509KeyPair(conf.Cert, conf.Key)
	if err != nil {
		panic(err)
	}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			Certificates: []tls.Certificate{cert},
			ClientAuth:   tls.RequireAnyClientCert,
			RootCAs:      caPool,
		},
		DisableCompression: true,
	}

	for _, changesPath := range flags.Args() {
		changes, err := control.ParseChangesFile(changesPath)
		if err != nil {
			panic(err)
		}

		fmt.Printf("Pushing %s\n", changesPath)
		client := &http.Client{Transport: tr}
		err = descend.DoPutChanges(
			client, changes,
			fmt.Sprintf("%s:%d", conf.Host, conf.Port),
			conf.Archive,
		)
		if err != nil {
			panic(err)
		}
	}
}

// vim: foldmethod=marker
<commit_msg>refactor client creation<commit_after>/* {{{ Copyright (c) Paul R. Tagliamonte <paultag@gmail.com>, 2015
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. }}} */

package main

import (
	"flag"
	"fmt"
	"os"

	"pault.ag/go/config"
	"pault.ag/go/debian/control"
	"pault.ag/go/descend/descend"
)

func Missing(flags *flag.FlagSet, values ...string) {
	for _, value := range values {
		if value != "" {
			continue
		}
		flags.Usage()
		os.Exit(0)
	}
}

func main() {
	conf := descend.Descend{
		Host: "localhost",
		Port: 443,
	}
	flags, err := config.LoadFlags("descend", &conf)
	if err != nil {
		panic(err)
	}
	flags.Parse(os.Args[1:])
	Missing(flags, conf.CaCert, conf.Cert, conf.Key)

	client, err := descend.NewClient(conf.CaCert, conf.Cert, conf.Key)
	if err != nil {
		panic(err)
	}

	for _, changesPath := range flags.Args() {
		changes, err := control.ParseChangesFile(changesPath)
		if err != nil {
			panic(err)
		}

		fmt.Printf("Pushing %s\n", changesPath)
		err = descend.DoPutChanges(
			client, changes,
			fmt.Sprintf("%s:%d", conf.Host, conf.Port),
			conf.Archive,
		)
		if err != nil {
			panic(err)
		}
	}
}

// vim: foldmethod=marker
<|endoftext|>


<commit_before>package main

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

func ProxyServer(w http.ResponseWriter, req *http.Request) {
	for k, v := range req.Header {
		fmt.Printf("%s - %s\n", k, strings.Join(v, ","))
	}

	fmt.Fprintln(w, "ok")
}

func main() {
	http.HandleFunc("/", ProxyServer)
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Better request path<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func ProxyServer(w http.ResponseWriter, req *http.Request) {
	req.Header.Set("Host", req.Host)

	fmt.Printf("> %s %s %s\n", req.Method, reqPath(req), req.Proto)

	for k, v := range req.Header {
		fmt.Printf("> %s - %s\n", k, strings.Join(v, ","))
	}

	content, err := ioutil.ReadAll(req.Body)
	req.Body.Close()
	if err == nil {
		fmt.Println(string(content))
	}

	fmt.Println("")

	fmt.Fprintln(w, "ok")
}

func reqPath(req *http.Request) string {
	path := req.URL.Path
	query := []string{}
	for k, v := range req.URL.Query() {
		query = append(query, fmt.Sprintf("%s=%s", k, strings.Join(v, ",")))
	}

	if len(query) > 0 {
		path = fmt.Sprintf("%s?%s", path, strings.Join(query, "&"))
	}

	return path
}

func main() {
	http.HandleFunc("/", ProxyServer)
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	_ "github.com/astaxie/beego/session/mysql" // used for all session stores
	_ "github.com/astaxie/beego/session/redis"
	_ "github.com/nhatvhm/asolution/models"
	_ "github.com/nhatvhm/asolution/routers"
	_ "github.com/lib/pq"
	"log"
	"time"
)

var (
   dbConnectString string = beego.AppConfig.String("dbConnectString")
   dbDriverName string = beego.AppConfig.String("dbDriverName")
   dbMaxIdle, dbMaxIdleErr = beego.AppConfig.Int("dbMaxIdle")
   dbMaxConn, dbMaxConnErr = beego.AppConfig.Int("dbMaxConn")
 )

func init() {
	// Development Settings, adjust for production
	// mysql / sqlite3 / postgres driver registered by default already
	orm.RegisterDriver(dbDriverName, orm.DRPostgres)

	if dbMaxIdleErr != nil {
      panic("Main Init: - Unable to start the server can't parse dbMaxIdleErr from configuration file must be int.")
    }

    if dbMaxConnErr != nil {
      panic("Main Init: - Unable to start the server can't parse dbMaxConnErr from configuration file must be int.")
    }

	//                    db alias  drivername
	orm.RegisterDataBase("default", dbDriverName, dbConnectString, dbMaxIdle, dbMaxConn)
	orm.DefaultTimeLoc = time.UTC

}

func main() {
	//beego.TemplateLeft = "<<<" // set to make internal template compatible with most front ends i.e. Angular, Polymer, etc
	//beego.TemplateRight = ">>>"

	name := "default"
	// Whether to drop table and re-create.
	force := true
	// Print log.
	verbose := true
	// Error.
	err := orm.RunSyncdb(name, force, verbose)
	if err != nil {
		log.Println(err)
	}
	beego.Run()
}
<commit_msg>fix Web process failed to bind to  within 60 seconds of launch<commit_after>package main

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	_ "github.com/astaxie/beego/session/mysql" // used for all session stores
	_ "github.com/astaxie/beego/session/redis"
	_ "github.com/nhatvhm/asolution/models"
	_ "github.com/nhatvhm/asolution/routers"
	_ "github.com/lib/pq"
	"log"
	"time"
	"strconv"
    "os"
)

var (
   dbConnectString string = beego.AppConfig.String("dbConnectString")
   dbDriverName string = beego.AppConfig.String("dbDriverName")
   dbMaxIdle, dbMaxIdleErr = beego.AppConfig.Int("dbMaxIdle")
   dbMaxConn, dbMaxConnErr = beego.AppConfig.Int("dbMaxConn")
 )

func init() {
	// Development Settings, adjust for production
	// mysql / sqlite3 / postgres driver registered by default already
	orm.RegisterDriver(dbDriverName, orm.DRPostgres)

	if dbMaxIdleErr != nil {
      panic("Main Init: - Unable to start the server can't parse dbMaxIdleErr from configuration file must be int.")
    }

    if dbMaxConnErr != nil {
      panic("Main Init: - Unable to start the server can't parse dbMaxConnErr from configuration file must be int.")
    }

	//                    db alias  drivername
	orm.RegisterDataBase("default", dbDriverName, dbConnectString, dbMaxIdle, dbMaxConn)
	orm.DefaultTimeLoc = time.UTC

}

func main() {
	//beego.TemplateLeft = "<<<" // set to make internal template compatible with most front ends i.e. Angular, Polymer, etc
	//beego.TemplateRight = ">>>"

	name := "default"
	// Whether to drop table and re-create.
	force := true
	// Print log.
	verbose := true
	// Error.
	err := orm.RunSyncdb(name, force, verbose)
	if err != nil {
		log.Println(err)
	}
	// port, err := strconv.Atoi(os.Getenv("PORT"))
    if err == nil {
        beego.HttpPort = port
    }
	beego.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"sync"

	"github.com/yosisa/fluxion/buffer"
	"github.com/yosisa/fluxion/message"
	"github.com/yosisa/fluxion/plugin"
)

type Buffer struct {
	sync.Mutex
	Items []string
}

type Config struct {
	Listen string
}

type NetbufOutput struct {
	env    *plugin.Env
	conf   *Config
	ln     net.Listener
	bufs   map[string]*Buffer
	lock   sync.Mutex
	closed bool
}

func (p *NetbufOutput) Init(env *plugin.Env) (err error) {
	p.env = env
	p.conf = &Config{}
	p.bufs = make(map[string]*Buffer)
	return env.ReadConfig(p.conf)
}

func (p *NetbufOutput) Start() (err error) {
	if p.ln, err = net.Listen("tcp", p.conf.Listen); err != nil {
		return
	}
	go p.accepter()
	return
}

func (p *NetbufOutput) Encode(ev *message.Event) (buffer.Sizer, error) {
	t := ev.Time.Format("2006/01/02 15:04:05 MST")
	s := buffer.StringItem(fmt.Sprintf("%s %s %s", t, ev.Tag, ev.Record["message"]))
	return s, nil
}

func (p *NetbufOutput) Write(l []buffer.Sizer) (int, error) {
	for _, buf := range p.bufs {
		buf.Lock()
		for _, s := range l {
			buf.Items = append(buf.Items, string(s.(buffer.StringItem)))
		}
		buf.Unlock()
	}
	return len(l), nil
}

func (p *NetbufOutput) Close() error {
	p.closed = true
	return p.ln.Close()
}

func (p *NetbufOutput) accepter() {
	for !p.closed {
		conn, err := p.ln.Accept()
		if err != nil {
			continue
		}
		go p.handler(conn)
	}
}

func (p *NetbufOutput) handler(conn net.Conn) {
	defer conn.Close()
	remote, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
	p.env.Log.Infof("Connected from %s", remote)
	buf, ok := p.bufs[remote]
	if !ok {
		p.env.Log.Infof("No buffer found for %s, create now", remote)
		p.addBuffer(remote)
		return
	}

	buf.Lock()
	defer buf.Unlock()

	p.env.Log.Infof("Send %d line to %s", len(buf.Items), remote)
	for i, s := range buf.Items {
		if _, err := conn.Write([]byte(s + "\n")); err != nil {
			p.env.Log.Warning(err)
			buf.Items = buf.Items[i:]
			return
		}
	}
	buf.Items = buf.Items[:0]
}

func (p *NetbufOutput) addBuffer(name string) {
	p.lock.Lock()
	defer p.lock.Unlock()
	if _, ok := p.bufs[name]; ok {
		return
	}
	p.bufs[name] = &Buffer{}
}

func main() {
	plugin.New("out-netbuf", func() plugin.Plugin {
		return &NetbufOutput{}
	}).Run()
}
<commit_msg>Add TTL support<commit_after>package main

import (
	"fmt"
	"net"
	"sync"
	"time"

	"github.com/yosisa/fluxion/buffer"
	"github.com/yosisa/fluxion/message"
	"github.com/yosisa/fluxion/plugin"
)

type Buffer struct {
	sync.Mutex
	Items        []string
	LastAccessed time.Time
}

type Config struct {
	Listen string
	TTL    buffer.Duration
}

type NetbufOutput struct {
	env    *plugin.Env
	conf   *Config
	ln     net.Listener
	bufs   map[string]*Buffer
	lock   sync.Mutex
	closed bool
}

func (p *NetbufOutput) Init(env *plugin.Env) (err error) {
	p.env = env
	p.conf = &Config{}
	p.bufs = make(map[string]*Buffer)
	return env.ReadConfig(p.conf)
}

func (p *NetbufOutput) Start() (err error) {
	if p.ln, err = net.Listen("tcp", p.conf.Listen); err != nil {
		return
	}
	go p.accepter()
	if p.conf.TTL > 0 {
		p.env.Log.Infof("Enable gc: ttl %v", time.Duration(p.conf.TTL))
		go p.gc()
	}
	return
}

func (p *NetbufOutput) Encode(ev *message.Event) (buffer.Sizer, error) {
	t := ev.Time.Format("2006/01/02 15:04:05 MST")
	s := buffer.StringItem(fmt.Sprintf("%s %s %s", t, ev.Tag, ev.Record["message"]))
	return s, nil
}

func (p *NetbufOutput) Write(l []buffer.Sizer) (int, error) {
	for _, buf := range p.bufs {
		buf.Lock()
		for _, s := range l {
			buf.Items = append(buf.Items, string(s.(buffer.StringItem)))
		}
		buf.Unlock()
	}
	return len(l), nil
}

func (p *NetbufOutput) Close() error {
	p.closed = true
	return p.ln.Close()
}

func (p *NetbufOutput) accepter() {
	for !p.closed {
		conn, err := p.ln.Accept()
		if err != nil {
			continue
		}
		go p.handler(conn)
	}
}

func (p *NetbufOutput) handler(conn net.Conn) {
	defer conn.Close()
	remote, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
	p.env.Log.Infof("Connected from %s", remote)
	buf, ok := p.bufs[remote]
	if !ok {
		p.env.Log.Infof("No buffer found for %s, create now", remote)
		p.addBuffer(remote)
		return
	}

	buf.Lock()
	defer buf.Unlock()

	buf.LastAccessed = time.Now()
	p.env.Log.Infof("Send %d line to %s", len(buf.Items), remote)
	for i, s := range buf.Items {
		if _, err := conn.Write([]byte(s + "\n")); err != nil {
			p.env.Log.Warning(err)
			buf.Items = buf.Items[i:]
			return
		}
	}
	buf.Items = buf.Items[:0]
}

func (p *NetbufOutput) addBuffer(name string) {
	p.lock.Lock()
	defer p.lock.Unlock()
	if _, ok := p.bufs[name]; ok {
		return
	}
	p.bufs[name] = &Buffer{
		LastAccessed: time.Now(),
	}
}

func (p *NetbufOutput) gc() {
	ttl := time.Duration(p.conf.TTL)
	for _ = range time.Tick(time.Minute) {
		p.lock.Lock()
		now := time.Now()
		for remote, buf := range p.bufs {
			if now.After(buf.LastAccessed.Add(ttl)) {
				p.env.Log.Infof("Buffer for %s is expired, last access %v", remote, buf.LastAccessed)
				delete(p.bufs, remote)
			}
		}
		p.lock.Unlock()
	}
}

func main() {
	plugin.New("out-netbuf", func() plugin.Plugin {
		return &NetbufOutput{}
	}).Run()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/cloud66/habitus/build"
	"github.com/cloud66/habitus/configuration"
	"github.com/op/go-logging"

	"github.com/bugsnag/bugsnag-go"
)

var format = logging.MustStringFormatter(
	"%{color}▶ %{message} %{color:reset}",
)

var (
	flagLevel       string
	flagShowHelp    bool
	flagShowVersion bool
	VERSION         string = "dev"
	BUILD_DATE      string = ""
)

func init() {
	bugsnag.Configure(bugsnag.Configuration{
		APIKey:     "ba9d7ae6b333e27971d86e5bf7abe996",
		AppVersion: VERSION,
	})
}

func main() {
	args := os.Args[1:]
	defer bugsnag.AutoNotify()

	var log = logging.MustGetLogger("cxbuilder")
	logging.SetFormatter(format)

	config := configuration.CreateConfig()
	flag.StringVar(&config.Buildfile, "f", "build.yml", "Build file path. Defaults to build.yml in the workdir")
	flag.StringVar(&config.Workdir, "d", "", "work directory for this build. Defaults to the current directory")
	flag.BoolVar(&config.NoCache, "no-cache", false, "Use cache in build")
	flag.BoolVar(&config.SuppressOutput, "suppress", false, "Suppress build output")
	flag.BoolVar(&config.RmTmpContainers, "rm", true, "Remove intermediate containers")
	flag.BoolVar(&config.ForceRmTmpContainer, "force-rm", false, "Force remove intermediate containers")
	flag.StringVar(&config.UniqueID, "uid", "", "Unique ID for the build. Used only for multi-tenanted build environments")
	flag.StringVar(&flagLevel, "level", "debug", "Log level: debug, info, notice, warning, error and critical")
	flag.StringVar(&config.DockerHost, "host", os.Getenv("DOCKER_HOST"), "Docker host link. Uses DOCKER_HOST if missing")
	flag.StringVar(&config.DockerCert, "certs", os.Getenv("DOCKER_CERT_PATH"), "Docker cert folder. Uses DOCKER_CERT_PATH if missing")
	flag.Var(&config.EnvVars, "env", "Environment variables to be used during build. If empty cxbuild uses parent process environment variables")
	flag.BoolVar(&config.KeepSteps, "keep-steps", false, "Keep all stpes. Used for debugging each step")
	flag.BoolVar(&config.NoSquash, "no-cleanup", false, "Skip cleanup commands for this run. Used for debugging")
	flag.BoolVar(&config.FroceRmImages, "force-rmi", false, "Force remove of unwanted images")
	flag.BoolVar(&config.NoPruneRmImages, "noprune-rmi", false, "No pruning of unwanted images")
	flag.BoolVar(&flagShowHelp, "help", false, "Display the help")
	flag.BoolVar(&flagShowVersion, "version", false, "Display version information")

	config.Logger = *log

	flag.Parse()

	if flagShowHelp || (len(args) > 0 && args[0] == "help") {
		fmt.Println("Habitus - (c) 2016 Cloud 66 Inc.")
		flag.PrintDefaults()
		return
	}

	if flagShowVersion || (len(args) > 0 && args[0] == "version") {
		if BUILD_DATE == "" {
			fmt.Printf("Habitus - v%s (c) 2016 Cloud 66 Inc.\n", VERSION)
		} else {
			fmt.Printf("Habitus - v%s (%s) (c) 2016 Cloud 66 Inc.\n", VERSION, BUILD_DATE)
		}
		return
	}

	level, err := logging.LogLevel(flagLevel)
	if err != nil {
		fmt.Println("Invalid log level value. Falling back to debug")
		level = logging.DEBUG
	}
	logging.SetLevel(level, "cxbuilder")

	if config.Workdir == "" {
		if curr, err := os.Getwd(); err != nil {
			log.Fatal("Failed to get the current directory")
			os.Exit(1)
		} else {
			config.Workdir = curr
		}
	}

	if config.Buildfile == "build.yml" {
		config.Buildfile = filepath.Join(config.Workdir, "build.yml")
	}

	c, err := build.LoadBuildFromFile(&config)
	if err != nil {
		log.Fatalf("Failed: %s", err.Error())
	}

	if c.IsPrivileged && os.Getenv("SUDO_USER") == "" {
		log.Fatal("Some of the build steps require admin privileges (sudo). Please run with sudo\nYou might want to use --certs=$DOCKER_CERT_PATH --host=$DOCKER_HOST params to make sure all environment variables are available to the process")
		os.Exit(1)
	}

	b := build.NewBuilder(c, &config)
	err = b.StartBuild()
	if err != nil {
		log.Error("Error during build %s", err.Error())
	}
}
<commit_msg>include plain-format for auto-output<commit_after>package main

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

	"github.com/cloud66/habitus/build"
	"github.com/cloud66/habitus/configuration"
	"github.com/op/go-logging"

	"github.com/bugsnag/bugsnag-go"
)

var prettyFormat = logging.MustStringFormatter(
	"%{color}▶ %{message} %{color:reset}",
)
var plainFormat = logging.MustStringFormatter(
	"> %{message}",
)

var (
	flagLevel       string
	flagShowHelp    bool
	flagShowVersion bool
	flagPrettyLog   bool
	VERSION         string = "dev"
	BUILD_DATE      string = ""
)

func init() {
	bugsnag.Configure(bugsnag.Configuration{
		APIKey:     "ba9d7ae6b333e27971d86e5bf7abe996",
		AppVersion: VERSION,
	})
}

func main() {
	args := os.Args[1:]
	defer bugsnag.AutoNotify()

	var log = logging.MustGetLogger("cxbuilder")
	logging.SetFormatter(plainFormat)

	config := configuration.CreateConfig()
	flag.StringVar(&config.Buildfile, "f", "build.yml", "Build file path. Defaults to build.yml in the workdir")
	flag.StringVar(&config.Workdir, "d", "", "work directory for this build. Defaults to the current directory")
	flag.BoolVar(&config.NoCache, "no-cache", false, "Use cache in build")
	flag.BoolVar(&config.SuppressOutput, "suppress", false, "Suppress build output")
	flag.BoolVar(&config.RmTmpContainers, "rm", true, "Remove intermediate containers")
	flag.BoolVar(&config.ForceRmTmpContainer, "force-rm", false, "Force remove intermediate containers")
	flag.StringVar(&config.UniqueID, "uid", "", "Unique ID for the build. Used only for multi-tenanted build environments")
	flag.StringVar(&flagLevel, "level", "debug", "Log level: debug, info, notice, warning, error and critical")
	flag.BoolVar(&flagPrettyLog, "pretty", true, "Display logs with color and formatting")
	flag.StringVar(&config.DockerHost, "host", os.Getenv("DOCKER_HOST"), "Docker host link. Uses DOCKER_HOST if missing")
	flag.StringVar(&config.DockerCert, "certs", os.Getenv("DOCKER_CERT_PATH"), "Docker cert folder. Uses DOCKER_CERT_PATH if missing")
	flag.Var(&config.EnvVars, "env", "Environment variables to be used during build. If empty cxbuild uses parent process environment variables")
	flag.BoolVar(&config.KeepSteps, "keep-steps", false, "Keep all stpes. Used for debugging each step")
	flag.BoolVar(&config.NoSquash, "no-cleanup", false, "Skip cleanup commands for this run. Used for debugging")
	flag.BoolVar(&config.FroceRmImages, "force-rmi", false, "Force remove of unwanted images")
	flag.BoolVar(&config.NoPruneRmImages, "noprune-rmi", false, "No pruning of unwanted images")
	flag.BoolVar(&flagShowHelp, "help", false, "Display the help")
	flag.BoolVar(&flagShowVersion, "version", false, "Display version information")

	config.Logger = *log
	flag.Parse()

	if flagPrettyLog {
		logging.SetFormatter(prettyFormat)
		// config.Logger = *log
	}

	if flagShowHelp || (len(args) > 0 && args[0] == "help") {
		fmt.Println("Habitus - (c) 2016 Cloud 66 Inc.")
		flag.PrintDefaults()
		return
	}

	if flagShowVersion || (len(args) > 0 && args[0] == "version") {
		if BUILD_DATE == "" {
			fmt.Printf("Habitus - v%s (c) 2016 Cloud 66 Inc.\n", VERSION)
		} else {
			fmt.Printf("Habitus - v%s (%s) (c) 2016 Cloud 66 Inc.\n", VERSION, BUILD_DATE)
		}
		return
	}

	level, err := logging.LogLevel(flagLevel)
	if err != nil {
		fmt.Println("Invalid log level value. Falling back to debug")
		level = logging.DEBUG
	}
	logging.SetLevel(level, "cxbuilder")

	if config.Workdir == "" {
		if curr, err := os.Getwd(); err != nil {
			log.Fatal("Failed to get the current directory")
			os.Exit(1)
		} else {
			config.Workdir = curr
		}
	}

	if config.Buildfile == "build.yml" {
		config.Buildfile = filepath.Join(config.Workdir, "build.yml")
	}

	c, err := build.LoadBuildFromFile(&config)
	if err != nil {
		log.Fatalf("Failed: %s", err.Error())
	}

	if c.IsPrivileged && os.Getenv("SUDO_USER") == "" {
		log.Fatal("Some of the build steps require admin privileges (sudo). Please run with sudo\nYou might want to use --certs=$DOCKER_CERT_PATH --host=$DOCKER_HOST params to make sure all environment variables are available to the process")
		os.Exit(1)
	}

	b := build.NewBuilder(c, &config)
	err = b.StartBuild()
	if err != nil {
		log.Error("Error during build %s", err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jessevdk/go-flags"
	_ "github.com/lib/pq"
	"os"
	"os/exec"
	"os/signal"
)

const VERSION = "0.3.0"

var options struct {
	Version  bool   `short:"v" long:"version" description:"Print version"`
	Debug    bool   `short:"d" long:"debug" description:"Enable debugging mode" default:"false"`
	Url      string `long:"url" description:"Database connection string"`
	Host     string `long:"host" description:"Server hostname or IP" default:"localhost"`
	Port     int    `long:"port" description:"Server port" default:"5432"`
	User     string `long:"user" description:"Database user" default:"postgres"`
	DbName   string `long:"db" description:"Database name" default:"postgres"`
	Ssl      string `long:"ssl" description:"SSL option" default:"disable"`
	HttpPort uint   `long:"listen" description:"HTTP server listen port" default:"8080"`
}

var dbClient *Client

func exitWithMessage(message string) {
	fmt.Println("Error:", message)
	os.Exit(1)
}

func getConnectionString() string {
	if options.Url != "" {
		return options.Url
	}

	return fmt.Sprintf(
		"host=%s port=%d user=%s dbname=%s sslmode=disable",
		options.Host, options.Port,
		options.User, options.DbName,
	)
}

func initClient() {
	client, err := NewClient()
	if err != nil {
		exitWithMessage(err.Error())
	}

	fmt.Println("Connecting to server...")
	err = client.Test()
	if err != nil {
		exitWithMessage(err.Error())
	}

	fmt.Println("Checking tables...")
	tables, err := client.Tables()
	if err != nil {
		exitWithMessage(err.Error())
	}

	if len(tables) == 0 {
		exitWithMessage("Database does not have any tables")
	}

	dbClient = client
}

func initOptions() {
	_, err := flags.ParseArgs(&options, os.Args)

	if err != nil {
		os.Exit(1)
	}

	if options.Url == "" {
		options.Url = os.Getenv("DATABASE_URL")
	}

	if options.Version {
		fmt.Printf("pgweb v%s\n", VERSION)
		os.Exit(0)
	}
}

func startServer() {
	router := gin.Default()

	router.GET("/", API_Home)
	router.GET("/databases", API_GetDatabases)
	router.GET("/info", API_Info)
	router.GET("/tables", API_GetTables)
	router.GET("/tables/:table", API_GetTable)
	router.GET("/tables/:table/info", API_GetTableInfo)
	router.GET("/tables/:table/indexes", API_TableIndexes)
	router.GET("/query", API_RunQuery)
	router.POST("/query", API_RunQuery)
	router.GET("/explain", API_ExplainQuery)
	router.POST("/explain", API_ExplainQuery)
	router.GET("/history", API_History)
	router.GET("/static/:type/:name", API_ServeAsset)

	fmt.Println("Starting server...")
	go router.Run(fmt.Sprintf(":%v", options.HttpPort))
}

func handleSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	<-c
}

func openPage() {
	url := fmt.Sprintf("http://localhost:%v", options.HttpPort)
	fmt.Println("To view database open", url, "in browser")

	_, err := exec.Command("which", "open").Output()
	if err != nil {
		return
	}

	exec.Command("open", url).Output()
}

func main() {
	initOptions()
	initClient()

	defer dbClient.db.Close()

	if !options.Debug {
		gin.SetMode("release")
	}

	startServer()
	openPage()
	handleSignals()
}
<commit_msg>Use ssl flag when generating connection string, remove hardcoded value<commit_after>package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jessevdk/go-flags"
	_ "github.com/lib/pq"
	"os"
	"os/exec"
	"os/signal"
)

const VERSION = "0.3.0"

var options struct {
	Version  bool   `short:"v" long:"version" description:"Print version"`
	Debug    bool   `short:"d" long:"debug" description:"Enable debugging mode" default:"false"`
	Url      string `long:"url" description:"Database connection string"`
	Host     string `long:"host" description:"Server hostname or IP" default:"localhost"`
	Port     int    `long:"port" description:"Server port" default:"5432"`
	User     string `long:"user" description:"Database user" default:"postgres"`
	DbName   string `long:"db" description:"Database name" default:"postgres"`
	Ssl      string `long:"ssl" description:"SSL option" default:"disable"`
	HttpPort uint   `long:"listen" description:"HTTP server listen port" default:"8080"`
}

var dbClient *Client

func exitWithMessage(message string) {
	fmt.Println("Error:", message)
	os.Exit(1)
}

func getConnectionString() string {
	if options.Url != "" {
		return options.Url
	}

	return fmt.Sprintf(
		"host=%s port=%d user=%s dbname=%s sslmode=%s",
		options.Host, options.Port,
		options.User, options.DbName,
		options.Ssl,
	)
}

func initClient() {
	client, err := NewClient()
	if err != nil {
		exitWithMessage(err.Error())
	}

	fmt.Println("Connecting to server...")
	err = client.Test()
	if err != nil {
		exitWithMessage(err.Error())
	}

	fmt.Println("Checking tables...")
	tables, err := client.Tables()
	if err != nil {
		exitWithMessage(err.Error())
	}

	if len(tables) == 0 {
		exitWithMessage("Database does not have any tables")
	}

	dbClient = client
}

func initOptions() {
	_, err := flags.ParseArgs(&options, os.Args)

	if err != nil {
		os.Exit(1)
	}

	if options.Url == "" {
		options.Url = os.Getenv("DATABASE_URL")
	}

	if options.Version {
		fmt.Printf("pgweb v%s\n", VERSION)
		os.Exit(0)
	}
}

func startServer() {
	router := gin.Default()

	router.GET("/", API_Home)
	router.GET("/databases", API_GetDatabases)
	router.GET("/info", API_Info)
	router.GET("/tables", API_GetTables)
	router.GET("/tables/:table", API_GetTable)
	router.GET("/tables/:table/info", API_GetTableInfo)
	router.GET("/tables/:table/indexes", API_TableIndexes)
	router.GET("/query", API_RunQuery)
	router.POST("/query", API_RunQuery)
	router.GET("/explain", API_ExplainQuery)
	router.POST("/explain", API_ExplainQuery)
	router.GET("/history", API_History)
	router.GET("/static/:type/:name", API_ServeAsset)

	fmt.Println("Starting server...")
	go router.Run(fmt.Sprintf(":%v", options.HttpPort))
}

func handleSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	<-c
}

func openPage() {
	url := fmt.Sprintf("http://localhost:%v", options.HttpPort)
	fmt.Println("To view database open", url, "in browser")

	_, err := exec.Command("which", "open").Output()
	if err != nil {
		return
	}

	exec.Command("open", url).Output()
}

func main() {
	initOptions()
	initClient()

	defer dbClient.db.Close()

	if !options.Debug {
		gin.SetMode("release")
	}

	startServer()
	openPage()
	handleSignals()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/zmj/sfslack/log"

	"os"

	"github.com/zmj/sfslack/server"
)

func main() {
	cfg := server.Config{}
	flag.StringVar(&cfg.Host, "host", "", "Public host address")
	flag.IntVar(&cfg.Port, "port", 8080, "Listen Port")
	flag.StringVar(&cfg.SfOAuthID, "sfoauthid", "", "ShareFile OAuth Client ID")
	flag.StringVar(&cfg.SfOAuthSecret, "sfoauthsecret", "", "ShareFile OAuth Client Secret")
	flag.StringVar(&cfg.SlackVerificationToken, "slackverifytoken", "", "Slack command verification token")
	flag.Parse()
	// validate before open log, not in server

	logfile, err := os.Open("log")
	if err != nil {
		err = fmt.Errorf("Failed to open log file\n%v", err)
		fmt.Println(err.Error)
		return
	}
	srv, err := server.NewServer(cfg, log.New(logfile, true))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	err = srv.ListenAndServe()
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
<commit_msg>create log file if not exists<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/zmj/sfslack/log"

	"os"

	"github.com/zmj/sfslack/server"
)

func main() {
	cfg := server.Config{}
	flag.StringVar(&cfg.Host, "host", "", "Public host address")
	flag.IntVar(&cfg.Port, "port", 8080, "Listen Port")
	flag.StringVar(&cfg.SfOAuthID, "sfoauthid", "", "ShareFile OAuth Client ID")
	flag.StringVar(&cfg.SfOAuthSecret, "sfoauthsecret", "", "ShareFile OAuth Client Secret")
	flag.StringVar(&cfg.SlackVerificationToken, "slackverifytoken", "", "Slack command verification token")
	flag.Parse()
	// validate before open log, not in server

	logfile, err := os.Open("log.txt") // from args?
	if err != nil {
		logfile, err = os.Create("log.txt")
		if err != nil {
			err = fmt.Errorf("Failed to open log file\n%v", err)
			fmt.Println(err.Error)
			return
		}
	}
	srv, err := server.NewServer(cfg, log.New(logfile, true))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	err = srv.ListenAndServe()
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016, RadiantBlue Technologies, Inc.

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/binary"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"
	"github.com/venicegeo/pzsvc-sdk-go/s3"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

// LasHeader is the LAS header.
type LasHeader struct {
	FileSignature                [4]byte
	FileSourceID                 uint16
	GlobalEncoding               uint16
	GUID1                        uint32
	GUID2                        uint16
	GUID3                        uint16
	GUID4                        [8]uint8
	VersionMajor, VersionMinor   uint8
	SystemIdentifier             [32]byte
	GeneratingSoftware           [32]byte
	FileCreationDayOfYear        uint16
	FileCreationYear             uint16
	HeaderSize                   uint16
	OffsetToPointData            uint32
	NumberOfVLRs                 uint32
	PointDataRecordFormat        uint8
	PointDataRecordLength        uint16
	LegacyNumberOfPointRecords   uint32
	LegacyNumberOfPointsByReturn [5]uint32
	XScale, YScale, ZScale       float64
	XOffset, YOffset, ZOffset    float64
	MaxX, MinX                   float64
	MaxY, MinY                   float64
	MaxZ, MinZ                   float64
	// missing some waveform packet stuff for 1.4
}

// Format0 is Point Data Record Format 0.
type Format0 struct {
	X, Y, Z        int32
	Intensity      uint16
	Foo            byte
	Classification uint8
	ScanAngleRank  byte
	UserData       uint8
	PointSourceID  uint16
}

// Format1 is Point Data Record Format 1.
type Format1 struct {
	Format0
	GPSTime float64
}

// Format3 is Point Date Record Format 3.
type Format3 struct {
	Format1
	Red, Blue, Green uint16
}

// ReadLas reads an LAS file.
func ReadLas(fname string) (h LasHeader, p []Format1) {
	f, err := os.Open(fname)
	check(err)
	defer f.Close()

	binary.Read(f, binary.LittleEndian, &h)
	fmt.Printf("%+v\n", h)

	f.Seek(int64(h.OffsetToPointData), 0)
	if h.PointDataRecordFormat == 0 {
		fmt.Println("format = 0")
		points := make([]Format0, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, points)
		fmt.Printf("%+v\n", points[:5])
		fmt.Printf("%+v\n", points[len(points)-5:])
	} else if h.PointDataRecordFormat == 1 {
		fmt.Println("format = 1")
		p = make([]Format1, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, p)
		fmt.Printf("%+v\n", p[:5])
		fmt.Printf("%+v\n", p[len(p)-5:])
	} else if h.PointDataRecordFormat == 3 {
		fmt.Println("format = 3")
		points := make([]Format3, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, points)
		fmt.Printf("%+v\n", points[:5])
		fmt.Printf("%+v\n", points[len(points)-5:])
	}
	return
}

func main() {
	router := httprouter.New()

	router.GET("/", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
		fmt.Fprintf(w, "Hi!")
	})

	router.GET("/info", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var inputName string
		var fileIn *os.File

		// Split the source S3 key string, interpreting the last element as the
		// input filename. Create the input file, throwing 500 on error.
		inputName = s3.ParseFilenameFromKey("pointcloud/samp11-utm.las")
		fileIn, err := os.Create(inputName)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		defer fileIn.Close()

		// Download the source data from S3, throwing 500 on error.
		err = s3.Download(fileIn, "venicegeo-sample-data", "pointcloud/samp11-utm.las")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

		h, _ := ReadLas(inputName)

		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(h); err != nil {
			log.Fatal(err)
		}
	})

	var defaultPort = os.Getenv("PORT")
	if defaultPort == "" {
		defaultPort = "8080"
	}

	log.Println("Starting on ", defaultPort)
	if err := http.ListenAndServe(":"+defaultPort, router); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Return error from ReadLas<commit_after>/*
Copyright 2016, RadiantBlue Technologies, Inc.

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/binary"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"
	"github.com/venicegeo/pzsvc-sdk-go/s3"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

// LasHeader is the LAS header.
type LasHeader struct {
	FileSignature                [4]byte
	FileSourceID                 uint16
	GlobalEncoding               uint16
	GUID1                        uint32
	GUID2                        uint16
	GUID3                        uint16
	GUID4                        [8]uint8
	VersionMajor, VersionMinor   uint8
	SystemIdentifier             [32]byte
	GeneratingSoftware           [32]byte
	FileCreationDayOfYear        uint16
	FileCreationYear             uint16
	HeaderSize                   uint16
	OffsetToPointData            uint32
	NumberOfVLRs                 uint32
	PointDataRecordFormat        uint8
	PointDataRecordLength        uint16
	LegacyNumberOfPointRecords   uint32
	LegacyNumberOfPointsByReturn [5]uint32
	XScale, YScale, ZScale       float64
	XOffset, YOffset, ZOffset    float64
	MaxX, MinX                   float64
	MaxY, MinY                   float64
	MaxZ, MinZ                   float64
	// missing some waveform packet stuff for 1.4
}

// Format0 is Point Data Record Format 0.
type Format0 struct {
	X, Y, Z        int32
	Intensity      uint16
	Foo            byte
	Classification uint8
	ScanAngleRank  byte
	UserData       uint8
	PointSourceID  uint16
}

// Format1 is Point Data Record Format 1.
type Format1 struct {
	Format0
	GPSTime float64
}

// Format3 is Point Date Record Format 3.
type Format3 struct {
	Format1
	Red, Blue, Green uint16
}

// ReadLas reads an LAS file.
func ReadLas(fname string) (h LasHeader, p []Format1, err error) {
	f, err := os.Open(fname)
	if err != nil {
		return h, p, err
	}
	defer f.Close()

	binary.Read(f, binary.LittleEndian, &h)
	fmt.Printf("%+v\n", h)

	f.Seek(int64(h.OffsetToPointData), 0)
	if h.PointDataRecordFormat == 0 {
		fmt.Println("format = 0")
		points := make([]Format0, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, points)
		fmt.Printf("%+v\n", points[:5])
		fmt.Printf("%+v\n", points[len(points)-5:])
	} else if h.PointDataRecordFormat == 1 {
		fmt.Println("format = 1")
		p = make([]Format1, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, p)
		fmt.Printf("%+v\n", p[:5])
		fmt.Printf("%+v\n", p[len(p)-5:])
	} else if h.PointDataRecordFormat == 3 {
		fmt.Println("format = 3")
		points := make([]Format3, h.LegacyNumberOfPointRecords)
		binary.Read(f, binary.LittleEndian, points)
		fmt.Printf("%+v\n", points[:5])
		fmt.Printf("%+v\n", points[len(points)-5:])
	}
	return h, p, nil
}

func main() {
	router := httprouter.New()

	router.GET("/", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
		fmt.Fprintf(w, "Hi!")
	})

	router.GET("/info", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var inputName string
		var fileIn *os.File

		// Split the source S3 key string, interpreting the last element as the
		// input filename. Create the input file, throwing 500 on error.
		inputName = s3.ParseFilenameFromKey("pointcloud/samp11-utm.las")
		fileIn, err := os.Create(inputName)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		defer fileIn.Close()

		// Download the source data from S3, throwing 500 on error.
		err = s3.Download(fileIn, "venicegeo-sample-data", "pointcloud/samp11-utm.las")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

		h, _, err := ReadLas(inputName)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(h); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	})

	var defaultPort = os.Getenv("PORT")
	if defaultPort == "" {
		defaultPort = "8080"
	}

	log.Println("Starting on ", defaultPort)
	if err := http.ListenAndServe(":"+defaultPort, router); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/alienth/fastlyctl/util"
	"github.com/alienth/go-fastly"
	"github.com/urfave/cli"
	"gopkg.in/mcuadros/go-syslog.v2"

	_ "expvar"
	_ "net/http/pprof"
)

var client *fastly.Client
var ipLists IPLists
var hook hookService
var noop bool

var syslogChannel syslog.LogPartsChannel

// How many syslog logs we want to buffer, at max.
const syslogChannelBufferSize = 3000

// How many log reading workers we fire up
const workers = 1

// TODO pass this along in context to the webserver instead of
// making it global.
var hits = hitMap{m: make(map[string]*ipRate)}

func main() {
	app := cli.NewApp()
	app.Name = "fastly-ratelimit"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "config, c",
			Usage: "Read config `FILE`.",
			Value: "config.toml",
		},
		cli.StringFlag{
			Name:  "listen, l",
			Usage: "Specify listen `ADDRESS:PORT`.",
			Value: "0.0.0.0:514",
		},
		cli.StringFlag{
			Name:   "fastly-key, K",
			Usage:  "Fastly API Key. Can be read from 'fastly_key' file in CWD.",
			EnvVar: "FASTLY_KEY",
			Value:  util.GetFastlyKey(),
		},
		cli.BoolFlag{
			Name:  "noop, n",
			Usage: "Noop mode. Print what we'd do, but don't actually do anything.",
		},
	}
	app.Before = func(c *cli.Context) error {
		if len(c.Args()) > 0 {
			return cli.NewExitError("Invalid usage. More arguments received than expected.", -1)
		}
		return nil
	}
	app.Action = runServer

	app.Run(os.Args)
}

func runServer(c *cli.Context) error {
	http.HandleFunc("/", handler)
	go http.ListenAndServe(":80", nil)
	client = fastly.NewClient(nil, c.GlobalString("fastly-key"))
	syslogChannel = make(syslog.LogPartsChannel, syslogChannelBufferSize)
	handler := syslog.NewChannelHandler(syslogChannel)

	noop = c.GlobalBool("noop")

	config, err := readConfig(c.GlobalString("config"))
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Error reading config file:\n%s\n", err), -1)
	}
	ipLists = config.Lists
	hook = config.HookService
	hook.hookedIPs.m = make(map[string]bool)

	serviceDomains, err := getServiceDomains()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Error fetching fasty domains:\n%s\n", err), -1)
	}

	if err := hits.importIPRates(serviceDomains); err != nil {
		return cli.NewExitError(fmt.Sprintf("Error importing existing IP rates: %s", err), -1)
	}
	go hits.expireRecords()
	go hits.expireLimits()
	go queueFanout()
	if hook.SyncIPsUri != "" {
		go hits.syncIPsWithHook()
	}

	server := syslog.NewServer()
	server.SetFormat(syslog.RFC3164)
	server.SetHandler(handler)
	if err := server.ListenUDP(c.GlobalString("listen")); err != nil {
		return cli.NewExitError(fmt.Sprintf("Unable to listen: %s\n", err), -1)
	}
	if err := server.Boot(); err != nil {
		return cli.NewExitError(fmt.Sprintf("Unable to start server: %s\n", err), -1)
	}

	for i := 1; i <= workers; i++ {
		go readLogs(syslogChannel, serviceDomains)
	}

	server.Wait()

	return nil
}

func readLogs(channel syslog.LogPartsChannel, serviceDomains ServiceDomains) {
	for logParts := range channel {
		var line string
		var ok bool
		if line, ok = logParts["content"].(string); !ok || line == "" {
			continue
		}
		log := parseLog(line)
		if log == nil || log.cdnIP == nil || log.clientIP == nil {
			continue
		}
		if time.Now().Sub(log.timestamp) > time.Duration(2)*time.Minute {
			fmt.Printf("Warning: old log line. Log TS: %s, Current time: %s\n", log.timestamp.String(), time.Now().String())
		}
		var ipr *ipRate
		var found bool
		ts := time.Now()
		hits.Lock()
		if d := ts.Sub(time.Now()); d > time.Duration(1)*time.Second {
			fmt.Printf("Blocked for %d seconds waiting for hits lock\n", int(d.Seconds()))
		}
		if ipr, found = hits.m[log.cdnIP.String()]; !found {
			ipr = ipLists.getRate(log.cdnIP)
			hits.m[log.cdnIP.String()] = ipr
		}
		hits.Unlock()
		service, err := serviceDomains.getServiceByHost(log.host.Value)
		if err != nil {
			fmt.Printf("Error while finding fastly service for domain %s: %s\n.", log.host.Value, err)
		}
		if service == nil {
			fmt.Printf("Found request for host %s which is not in fastly. Ignoring\n", log.host.Value)
			continue
		}
		dimension := ipr.list.getDimension(log, service)
		overLimit := ipr.Hit(log.timestamp, dimension)
		if overLimit {
			if err := ipr.Limit(service); err != nil {
				fmt.Printf("Error limiting IP: %s\n", err)
			}
		}

		if len(channel) == syslogChannelBufferSize {
			fmt.Println("Warning: log buffer full. We are dropping logs.")
		}
	}

}
<commit_msg>Remove TODO.<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/alienth/fastlyctl/util"
	"github.com/alienth/go-fastly"
	"github.com/urfave/cli"
	"gopkg.in/mcuadros/go-syslog.v2"

	_ "expvar"
	_ "net/http/pprof"
)

var client *fastly.Client
var ipLists IPLists
var hook hookService
var noop bool

var syslogChannel syslog.LogPartsChannel

// How many syslog logs we want to buffer, at max.
const syslogChannelBufferSize = 3000

// How many log reading workers we fire up
const workers = 1

var hits = hitMap{m: make(map[string]*ipRate)}

func main() {
	app := cli.NewApp()
	app.Name = "fastly-ratelimit"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "config, c",
			Usage: "Read config `FILE`.",
			Value: "config.toml",
		},
		cli.StringFlag{
			Name:  "listen, l",
			Usage: "Specify listen `ADDRESS:PORT`.",
			Value: "0.0.0.0:514",
		},
		cli.StringFlag{
			Name:   "fastly-key, K",
			Usage:  "Fastly API Key. Can be read from 'fastly_key' file in CWD.",
			EnvVar: "FASTLY_KEY",
			Value:  util.GetFastlyKey(),
		},
		cli.BoolFlag{
			Name:  "noop, n",
			Usage: "Noop mode. Print what we'd do, but don't actually do anything.",
		},
	}
	app.Before = func(c *cli.Context) error {
		if len(c.Args()) > 0 {
			return cli.NewExitError("Invalid usage. More arguments received than expected.", -1)
		}
		return nil
	}
	app.Action = runServer

	app.Run(os.Args)
}

func runServer(c *cli.Context) error {
	http.HandleFunc("/", handler)
	go http.ListenAndServe(":80", nil)
	client = fastly.NewClient(nil, c.GlobalString("fastly-key"))
	syslogChannel = make(syslog.LogPartsChannel, syslogChannelBufferSize)
	handler := syslog.NewChannelHandler(syslogChannel)

	noop = c.GlobalBool("noop")

	config, err := readConfig(c.GlobalString("config"))
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Error reading config file:\n%s\n", err), -1)
	}
	ipLists = config.Lists
	hook = config.HookService
	hook.hookedIPs.m = make(map[string]bool)

	serviceDomains, err := getServiceDomains()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Error fetching fasty domains:\n%s\n", err), -1)
	}

	if err := hits.importIPRates(serviceDomains); err != nil {
		return cli.NewExitError(fmt.Sprintf("Error importing existing IP rates: %s", err), -1)
	}
	go hits.expireRecords()
	go hits.expireLimits()
	go queueFanout()
	if hook.SyncIPsUri != "" {
		go hits.syncIPsWithHook()
	}

	server := syslog.NewServer()
	server.SetFormat(syslog.RFC3164)
	server.SetHandler(handler)
	if err := server.ListenUDP(c.GlobalString("listen")); err != nil {
		return cli.NewExitError(fmt.Sprintf("Unable to listen: %s\n", err), -1)
	}
	if err := server.Boot(); err != nil {
		return cli.NewExitError(fmt.Sprintf("Unable to start server: %s\n", err), -1)
	}

	for i := 1; i <= workers; i++ {
		go readLogs(syslogChannel, serviceDomains)
	}

	server.Wait()

	return nil
}

func readLogs(channel syslog.LogPartsChannel, serviceDomains ServiceDomains) {
	for logParts := range channel {
		var line string
		var ok bool
		if line, ok = logParts["content"].(string); !ok || line == "" {
			continue
		}
		log := parseLog(line)
		if log == nil || log.cdnIP == nil || log.clientIP == nil {
			continue
		}
		if time.Now().Sub(log.timestamp) > time.Duration(2)*time.Minute {
			fmt.Printf("Warning: old log line. Log TS: %s, Current time: %s\n", log.timestamp.String(), time.Now().String())
		}
		var ipr *ipRate
		var found bool
		ts := time.Now()
		hits.Lock()
		if d := ts.Sub(time.Now()); d > time.Duration(1)*time.Second {
			fmt.Printf("Blocked for %d seconds waiting for hits lock\n", int(d.Seconds()))
		}
		if ipr, found = hits.m[log.cdnIP.String()]; !found {
			ipr = ipLists.getRate(log.cdnIP)
			hits.m[log.cdnIP.String()] = ipr
		}
		hits.Unlock()
		service, err := serviceDomains.getServiceByHost(log.host.Value)
		if err != nil {
			fmt.Printf("Error while finding fastly service for domain %s: %s\n.", log.host.Value, err)
		}
		if service == nil {
			fmt.Printf("Found request for host %s which is not in fastly. Ignoring\n", log.host.Value)
			continue
		}
		dimension := ipr.list.getDimension(log, service)
		overLimit := ipr.Hit(log.timestamp, dimension)
		if overLimit {
			if err := ipr.Limit(service); err != nil {
				fmt.Printf("Error limiting IP: %s\n", err)
			}
		}

		if len(channel) == syslogChannelBufferSize {
			fmt.Println("Warning: log buffer full. We are dropping logs.")
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"syscall"

	"github.com/jaxxstorm/ploop-flexvol/volume"
	"github.com/jaxxstorm/flexvolume"
	"github.com/kolyshkin/goploop-cli"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "ploop flexvolume"
	app.Usage = "Mount ploop volumes in kubernetes using the flexvolume driver"
	app.Commands = flexvolume.Commands(Ploop{})
	app.Authors = []cli.Author{
		cli.Author{
			Name: "Lee Briggs",
		},
	}
	app.Version = "0.1a"
	app.Run(os.Args)
}

type Ploop struct{}

func (p Ploop) Init() flexvolume.Response {
	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Ploop is available",
	}
}

func (p Ploop) Attach(options map[string]string) flexvolume.Response {

	if options["volumePath"] == "" {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Must specify a volume path",
		}
	}

	if options["volumeId"] == "" {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Must specify a volume id",
		}
	}

	if _, err := os.Stat(options["volumePath"] + "/" + options["volumeId"] + "/" + "DiskDescriptor.xml"); err == nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Volume already exists",
			Device:  options["volumePath"] + "/" + options["volumeId"],
		}
	}

	if err := volume.Create(options); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
		}
	}

	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully attached the ploop volume",
		Device:  options["volumePath"] + "/" + options["volumeId"] + "/" + options["volumeId"],
	}
}

func (p Ploop) Detach(device string) flexvolume.Response {

	if err := ploop.UmountByDevice(device); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to detach ploop volume",
			Device:  device,
		}
	}
	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully detached the ploop volume",
		Device:  device,
	}
}

func (p Ploop) Mount(target, device string, options map[string]string) flexvolume.Response {
	// make the target directory we're going to mount to
	err := os.MkdirAll(target, 0755)
	if err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
			Device:  device,
		}
	}

	// open the disk descriptor first
	volume, err := ploop.Open(options["volumePath"] + "/" + options["volumeId"] + "/" + "DiskDescriptor.xml")
	if err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
			Device:  device,
		}
	}
	defer volume.Close()

	if m, _ := volume.IsMounted(); !m {
		// If it's mounted, let's mount it!

		readonly := false
		if options["kubernetes.io/readwrite"] == "ro" {
			readonly = true
		}

		mp := ploop.MountParam{Target: target, Readonly: readonly}

		dev, err := volume.Mount(&mp)
		if err != nil {
			return flexvolume.Response{
				Status:  flexvolume.StatusFailure,
				Message: err.Error(),
				Device:  dev,
			}
		}

		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Successfully mounted the ploop volume",
			Device:  device,
		}
	} else {

		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Ploop volume already mounted",
			Device:  device,
		}

	}
}

func (p Ploop) Unmount(mount string) flexvolume.Response {

	if err := syscall.Unmount(mount, 0x2); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to unmount ploop volume from pod",
			Device:  mount,
		}
	}

	if err := os.Remove(mount); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to remove stale directory from pod",
			Device:  mount,
		}
	}

	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully unmounted the ploop volume",
		Device:  mount,
	}
}
<commit_msg>go fmt<commit_after>package main

import (
	"os"
	"syscall"

	"github.com/jaxxstorm/flexvolume"
	"github.com/jaxxstorm/ploop-flexvol/volume"
	"github.com/kolyshkin/goploop-cli"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "ploop flexvolume"
	app.Usage = "Mount ploop volumes in kubernetes using the flexvolume driver"
	app.Commands = flexvolume.Commands(Ploop{})
	app.Authors = []cli.Author{
		cli.Author{
			Name: "Lee Briggs",
		},
	}
	app.Version = "0.1a"
	app.Run(os.Args)
}

type Ploop struct{}

func (p Ploop) Init() flexvolume.Response {
	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Ploop is available",
	}
}

func (p Ploop) Attach(options map[string]string) flexvolume.Response {

	if options["volumePath"] == "" {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Must specify a volume path",
		}
	}

	if options["volumeId"] == "" {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Must specify a volume id",
		}
	}

	if _, err := os.Stat(options["volumePath"] + "/" + options["volumeId"] + "/" + "DiskDescriptor.xml"); err == nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Volume already exists",
			Device:  options["volumePath"] + "/" + options["volumeId"],
		}
	}

	if err := volume.Create(options); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
		}
	}

	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully attached the ploop volume",
		Device:  options["volumePath"] + "/" + options["volumeId"] + "/" + options["volumeId"],
	}
}

func (p Ploop) Detach(device string) flexvolume.Response {

	if err := ploop.UmountByDevice(device); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to detach ploop volume",
			Device:  device,
		}
	}
	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully detached the ploop volume",
		Device:  device,
	}
}

func (p Ploop) Mount(target, device string, options map[string]string) flexvolume.Response {
	// make the target directory we're going to mount to
	err := os.MkdirAll(target, 0755)
	if err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
			Device:  device,
		}
	}

	// open the disk descriptor first
	volume, err := ploop.Open(options["volumePath"] + "/" + options["volumeId"] + "/" + "DiskDescriptor.xml")
	if err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: err.Error(),
			Device:  device,
		}
	}
	defer volume.Close()

	if m, _ := volume.IsMounted(); !m {
		// If it's mounted, let's mount it!

		readonly := false
		if options["kubernetes.io/readwrite"] == "ro" {
			readonly = true
		}

		mp := ploop.MountParam{Target: target, Readonly: readonly}

		dev, err := volume.Mount(&mp)
		if err != nil {
			return flexvolume.Response{
				Status:  flexvolume.StatusFailure,
				Message: err.Error(),
				Device:  dev,
			}
		}

		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Successfully mounted the ploop volume",
			Device:  device,
		}
	} else {

		return flexvolume.Response{
			Status:  flexvolume.StatusSuccess,
			Message: "Ploop volume already mounted",
			Device:  device,
		}

	}
}

func (p Ploop) Unmount(mount string) flexvolume.Response {

	if err := syscall.Unmount(mount, 0x2); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to unmount ploop volume from pod",
			Device:  mount,
		}
	}

	if err := os.Remove(mount); err != nil {
		return flexvolume.Response{
			Status:  flexvolume.StatusFailure,
			Message: "Unable to remove stale directory from pod",
			Device:  mount,
		}
	}

	return flexvolume.Response{
		Status:  flexvolume.StatusSuccess,
		Message: "Successfully unmounted the ploop volume",
		Device:  mount,
	}
}
<|endoftext|>