<commit_before>package main

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

const defaultBufferSize = 1024

func readAndDiscard(c net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte
		_, err := c.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}
	}
}

func forward(from net.Conn, to net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte

		n, err := from.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}

		_, err = to.Write(b[:n])
		if err != nil {
			errCh <- err
			return
		}
	}
}

func forwardAndCopy(from net.Conn, to net.Conn, mirrors []net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte

		n, err := from.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}

		_, err = to.Write(b[:n])
		if err != nil {
			errCh <- err
			return
		}

		for i := 0; i < len(mirrors); i++ {
			_, err = mirrors[i].Write(b[:n])
			if err != nil {
				errCh <- err
				return
			}
		}
	}
}

func connect(origin net.Conn, forwarder net.Conn, mirrors []net.Conn, errCh chan error) {

	for i := 0; i < len(mirrors); i++ {
		go readAndDiscard(mirrors[i], errCh)
	}

	go forward(forwarder, origin, errCh)
	go forwardAndCopy(origin, forwarder, mirrors, errCh)
}

type mirrorList []string

func (l *mirrorList) String() string {
	return fmt.Sprint(*l)
}

func (l *mirrorList) Set(value string) error {
	for _, m := range strings.Split(value, ",") {
		*l = append(*l, m)
	}
	return nil
}

func main() {

	var (
		listenAddress   string
		forwardAddress  string
		mirrorAddresses mirrorList
	)

	flag.StringVar(&listenAddress, "l", "", "listen address (e.g. 'localhost:8080')")
	flag.StringVar(&forwardAddress, "f", "", "forward to address (e.g. 'localhost:8081')")
	flag.Var(&mirrorAddresses, "m", "comma separated list of mirror addresses (e.g. 'localhost:8082,localhost:8083')")
	flag.Parse()

	if listenAddress == "" || forwardAddress == "" || len(mirrorAddresses) == 0 {
		flag.Usage()
		return
	}

	l, err := net.Listen("tcp", listenAddress)
	if err != nil {
		log.Fatalf("error while listening: %s", err)
	}

	connNo := uint64(1)

	for {
		c, err := l.Accept()
		if err != nil {
			log.Fatalf("Error while accepting: %s", err)
		}

		log.Printf("accepted connection %d (%s <-> %s)", connNo, c.RemoteAddr(), c.LocalAddr())

		go func(c net.Conn) {

			cF, err := net.Dial("tcp", forwardAddress)
			if err != nil {
				log.Fatalf("error while connecting to forwarder: %s", err)
			}

			mirrorConns := make([]net.Conn, 0)

			for _, addr := range mirrorAddresses {
				c, err := net.Dial("tcp", addr)
				if err != nil {
					log.Fatalf("error while connecting to mirror %s: %s", addr, err)
				}
				mirrorConns = append(mirrorConns, c)
			}

			errCh := make(chan error, 1024)

			connect(c, cF, mirrorConns, errCh)

			err = <-errCh

			log.Printf("got error: %s", err)

			c.Close()
			cF.Close()

			for _, c := range mirrorConns {
				c.Close()
			}
		}(c)

		connNo += 1
	}
}
<commit_msg>initial (buggy) splice/tee implementation<commit_after>package main

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

	"golang.org/x/sys/unix"
)

const defaultBufferSize = 1024

func readAndDiscard(c net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte
		_, err := c.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}
	}
}

func forwardSplice(from net.Conn, to net.Conn, errCh chan error) {
	var (
		p       [2]int
		nullPtr *int64
	)

	err := unix.Pipe(p[:])
	if err != nil {
		log.Fatalf("pipe() error: %s", err)
	}

	fromFile, err := from.(*net.TCPConn).File()
	if err != nil {
		log.Fatalf("error while creating File() from incoming connection: %s", err)
	}

	toFile, err := to.(*net.TCPConn).File()
	if err != nil {
		log.Fatalf("error while creating File() from outgoing connection: %s", err)
	}

	for {
		_, err = unix.Splice(int(fromFile.Fd()), nullPtr, p[1], nullPtr, 1024, 0)
		if err != nil {
			log.Fatalf("error while splicing from conn to pipe: %s", err)
		}

		_, err = unix.Splice(p[0], nullPtr, int(toFile.Fd()), nullPtr, 1024, 0)
		if err != nil {
			log.Fatalf("error while splicing from pipe to conn: %s", err)
		}
	}
}

func forward(from net.Conn, to net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte

		n, err := from.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}

		_, err = to.Write(b[:n])
		if err != nil {
			errCh <- err
			return
		}
	}
}

func forwardAndCopyZeroCopy(from net.Conn, to net.Conn, mirrors []net.Conn, errCh chan error) {
	var (
		p           [2]int
		nullPtr     *int64
		mirrorFiles []*os.File
	)

	err := unix.Pipe(p[:])
	if err != nil {
		log.Fatalf("pipe() error: %s", err)
	}

	fromFile, err := from.(*net.TCPConn).File()
	if err != nil {
		log.Fatalf("error while creating File() from incoming connection: %s", err)
	}

	toFile, err := to.(*net.TCPConn).File()
	if err != nil {
		log.Fatalf("error while creating File() from outgoing connection: %s", err)
	}

	for _, m := range mirrors {
		mFile, err := m.(*net.TCPConn).File()
		if err != nil {
			log.Fatalf("error while creating File() from incoming connection: %s", err)
		}
		mirrorFiles = append(mirrorFiles, mFile)
	}

	go func() { // splice data from conn to pipe
		for {
			_, err = unix.Splice(int(fromFile.Fd()), nullPtr, p[1], nullPtr, 1024, 0)
			if err != nil {
				log.Fatalf("error while splicing from conn to pipe: %s", err)
			}
		}
	}()

	for {
		nteed, err := unix.Tee(p[0], int(mirrorFiles[0].Fd()), 1024, 0)
		if err != nil {
			log.Fatalf("error while tee(): %s", err)
		}

		_, err = unix.Splice(p[0], nullPtr, int(toFile.Fd()), nullPtr, int(nteed), 0)
		if err != nil {
			log.Fatalf("error while splice(): %s", err)
		}
	}

}

func forwardAndCopy(from net.Conn, to net.Conn, mirrors []net.Conn, errCh chan error) {
	for {
		var b [defaultBufferSize]byte

		n, err := from.Read(b[:])
		if err != nil {
			errCh <- err
			return
		}

		_, err = to.Write(b[:n])
		if err != nil {
			errCh <- err
			return
		}

		for i := 0; i < len(mirrors); i++ {
			_, err = mirrors[i].Write(b[:n])
			if err != nil {
				errCh <- err
				return
			}
		}
	}
}

func connect(origin net.Conn, forwarder net.Conn, mirrors []net.Conn, errCh chan error) {

	for i := 0; i < len(mirrors); i++ {
		go readAndDiscard(mirrors[i], errCh)
	}

	go forwardSplice(forwarder, origin, errCh)
	go forwardAndCopy(origin, forwarder, mirrors, errCh)
}

type mirrorList []string

func (l *mirrorList) String() string {
	return fmt.Sprint(*l)
}

func (l *mirrorList) Set(value string) error {
	for _, m := range strings.Split(value, ",") {
		*l = append(*l, m)
	}
	return nil
}

func main() {

	var (
		listenAddress   string
		forwardAddress  string
		mirrorAddresses mirrorList
	)

	flag.StringVar(&listenAddress, "l", "", "listen address (e.g. 'localhost:8080')")
	flag.StringVar(&forwardAddress, "f", "", "forward to address (e.g. 'localhost:8081')")
	flag.Var(&mirrorAddresses, "m", "comma separated list of mirror addresses (e.g. 'localhost:8082,localhost:8083')")
	flag.Parse()

	if listenAddress == "" || forwardAddress == "" || len(mirrorAddresses) == 0 {
		flag.Usage()
		return
	}

	l, err := net.Listen("tcp", listenAddress)
	if err != nil {
		log.Fatalf("error while listening: %s", err)
	}

	connNo := uint64(1)

	for {
		c, err := l.Accept()
		if err != nil {
			log.Fatalf("Error while accepting: %s", err)
		}

		log.Printf("accepted connection %d (%s <-> %s)", connNo, c.RemoteAddr(), c.LocalAddr())

		go func(c net.Conn) {

			cF, err := net.Dial("tcp", forwardAddress)
			if err != nil {
				log.Fatalf("error while connecting to forwarder: %s", err)
			}

			mirrorConns := make([]net.Conn, 0)

			for _, addr := range mirrorAddresses {
				c, err := net.Dial("tcp", addr)
				if err != nil {
					log.Fatalf("error while connecting to mirror %s: %s", addr, err)
				}
				mirrorConns = append(mirrorConns, c)
			}

			errCh := make(chan error, 1024)

			connect(c, cF, mirrorConns, errCh)

			err = <-errCh

			log.Printf("got error: %s", err)

			c.Close()
			cF.Close()

			for _, c := range mirrorConns {
				c.Close()
			}
		}(c)

		connNo += 1
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"net/http"
	"os"
	"time"
)

const Version = "4.2.4"

var options struct {
	http            string
	pinNumber       int
	statusPinNumber int
	cert            string
	key             string
	version         bool
}

var sharedSecret = os.Getenv("GARAGE_SECRET")

func logHandler(event string) {
	fmt.Fprintln(os.Stdout, event, "-", time.Now())
}

func verifySignature(signedText []byte, signature []byte) bool {
	mac := hmac.New(sha512.New, []byte(sharedSecret))
	mac.Write(signedText)
	expectedMAC := []byte(hex.EncodeToString(mac.Sum(nil)))
	return hmac.Equal(signature, expectedMAC)
}

func verifyTime(timestamp int64) (int64, error) {
	timeSinceRequest := time.Now().Unix() - timestamp
	if timeSinceRequest > 10 {
		return -1, errors.New("Timestamp is too far in the past")
	}
	return timestamp, nil
}

func toggleSwitch(pinNumber int) (err error) {
	err = rpio.Open()
	if err != nil {
		return err
	}
	pin := rpio.Pin(pinNumber)
	pin.Output()

	pin.Low()
	rpio.Close()

	time.Sleep(100 * time.Millisecond)

	err = rpio.Open()
	if err != nil {
		return err
	}
	pin.High()
	rpio.Close()

	return nil
}

type ClientRequest struct {
	Timestamp int64 `json:"timestamp"`
}

func CheckStatus(pinNumber int) (state string, err error) {
	err = rpio.Open()
	if err != nil {
		return
	}
	defer rpio.Close()

	pin := rpio.Pin(pinNumber)

	status := "open"
	if pin.Read() == 0 {
		status = "closed"
	}

	return status, err
}

func DoorStatus(w http.ResponseWriter, r *http.Request) {
	var jsonResp struct {
		Text string `json:"door_status"`
	}

	status, err := CheckStatus(options.statusPinNumber)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		w.WriteHeader(422)
		jsonResp.Text = fmt.Sprintf("%s", err)
	}

	jsonResp.Text = status
	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func GetVersion(w http.ResponseWriter, r *http.Request) {
	logHandler("Version")
	var jsonResp struct {
		Text string `json:"version"`
	}
	jsonResp.Text = Version
	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func Relay(w http.ResponseWriter, r *http.Request) {
	header := r.Header.Get("signature")
	signature, err := base64.URLEncoding.DecodeString(header)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	buf.ReadFrom(r.Body)
	body := buf.Bytes()

	var jsonResp struct {
		Text string `json:"status"`
	}
	jsonResp.Text = "signal received"

	verified := verifySignature(body, signature)
	if verified {
		// Verify time
		var clientRequest ClientRequest
		err := json.Unmarshal([]byte(body), &clientRequest)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}

		_, err = verifyTime(clientRequest.Timestamp)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}

		// Toggle switch
		logHandler("TOGGLE DOOR")
		err = toggleSwitch(options.pinNumber)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			w.WriteHeader(422)
			jsonResp.Text = fmt.Sprintf("%s", err)
		}
	} else {
		w.WriteHeader(401)
		logHandler(fmt.Sprintf("Invalid signature: %s", signature))
		jsonResp.Text = fmt.Sprintf("%s", "Invalid signature")
	}

	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func main() {
	if os.Args[1] == "update" {
		CheckForUpdates()
		os.Exit(0)
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage:  %s [options]\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.IntVar(&options.pinNumber, "pin", 25, "GPIO pin of relay")
	flag.IntVar(&options.statusPinNumber, "status-pin", 10, "GPIO pin of reed switch")
	flag.StringVar(&options.http, "http", "", "HTTP listen address (e.g. 127.0.0.1:8225)")
	flag.StringVar(&options.cert, "cert", "", "SSL certificate path (e.g. /ssl/example.com.cert)")
	flag.StringVar(&options.key, "key", "", "SSL certificate key (e.g. /ssl/example.com.key)")
	flag.BoolVar(&options.version, "version", false, "print version and exit")
	flag.Parse()

	if options.version {
		fmt.Printf("garage-server v%v\n", Version)
		os.Exit(0)
	}

	if sharedSecret == "" {
		println("You did not set GARAGE_SECRET env var")
		os.Exit(1)
	}

	serveAddress := "127.0.0.1:8225"
	if options.http != "" {
		serveAddress = options.http
	}

	http.HandleFunc("/", Relay)
	http.HandleFunc("/status", DoorStatus)
	http.HandleFunc("/version", GetVersion)

	fmt.Fprintln(os.Stderr, "=> Booting Garage Server ", Version)
	fmt.Fprintln(os.Stderr, "=> Run `garage-server -h` for more startup options")
	fmt.Fprintln(os.Stderr, "=> Ctrl-C to shutdown server")

	var err error
	if options.key != "" && options.cert != "" {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on https://%s", serveAddress))
		err = http.ListenAndServeTLS(serveAddress, options.cert, options.key, nil)
	} else {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on http://%s", serveAddress))
		err = http.ListenAndServe(serveAddress, nil)
	}

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Bump to version 4.3.0<commit_after>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"net/http"
	"os"
	"time"
)

const Version = "4.3.0"

var options struct {
	http            string
	pinNumber       int
	statusPinNumber int
	cert            string
	key             string
	version         bool
}

var sharedSecret = os.Getenv("GARAGE_SECRET")

func logHandler(event string) {
	fmt.Fprintln(os.Stdout, event, "-", time.Now())
}

func verifySignature(signedText []byte, signature []byte) bool {
	mac := hmac.New(sha512.New, []byte(sharedSecret))
	mac.Write(signedText)
	expectedMAC := []byte(hex.EncodeToString(mac.Sum(nil)))
	return hmac.Equal(signature, expectedMAC)
}

func verifyTime(timestamp int64) (int64, error) {
	timeSinceRequest := time.Now().Unix() - timestamp
	if timeSinceRequest > 10 {
		return -1, errors.New("Timestamp is too far in the past")
	}
	return timestamp, nil
}

func toggleSwitch(pinNumber int) (err error) {
	err = rpio.Open()
	if err != nil {
		return err
	}
	pin := rpio.Pin(pinNumber)
	pin.Output()

	pin.Low()
	rpio.Close()

	time.Sleep(100 * time.Millisecond)

	err = rpio.Open()
	if err != nil {
		return err
	}
	pin.High()
	rpio.Close()

	return nil
}

type ClientRequest struct {
	Timestamp int64 `json:"timestamp"`
}

func CheckStatus(pinNumber int) (state string, err error) {
	err = rpio.Open()
	if err != nil {
		return
	}
	defer rpio.Close()

	pin := rpio.Pin(pinNumber)

	status := "open"
	if pin.Read() == 0 {
		status = "closed"
	}

	return status, err
}

func DoorStatus(w http.ResponseWriter, r *http.Request) {
	var jsonResp struct {
		Text string `json:"door_status"`
	}

	status, err := CheckStatus(options.statusPinNumber)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		w.WriteHeader(422)
		jsonResp.Text = fmt.Sprintf("%s", err)
	}

	jsonResp.Text = status
	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func GetVersion(w http.ResponseWriter, r *http.Request) {
	logHandler("Version")
	var jsonResp struct {
		Text string `json:"version"`
	}
	jsonResp.Text = Version
	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func Relay(w http.ResponseWriter, r *http.Request) {
	header := r.Header.Get("signature")
	signature, err := base64.URLEncoding.DecodeString(header)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	buf.ReadFrom(r.Body)
	body := buf.Bytes()

	var jsonResp struct {
		Text string `json:"status"`
	}
	jsonResp.Text = "signal received"

	verified := verifySignature(body, signature)
	if verified {
		// Verify time
		var clientRequest ClientRequest
		err := json.Unmarshal([]byte(body), &clientRequest)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}

		_, err = verifyTime(clientRequest.Timestamp)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}

		// Toggle switch
		logHandler("TOGGLE DOOR")
		err = toggleSwitch(options.pinNumber)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			w.WriteHeader(422)
			jsonResp.Text = fmt.Sprintf("%s", err)
		}
	} else {
		w.WriteHeader(401)
		logHandler(fmt.Sprintf("Invalid signature: %s", signature))
		jsonResp.Text = fmt.Sprintf("%s", "Invalid signature")
	}

	message, err := json.Marshal(jsonResp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	w.Write(message)
}

func main() {
	if os.Args[1] == "update" {
		CheckForUpdates()
		os.Exit(0)
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage:  %s [options]\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.IntVar(&options.pinNumber, "pin", 25, "GPIO pin of relay")
	flag.IntVar(&options.statusPinNumber, "status-pin", 10, "GPIO pin of reed switch")
	flag.StringVar(&options.http, "http", "", "HTTP listen address (e.g. 127.0.0.1:8225)")
	flag.StringVar(&options.cert, "cert", "", "SSL certificate path (e.g. /ssl/example.com.cert)")
	flag.StringVar(&options.key, "key", "", "SSL certificate key (e.g. /ssl/example.com.key)")
	flag.BoolVar(&options.version, "version", false, "print version and exit")
	flag.Parse()

	if options.version {
		fmt.Printf("garage-server v%v\n", Version)
		os.Exit(0)
	}

	if sharedSecret == "" {
		println("You did not set GARAGE_SECRET env var")
		os.Exit(1)
	}

	serveAddress := "127.0.0.1:8225"
	if options.http != "" {
		serveAddress = options.http
	}

	http.HandleFunc("/", Relay)
	http.HandleFunc("/status", DoorStatus)
	http.HandleFunc("/version", GetVersion)

	fmt.Fprintln(os.Stderr, "=> Booting Garage Server ", Version)
	fmt.Fprintln(os.Stderr, "=> Run `garage-server -h` for more startup options")
	fmt.Fprintln(os.Stderr, "=> Ctrl-C to shutdown server")

	var err error
	if options.key != "" && options.cert != "" {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on https://%s", serveAddress))
		err = http.ListenAndServeTLS(serveAddress, options.cert, options.key, nil)
	} else {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on http://%s", serveAddress))
		err = http.ListenAndServe(serveAddress, nil)
	}

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
  "io"
  "os"
	"fmt"
  "os/exec"
  "github.com/drone/drone-go/drone"
  "github.com/drone/drone-go/plugin"
  "strings"
)

type CloudFoundry struct {
  Api string `json:"api"`
  User string `json:"user"`
  Password string `json:"password"`
  Org string `json:"org"`
  Space string `json:"space"`
}

func main() {
  repo := drone.Repo{}
  build := drone.Build{}
  workspace := drone.Workspace{}
  vargs := CloudFoundry{}

  plugin.Param("repo", &repo)
  plugin.Param("build", &build)
  plugin.Param("workspace", &workspace)
  plugin.Param("vargs", &vargs)
  plugin.Parse()

  if vargs.Api == "" || vargs.User == "" || vargs.Password == "" {
    fmt.Fprintln(os.Stderr, "required")
    os.Exit(1)
  }
  fmt.Println(vargs)
  var cmd *exec.Cmd
  cmd = login(vargs)
  run(*cmd)

  cmd = exec.Command("cf", "push")
  fmt.Println(strings.Join(cmd.Args, " "))
  run(*cmd)

}
func run(cmd exec.Cmd) error {
  stdout, _ := cmd.StdoutPipe()
  stderr, _ := cmd.StderrPipe()

  cmd.Start()

  go io.Copy(os.Stdout, stdout)
  go io.Copy(os.Stderr, stderr)
  return cmd.Wait()
}
func login(vargs CloudFoundry) *exec.Cmd {
  return exec.Command("cf", "login", "-a", vargs.Api, "-u", vargs.User, "-p", vargs.Password)
}
<commit_msg>Don't output vargs<commit_after>package main

import (
  "io"
  "os"
	"fmt"
  "os/exec"
  "github.com/drone/drone-go/drone"
  "github.com/drone/drone-go/plugin"
  "strings"
)

type CloudFoundry struct {
  Api string `json:"api"`
  User string `json:"user"`
  Password string `json:"password"`
  Org string `json:"org"`
  Space string `json:"space"`
}

func main() {
  repo := drone.Repo{}
  build := drone.Build{}
  workspace := drone.Workspace{}
  vargs := CloudFoundry{}

  plugin.Param("repo", &repo)
  plugin.Param("build", &build)
  plugin.Param("workspace", &workspace)
  plugin.Param("vargs", &vargs)
  plugin.Parse()

  if vargs.Api == "" || vargs.User == "" || vargs.Password == "" {
    fmt.Fprintln(os.Stderr, "required")
    os.Exit(1)
  }
  var cmd *exec.Cmd

  // login
  cmd = login(vargs)
  run(*cmd)

  // cf push
  cmd = exec.Command("cf", "push")
  fmt.Println(strings.Join(cmd.Args, " "))
  run(*cmd)
}
func run(cmd exec.Cmd) error {
  stdout, _ := cmd.StdoutPipe()
  stderr, _ := cmd.StderrPipe()

  cmd.Start()

  go io.Copy(os.Stdout, stdout)
  go io.Copy(os.Stderr, stderr)
  return cmd.Wait()
}
func login(vargs CloudFoundry) *exec.Cmd {
  return exec.Command("cf", "login", "-a", vargs.Api, "-u", vargs.User, "-p", vargs.Password)
}
<|endoftext|>


<commit_before>package request

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type RequestMethod string

const (
	GET     RequestMethod = "GET"
	HEAD                  = "HEAD"
	PUT                   = "PUT"
	POST                  = "POST"
	OPTIONS               = "OPTIONS"
)

type Request struct {
	url     string
	headers map[string]string
	body    bytes.Buffer
	method  RequestMethod
}

func New(url string) *Request {

	r := &Request{
		url: url,
	}

	return r
}

func (r *Request) Method(method RequestMethod) *Request {

	r.method = method

	return r
}

func (r *Request) Get(url string) *Request {

	return &Request{
		url:    url,
		method: GET,
	}
}

func (r *Request) Put(url string) *Request {

	return &Request{
		url:    url,
		method: PUT,
	}
}

func (r *Request) Head(url string) *Request {

	return &Request{
		url:    url,
		method: HEAD,
	}
}

func (r *Request) Options(url string) *Request {

	return &Request{
		url:    url,
		method: OPTIONS,
	}
}

func (r *Request) Post(url string) *Request {

	return &Request{
		url:    url,
		method: POST,
	}
}

func (r *Request) Header(key string, value string) *Request {

	r.headers[key] = value

	return r
}

func (r *Request) Headers(h map[string]string) *Request {
	r.headers = h

	return r
}

func (r *Request) Do() ([]byte, error) {

	if r.method == "" {
		r.method = GET
	}

	cli := &http.Client{}
	req, err := http.NewRequest(r.method.string(), r.url, nil)
	if err != nil {
		return nil, err
	}

	res, err := cli.Do(req)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func (r *Request) Map(i interface{}) error {

	resp, err := r.Do()
	if err != nil {
		return err
	}

	err = json.Unmarshal(resp, &i)

	return err
}

func (m RequestMethod) string() string {
	switch m {
	case HEAD:
		return "HEAD"
	case PUT:
		return "PUT"
	case POST:
		return "POST"
	case OPTIONS:
		return "OPTIONS"
	}

	return "GET"
}
<commit_msg>fix what i just broke<commit_after>package request

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type RequestMethod string

const (
	GET     RequestMethod = "GET"
	HEAD                  = "HEAD"
	PUT                   = "PUT"
	POST                  = "POST"
	OPTIONS               = "OPTIONS"
)

type Request struct {
	url     string
	headers map[string]string
	body    bytes.Buffer
	method  RequestMethod
}

func New(url string) *Request {

	r := &Request{
		url: url,
	}

	return r
}

func (r *Request) Method(method RequestMethod) *Request {

	r.method = method

	return r
}

func Get(url string) *Request {

	return &Request{
		url:    url,
		method: GET,
	}
}

func Put(url string) *Request {

	return &Request{
		url:    url,
		method: PUT,
	}
}

func Head(url string) *Request {

	return &Request{
		url:    url,
		method: HEAD,
	}
}

func Options(url string) *Request {

	return &Request{
		url:    url,
		method: OPTIONS,
	}
}

func Post(url string) *Request {

	return &Request{
		url:    url,
		method: POST,
	}
}

func (r *Request) Header(key string, value string) *Request {

	r.headers[key] = value

	return r
}

func (r *Request) Headers(h map[string]string) *Request {
	r.headers = h

	return r
}

func (r *Request) Do() ([]byte, error) {

	if r.method == "" {
		r.method = GET
	}

	cli := &http.Client{}
	req, err := http.NewRequest(r.method.string(), r.url, nil)
	if err != nil {
		return nil, err
	}

	res, err := cli.Do(req)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func (r *Request) Map(i interface{}) error {

	resp, err := r.Do()
	if err != nil {
		return err
	}

	err = json.Unmarshal(resp, &i)

	return err
}

func (m RequestMethod) string() string {
	switch m {
	case HEAD:
		return "HEAD"
	case PUT:
		return "PUT"
	case POST:
		return "POST"
	case OPTIONS:
		return "OPTIONS"
	}

	return "GET"
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	_ "github.com/go-sql-driver/mysql"
	"github.com/tedsuo/ifrit"

	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/config"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/database"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/enforcer"
	"github.com/pivotal-golang/lager"
)

type Config struct {
	Host         string
	Port         int
	User         string
	Password     string
	BrokerDBName string
}

func main() {
	flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	runOnce := flags.Bool("runOnce", false, "Run only once instead of continuously")
	configFile := flags.String("configFile", "", "Location of config file")
	cf_lager.AddFlags(flags)
	flags.Parse(os.Args[1:])
	logger, _ := cf_lager.New("Quota Enforcer")

	logger.Info("Config file", lager.Data{"configFile": configFile})
	config, err := config.Load(*configFile)
	if err != nil {
		panic(err.Error())
	}

	brokerDBName := config.DBName
	if brokerDBName == "" {
		logger.Fatal("Must specify DBName in the config file", nil)
	}

	db, err := database.NewConnection(*config)
	if db != nil {
		defer db.Close()
	}

	if err != nil {
		panic(err.Error())
	}

	logger.Info(
		"Database connection established.",
		lager.Data{
			"Host":         config.Host,
			"Port":         config.Port,
			"User":         config.User,
			"DatabaseName": brokerDBName,
		})

	violatorRepo := database.NewViolatorRepo(brokerDBName, db, logger)
	reformerRepo := database.NewReformerRepo(brokerDBName, db, logger)

	e := enforcer.NewEnforcer(violatorRepo, reformerRepo, logger)
	r := enforcer.NewRunner(e, logger)

	if *runOnce {
		logger.Info("Running once")

		err := e.EnforceOnce()
		if err != nil {
			logger.Info(fmt.Sprintf("Quota Enforcing Failed: %s", err.Error()))
		}
	} else {
		process := ifrit.Invoke(r)
		logger.Info("Running continuously")

		err := <-process.Wait()
		if err != nil {
			logger.Fatal("Quota Enforcing Failed", err)
		}
	}
}

func enforce(e enforcer.Enforcer, logger lager.Logger) {
	logger.Info("Enforcing")
	err := e.EnforceOnce()
	if err != nil {
		logger.Info(fmt.Sprintf("Enforcing Failed: %s", err.Error()))
	}
}
<commit_msg>Replace panic with logger.Fatal.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	_ "github.com/go-sql-driver/mysql"
	"github.com/tedsuo/ifrit"

	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/config"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/database"
	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/enforcer"
	"github.com/pivotal-golang/lager"
)

type Config struct {
	Host         string
	Port         int
	User         string
	Password     string
	BrokerDBName string
}

func main() {
	flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	runOnce := flags.Bool("runOnce", false, "Run only once instead of continuously")
	configFile := flags.String("configFile", "", "Location of config file")
	cf_lager.AddFlags(flags)
	flags.Parse(os.Args[1:])
	logger, _ := cf_lager.New("Quota Enforcer")

	logger.Info("Config file", lager.Data{"configFile": configFile})
	config, err := config.Load(*configFile)
	if err != nil {
		logger.Fatal("Failed to load config file", err)
	}

	brokerDBName := config.DBName
	if brokerDBName == "" {
		logger.Fatal("Must specify DBName in the config file", nil)
	}

	db, err := database.NewConnection(*config)
	if db != nil {
		defer db.Close()
	}

	if err != nil {
		logger.Fatal("Failed to open database connection", err)
	}

	logger.Info(
		"Database connection established.",
		lager.Data{
			"Host":         config.Host,
			"Port":         config.Port,
			"User":         config.User,
			"DatabaseName": brokerDBName,
		})

	violatorRepo := database.NewViolatorRepo(brokerDBName, db, logger)
	reformerRepo := database.NewReformerRepo(brokerDBName, db, logger)

	e := enforcer.NewEnforcer(violatorRepo, reformerRepo, logger)
	r := enforcer.NewRunner(e, logger)

	if *runOnce {
		logger.Info("Running once")

		err := e.EnforceOnce()
		if err != nil {
			logger.Info(fmt.Sprintf("Quota Enforcing Failed: %s", err.Error()))
		}
	} else {
		process := ifrit.Invoke(r)
		logger.Info("Running continuously")

		err := <-process.Wait()
		if err != nil {
			logger.Fatal("Quota Enforcing Failed", err)
		}
	}
}

func enforce(e enforcer.Enforcer, logger lager.Logger) {
	logger.Info("Enforcing")
	err := e.EnforceOnce()
	if err != nil {
		logger.Info(fmt.Sprintf("Enforcing Failed: %s", err.Error()))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"appengine"
	"appengine/user"
	"github.com/gorilla/sessions"
	"github.com/icco/natnatnat/handlers"
	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
	"html/template"
	"net/http"
	"time"
)

var store *sessions.CookieStore

func HstsMiddleware(w traffic.ResponseWriter, r *traffic.Request) {
	w.Header().Add("Strict-Transport-Security", "max-age=15768000")
}

func IsAdmin(c appengine.Context) bool {
	return c != nil && user.IsAdmin(c)
}

func fmtTime(t time.Time) string {
	const layout = "03:04 on Jan 2, 2006"
	return t.Format(layout)
}

func markdown(args ...interface{}) template.HTML {
	return models.Markdown(args...)
}

// init is one of those magic functions that runs once on project create.
func init() {
	if !appengine.IsDevAppServer() {
		traffic.SetVar("env", "production")
	}

	traffic.TemplateFunc("fmttime", fmtTime)
	traffic.TemplateFunc("mrkdwn", markdown)

	router := traffic.New()
	router.Get("/", handlers.RootHandler)
	router.Get("/about", handlers.AboutHandler)
	router.Get("/archive", handlers.UnimplementedHandler)
	router.Get("/stats", handlers.UnimplementedHandler)

	router.Get("/post/new/?", handlers.NewPostGetHandler)
	router.Post("/post/new/?", handlers.NewPostPostHandler)

	router.Get("/post/:id/?", handlers.PostHandler)

	router.Get("/edit/:id/?", handlers.EditPostGetHandler)
	router.Post("/edit/:id/?", handlers.EditPostPostHandler)

	router.Get("/settings", handlers.SettingsGetHandler)
	router.Post("/settings", handlers.SettingsPostHandler)

	router.Get("/mention", handlers.WebMentionGetHandler)
	router.Post("/mention", handlers.WebMentionPostHandler)

	router.Get("/feed.atom", handlers.FeedAtomHandler)
	router.Get("/feed.rss", handlers.FeedRssHandler)

	router.AddBeforeFilter(HstsMiddleware)
	router.Use(NewStaticMiddleware(traffic.PublicPath()))

	http.Handle("/", router)
}

// Entry point for go server.
func main() {}
<commit_msg>plural<commit_after>package main

import (
	"appengine"
	"appengine/user"
	"github.com/gorilla/sessions"
	"github.com/icco/natnatnat/handlers"
	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
	"html/template"
	"net/http"
	"time"
)

var store *sessions.CookieStore

func HstsMiddleware(w traffic.ResponseWriter, r *traffic.Request) {
	w.Header().Add("Strict-Transport-Security", "max-age=15768000")
}

func IsAdmin(c appengine.Context) bool {
	return c != nil && user.IsAdmin(c)
}

func fmtTime(t time.Time) string {
	const layout = "03:04 on Jan 2, 2006"
	return t.Format(layout)
}

func markdown(args ...interface{}) template.HTML {
	return models.Markdown(args...)
}

// init is one of those magic functions that runs once on project create.
func init() {
	if !appengine.IsDevAppServer() {
		traffic.SetVar("env", "production")
	}

	traffic.TemplateFunc("fmttime", fmtTime)
	traffic.TemplateFunc("mrkdwn", markdown)

	router := traffic.New()
	router.Get("/", handlers.RootHandler)
	router.Get("/about", handlers.AboutHandler)
	router.Get("/archives", handlers.UnimplementedHandler)
	router.Get("/stats", handlers.UnimplementedHandler)

	router.Get("/post/new/?", handlers.NewPostGetHandler)
	router.Post("/post/new/?", handlers.NewPostPostHandler)

	router.Get("/post/:id/?", handlers.PostHandler)

	router.Get("/edit/:id/?", handlers.EditPostGetHandler)
	router.Post("/edit/:id/?", handlers.EditPostPostHandler)

	router.Get("/settings", handlers.SettingsGetHandler)
	router.Post("/settings", handlers.SettingsPostHandler)

	router.Get("/mention", handlers.WebMentionGetHandler)
	router.Post("/mention", handlers.WebMentionPostHandler)

	router.Get("/feed.atom", handlers.FeedAtomHandler)
	router.Get("/feed.rss", handlers.FeedRssHandler)

	router.AddBeforeFilter(HstsMiddleware)
	router.Use(NewStaticMiddleware(traffic.PublicPath()))

	http.Handle("/", router)
}

// Entry point for go server.
func main() {}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/* TODO: We have a problem with file dependencies. What if the header is
 * removed and shows up again?
 */

package main

import (
	"flag"
	"log"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"os"
	"os/signal"
	"sync"
)

func main() {
	// path to symbols DB
	var dbDir string
	flag.StringVar(&dbDir, "db", ".navc_dbsymbols", "Path to symbols DB dir")

	// number of parallel indexing threads
	var nIndexingThreads int
	flag.IntVar(&nIndexingThreads, "numThreads", 1,
		"Number of indexing threads (don't use)")

	// reset DB
	var resetDb bool
	flag.BoolVar(&resetDb, "resetDb", false,
		"Reset symbols DB and start over")

	flag.Parse()

	// socket file for communication with daemon
	socketFile := "/tmp/navc.sock"

	// list of directores with source to index
	var indexDir []string
	if len(flag.Args()) > 0 {
		indexDir = flag.Args()
		for _, path := range indexDir {
			fi, err := os.Stat(path)
			if err != nil {
				log.Println("unable to access ", path, err)
				return
			}
			if !fi.IsDir() {
				log.Println("only dir inputs allowed")
				return
			}
		}
	} else {
		indexDir = []string{"."}
	}

	// handle interrup and kill signals
	intr := make(chan os.Signal, 1)
	signal.Notify(intr, os.Interrupt, os.Kill)
	defer close(intr)

	var wg sync.WaitGroup
	defer wg.Wait()

	// if we need to reset the database, erase the old one
	if resetDb {
		os.RemoveAll(dbDir)
	}

	// open databased of symbols
	db := NewSymbolsDB(dbDir)

	// start files handler
	StartFilesHandler(indexDir, nIndexingThreads, db)
	defer CloseFilesHandler()

	// start serving requests
	os.Remove(socketFile)
	lis, err := net.Listen("unix", socketFile)
	if err != nil {
		log.Println("error opening socket", err)
		return
	}
	defer os.Remove(socketFile)
	defer lis.Close()

	handler := rpc.NewServer()
	handler.Register(&RequestHandler{db})
	go func() {
		wg.Add(1)
		defer wg.Done()

		for {
			conn, err := lis.Accept()
			if err != nil {
				log.Println("accepting connection (breaking):",
					err)
				return
			}

			codec := jsonrpc.NewServerCodec(conn)
			err = handler.ServeRequest(codec)
			if err != nil {
				log.Println("handling request (ignoring):", err)
			}
			codec.Close()
		}
	}()

	// wait until ctl-c is pressed
	select {
	case <-intr:
	}
}
<commit_msg>Multithreading should be on be default now<commit_after>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/* TODO: We have a problem with file dependencies. What if the header is
 * removed and shows up again?
 */

package main

import (
	"flag"
	"log"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"os"
	"os/signal"
	"runtime"
	"sync"
)

func main() {
	// path to symbols DB
	var dbDir string
	flag.StringVar(&dbDir, "db", ".navc_dbsymbols", "Path to symbols DB dir")

	// number of parallel indexing threads
	var nIndexingThreads int
	flag.IntVar(&nIndexingThreads, "numThreads", runtime.NumCPU(),
		"Number of indexing threads")

	// reset DB
	var resetDB bool
	flag.BoolVar(&resetDB, "resetDB", false,
		"Reset symbols DB and start over")

	flag.Parse()

	// socket file for communication with daemon
	socketFile := "/tmp/navc.sock"

	// list of directores with source to index
	var indexDir []string
	if len(flag.Args()) > 0 {
		indexDir = flag.Args()
		for _, path := range indexDir {
			fi, err := os.Stat(path)
			if err != nil {
				log.Println("unable to access ", path, err)
				return
			}
			if !fi.IsDir() {
				log.Println("only dir inputs allowed")
				return
			}
		}
	} else {
		indexDir = []string{"."}
	}

	// handle interrup and kill signals
	intr := make(chan os.Signal, 1)
	signal.Notify(intr, os.Interrupt, os.Kill)
	defer close(intr)

	var wg sync.WaitGroup
	defer wg.Wait()

	// if we need to reset the database, erase the old one
	if resetDB {
		os.RemoveAll(dbDir)
	}

	// open databased of symbols
	db := NewSymbolsDB(dbDir)

	// start files handler
	StartFilesHandler(indexDir, nIndexingThreads, db)
	defer CloseFilesHandler()

	// start serving requests
	os.Remove(socketFile)
	lis, err := net.Listen("unix", socketFile)
	if err != nil {
		log.Println("error opening socket", err)
		return
	}
	defer os.Remove(socketFile)
	defer lis.Close()

	handler := rpc.NewServer()
	handler.Register(&RequestHandler{db})
	go func() {
		wg.Add(1)
		defer wg.Done()

		for {
			conn, err := lis.Accept()
			if err != nil {
				log.Println("accepting connection (breaking):",
					err)
				return
			}

			codec := jsonrpc.NewServerCodec(conn)
			err = handler.ServeRequest(codec)
			if err != nil {
				log.Println("handling request (ignoring):", err)
			}
			codec.Close()
		}
	}()

	// wait until ctl-c is pressed
	select {
	case <-intr:
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"net"
	"net/http"
	"os"
	"runtime"
	"time"

	"github.com/Sirupsen/logrus"
	metrics_graphite "github.com/cyberdelia/go-metrics-graphite"

	"github.com/resourced/resourced/agent"
	_ "github.com/resourced/resourced/readers/docker"
	_ "github.com/resourced/resourced/readers/haproxy"
	_ "github.com/resourced/resourced/readers/mcrouter"
	_ "github.com/resourced/resourced/readers/memcache"
	_ "github.com/resourced/resourced/readers/mysql"
	_ "github.com/resourced/resourced/readers/procfs"
	_ "github.com/resourced/resourced/readers/redis"
	_ "github.com/resourced/resourced/readers/varnish"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

// main runs the web server for resourced.
func main() {
	configDir := os.Getenv("RESOURCED_CONFIG_DIR")
	if configDir == "" {
		err := errors.New("RESOURCED_CONFIG_DIR is required")
		logrus.Fatal(err)
	}

	a, err := agent.New()
	if err != nil {
		logrus.Fatal(err)
	}

	logLevel, err := logrus.ParseLevel(a.GeneralConfig.LogLevel)
	if err == nil {
		logrus.SetLevel(logLevel)
	}

	a.RunAllForever()

	// Graphite Settings
	graphiteListener, err := a.NewTCPServer(a.GeneralConfig.Graphite, "Graphite TCP")
	if err != nil {
		logrus.Fatal(err)
	}
	if graphiteListener != nil {
		defer graphiteListener.Close()

		go func(graphiteListener net.Listener) {
			for {
				conn, err := graphiteListener.Accept()
				if err == nil {
					go a.HandleGraphite(conn)
				}
			}
		}(graphiteListener)
	}

	// LogReceiver TCP Settings
	logReceiverListener, err := a.NewTCPServer(a.GeneralConfig.LogReceiver, "Log Receiver TCP")
	if err != nil {
		logrus.Fatal(err)
	}
	if logReceiverListener != nil {
		defer logReceiverListener.Close()

		go func(logReceiverListener net.Listener) {
			for {
				conn, err := logReceiverListener.Accept()
				if err == nil {
					go a.HandleLog(conn)
				}
			}
		}(logReceiverListener)
	}

	// Publish metrics to self graphite endpoint.
	addr, err := net.ResolveTCPAddr("tcp", a.GeneralConfig.Graphite.GetAddr())
	if err != nil {
		logrus.Fatal(err)
	}
	statsInterval, err := time.ParseDuration(a.GeneralConfig.Graphite.StatsInterval)
	if err != nil {
		logrus.Fatal(err)
	}
	go metrics_graphite.Graphite(a.NewMetricsRegistry(), statsInterval, "resourced_agent", addr)

	// HTTP Settings
	logFields := logrus.Fields{
		"Addr":                a.GeneralConfig.Addr,
		"LogLevel":            a.GeneralConfig.LogLevel,
		"ResourcedMaster.URL": a.GeneralConfig.ResourcedMaster.URL,
	}

	if a.GeneralConfig.HTTPS.CertFile != "" && a.GeneralConfig.HTTPS.KeyFile != "" {
		logFields["HTTPS.CertFile"] = a.GeneralConfig.HTTPS.CertFile
		logFields["HTTPS.KeyFile"] = a.GeneralConfig.HTTPS.KeyFile

		logrus.WithFields(logFields).Info("Running HTTPS server")

		err = http.ListenAndServeTLS(a.GeneralConfig.Addr, a.GeneralConfig.HTTPS.CertFile, a.GeneralConfig.HTTPS.KeyFile, a.HttpRouter())

	} else {
		logrus.WithFields(logFields).Info("Running HTTP server")

		err = http.ListenAndServe(a.GeneralConfig.Addr, a.HttpRouter())
	}

	if err != nil {
		logrus.Fatal(err)
	}
}
<commit_msg>go naming convention<commit_after>package main

import (
	"errors"
	"net"
	"net/http"
	"os"
	"runtime"
	"time"

	"github.com/Sirupsen/logrus"
	metrics_graphite "github.com/cyberdelia/go-metrics-graphite"

	"github.com/resourced/resourced/agent"
	_ "github.com/resourced/resourced/readers/docker"
	_ "github.com/resourced/resourced/readers/haproxy"
	_ "github.com/resourced/resourced/readers/mcrouter"
	_ "github.com/resourced/resourced/readers/memcache"
	_ "github.com/resourced/resourced/readers/mysql"
	_ "github.com/resourced/resourced/readers/procfs"
	_ "github.com/resourced/resourced/readers/redis"
	_ "github.com/resourced/resourced/readers/varnish"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

// main runs the web server for resourced.
func main() {
	configDir := os.Getenv("RESOURCED_CONFIG_DIR")
	if configDir == "" {
		err := errors.New("RESOURCED_CONFIG_DIR is required")
		logrus.Fatal(err)
	}

	a, err := agent.New()
	if err != nil {
		logrus.Fatal(err)
	}

	logLevel, err := logrus.ParseLevel(a.GeneralConfig.LogLevel)
	if err == nil {
		logrus.SetLevel(logLevel)
	}

	a.RunAllForever()

	// Graphite Settings
	graphiteListener, err := a.NewTCPServer(a.GeneralConfig.Graphite, "Graphite TCP")
	if err != nil {
		logrus.Fatal(err)
	}
	if graphiteListener != nil {
		defer graphiteListener.Close()

		go func(graphiteListener net.Listener) {
			for {
				conn, err := graphiteListener.Accept()
				if err == nil {
					go a.HandleGraphite(conn)
				}
			}
		}(graphiteListener)
	}

	// LogReceiver TCP Settings
	logReceiverListener, err := a.NewTCPServer(a.GeneralConfig.LogReceiver, "Log Receiver TCP")
	if err != nil {
		logrus.Fatal(err)
	}
	if logReceiverListener != nil {
		defer logReceiverListener.Close()

		go func(logReceiverListener net.Listener) {
			for {
				conn, err := logReceiverListener.Accept()
				if err == nil {
					go a.HandleLog(conn)
				}
			}
		}(logReceiverListener)
	}

	// Publish metrics to self graphite endpoint.
	addr, err := net.ResolveTCPAddr("tcp", a.GeneralConfig.Graphite.GetAddr())
	if err != nil {
		logrus.Fatal(err)
	}
	statsInterval, err := time.ParseDuration(a.GeneralConfig.Graphite.StatsInterval)
	if err != nil {
		logrus.Fatal(err)
	}
	go metrics_graphite.Graphite(a.NewMetricsRegistry(), statsInterval, "ResourcedAgent", addr)

	// HTTP Settings
	logFields := logrus.Fields{
		"Addr":                a.GeneralConfig.Addr,
		"LogLevel":            a.GeneralConfig.LogLevel,
		"ResourcedMaster.URL": a.GeneralConfig.ResourcedMaster.URL,
	}

	if a.GeneralConfig.HTTPS.CertFile != "" && a.GeneralConfig.HTTPS.KeyFile != "" {
		logFields["HTTPS.CertFile"] = a.GeneralConfig.HTTPS.CertFile
		logFields["HTTPS.KeyFile"] = a.GeneralConfig.HTTPS.KeyFile

		logrus.WithFields(logFields).Info("Running HTTPS server")

		err = http.ListenAndServeTLS(a.GeneralConfig.Addr, a.GeneralConfig.HTTPS.CertFile, a.GeneralConfig.HTTPS.KeyFile, a.HttpRouter())

	} else {
		logrus.WithFields(logFields).Info("Running HTTP server")

		err = http.ListenAndServe(a.GeneralConfig.Addr, a.HttpRouter())
	}

	if err != nil {
		logrus.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/ghthor/journal/config"
	"log"
	"os"
	"strings"
	"text/template"
)

var commands = []*Command{
	newEntryCmd,
}

func main() {
	configPath := flag.String("config", os.ExpandEnv("$HOME/.journal-config.json"), "a path to the configuration file")
	init := flag.Bool("init", false, "`git init` the journal directory if it doesn't exist")

	flag.Usage = usage
	flag.Parse()

	if c, err := config.ReadFromFile(*configPath); err == nil {
		_, err := os.Stat(c.Directory)
		if os.IsNotExist(err) && *init {
			err := GitInit(c.Directory)
			if err != nil {
				log.Fatal(err)
			}
		} else if err != nil {
			log.Fatal(err)
		}

		if err := os.Chdir(os.ExpandEnv(c.Directory)); err != nil {
			log.Fatal(err)
		}
	} else {
		log.Fatal(err)
	}

	args := flag.Args()
	if len(args) == 0 || args[0] == "-h" {
		flag.Usage()
		return
	}

	var cmd *Command
	name := args[0]
	for _, c := range commands {
		if strings.HasPrefix(c.Name, name) {
			cmd = c
			break
		}
	}

	if cmd == nil {
		fmt.Printf("error: unknown command %q\n", name)
		flag.Usage()
		os.Exit(1)
	}

	cmd.Exec(args[1:])
}

func usage() {
	fmt.Print(usagePrefix)
	flag.PrintDefaults()
	usageTmpl.Execute(os.Stdout, commands)
}

var usagePrefix = `
journal is a filesystem text based journal that stores metadata about each entry

Usage:
    journal [options] <subcommand> [subcommand options]

Options:
`
var usageTmpl = template.Must(template.New("usage").Parse(
	`
Commands:{{range .}}
    {{.Name | printf "%-10s"}} {{.Summary}}{{end}}
`))
<commit_msg>Need to Expand env variables<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/ghthor/journal/config"
	"log"
	"os"
	"strings"
	"text/template"
)

var commands = []*Command{
	newEntryCmd,
}

func main() {
	configPath := flag.String("config", os.ExpandEnv("$HOME/.journal-config.json"), "a path to the configuration file")
	init := flag.Bool("init", false, "`git init` the journal directory if it doesn't exist")

	flag.Usage = usage
	flag.Parse()

	if c, err := config.ReadFromFile(*configPath); err == nil {
		_, err := os.Stat(os.ExpandEnv(c.Directory))
		if os.IsNotExist(err) && *init {
			err := GitInit(c.Directory)
			if err != nil {
				log.Fatal(err)
			}
		} else if err != nil {
			log.Fatal(err)
		}

		if err := os.Chdir(os.ExpandEnv(c.Directory)); err != nil {
			log.Fatal(err)
		}
	} else {
		log.Fatal(err)
	}

	args := flag.Args()
	if len(args) == 0 || args[0] == "-h" {
		flag.Usage()
		return
	}

	var cmd *Command
	name := args[0]
	for _, c := range commands {
		if strings.HasPrefix(c.Name, name) {
			cmd = c
			break
		}
	}

	if cmd == nil {
		fmt.Printf("error: unknown command %q\n", name)
		flag.Usage()
		os.Exit(1)
	}

	cmd.Exec(args[1:])
}

func usage() {
	fmt.Print(usagePrefix)
	flag.PrintDefaults()
	usageTmpl.Execute(os.Stdout, commands)
}

var usagePrefix = `
journal is a filesystem text based journal that stores metadata about each entry

Usage:
    journal [options] <subcommand> [subcommand options]

Options:
`
var usageTmpl = template.Must(template.New("usage").Parse(
	`
Commands:{{range .}}
    {{.Name | printf "%-10s"}} {{.Summary}}{{end}}
`))
<|endoftext|>


<commit_before>// Package main hosts the main function for taskcluter-worker.
//
// The code is structured in 4 kinds of extension registries. The
// commands, config, engines and plugins packages each define interfaces and
// registries where implementations of these interfaces can be registered.
//
// To add a new command to taskcluster-worker you must create new sub-package of
// commands/ which implements and registers commands.CommandProvider with the
// commands.Register(name, provider) method. The same pattern is followed for
// implementation of config transformers, engines, and plugins.
//
// All the sub-packages are then imported here, which ensure that they'll all
// be included in the respective extension registries. Exceptions to this
// pattern is the runtime and worker packages. The runtime package and its
// sub-packages implements generic abstractions and utilities to be used by all
// other packages. The worker package implements task execution flow to be used
// by commands.
package main

import (
	"os"

	"github.com/taskcluster/taskcluster-worker/commands"

	// Import all sub-packages from commands/, config/, engines/ and plugins/
	// as they will register themselves using extension registries.

	_ "github.com/taskcluster/taskcluster-worker/commands/daemon"
	_ "github.com/taskcluster/taskcluster-worker/commands/help"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-build"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-guest-tools"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-run"
	_ "github.com/taskcluster/taskcluster-worker/commands/schema"
	_ "github.com/taskcluster/taskcluster-worker/commands/shell"
	_ "github.com/taskcluster/taskcluster-worker/commands/shell-server"
	_ "github.com/taskcluster/taskcluster-worker/commands/version"
	_ "github.com/taskcluster/taskcluster-worker/commands/work"
	_ "github.com/taskcluster/taskcluster-worker/config/abs"
	_ "github.com/taskcluster/taskcluster-worker/config/configtest"
	_ "github.com/taskcluster/taskcluster-worker/config/env"
	_ "github.com/taskcluster/taskcluster-worker/config/hostcredentials"
	_ "github.com/taskcluster/taskcluster-worker/config/packet"
	_ "github.com/taskcluster/taskcluster-worker/config/secrets"
	_ "github.com/taskcluster/taskcluster-worker/engines/docker"
	_ "github.com/taskcluster/taskcluster-worker/engines/enginetest"
	_ "github.com/taskcluster/taskcluster-worker/engines/mock"
	_ "github.com/taskcluster/taskcluster-worker/engines/native"
	_ "github.com/taskcluster/taskcluster-worker/engines/qemu"
	_ "github.com/taskcluster/taskcluster-worker/engines/script"
	_ "github.com/taskcluster/taskcluster-worker/plugins/artifacts"
	_ "github.com/taskcluster/taskcluster-worker/plugins/cache"
	_ "github.com/taskcluster/taskcluster-worker/plugins/env"
	_ "github.com/taskcluster/taskcluster-worker/plugins/interactive"
	_ "github.com/taskcluster/taskcluster-worker/plugins/livelog"
	_ "github.com/taskcluster/taskcluster-worker/plugins/logprefix"
	_ "github.com/taskcluster/taskcluster-worker/plugins/maxruntime"
	_ "github.com/taskcluster/taskcluster-worker/plugins/plugintest"
	_ "github.com/taskcluster/taskcluster-worker/plugins/reboot"
	_ "github.com/taskcluster/taskcluster-worker/plugins/success"
	_ "github.com/taskcluster/taskcluster-worker/plugins/tcproxy"
	_ "github.com/taskcluster/taskcluster-worker/plugins/watchdog"
)

func main() {
	os.Exit(commands.Run(nil))
}
<commit_msg>Enabled tasklog plugin, forgot to include it in the binary<commit_after>// Package main hosts the main function for taskcluter-worker.
//
// The code is structured in 4 kinds of extension registries. The
// commands, config, engines and plugins packages each define interfaces and
// registries where implementations of these interfaces can be registered.
//
// To add a new command to taskcluster-worker you must create new sub-package of
// commands/ which implements and registers commands.CommandProvider with the
// commands.Register(name, provider) method. The same pattern is followed for
// implementation of config transformers, engines, and plugins.
//
// All the sub-packages are then imported here, which ensure that they'll all
// be included in the respective extension registries. Exceptions to this
// pattern is the runtime and worker packages. The runtime package and its
// sub-packages implements generic abstractions and utilities to be used by all
// other packages. The worker package implements task execution flow to be used
// by commands.
package main

import (
	"os"

	"github.com/taskcluster/taskcluster-worker/commands"

	// Import all sub-packages from commands/, config/, engines/ and plugins/
	// as they will register themselves using extension registries.

	_ "github.com/taskcluster/taskcluster-worker/commands/daemon"
	_ "github.com/taskcluster/taskcluster-worker/commands/help"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-build"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-guest-tools"
	_ "github.com/taskcluster/taskcluster-worker/commands/qemu-run"
	_ "github.com/taskcluster/taskcluster-worker/commands/schema"
	_ "github.com/taskcluster/taskcluster-worker/commands/shell"
	_ "github.com/taskcluster/taskcluster-worker/commands/shell-server"
	_ "github.com/taskcluster/taskcluster-worker/commands/version"
	_ "github.com/taskcluster/taskcluster-worker/commands/work"
	_ "github.com/taskcluster/taskcluster-worker/config/abs"
	_ "github.com/taskcluster/taskcluster-worker/config/configtest"
	_ "github.com/taskcluster/taskcluster-worker/config/env"
	_ "github.com/taskcluster/taskcluster-worker/config/hostcredentials"
	_ "github.com/taskcluster/taskcluster-worker/config/packet"
	_ "github.com/taskcluster/taskcluster-worker/config/secrets"
	_ "github.com/taskcluster/taskcluster-worker/engines/docker"
	_ "github.com/taskcluster/taskcluster-worker/engines/enginetest"
	_ "github.com/taskcluster/taskcluster-worker/engines/mock"
	_ "github.com/taskcluster/taskcluster-worker/engines/native"
	_ "github.com/taskcluster/taskcluster-worker/engines/qemu"
	_ "github.com/taskcluster/taskcluster-worker/engines/script"
	_ "github.com/taskcluster/taskcluster-worker/plugins/artifacts"
	_ "github.com/taskcluster/taskcluster-worker/plugins/cache"
	_ "github.com/taskcluster/taskcluster-worker/plugins/env"
	_ "github.com/taskcluster/taskcluster-worker/plugins/interactive"
	_ "github.com/taskcluster/taskcluster-worker/plugins/livelog"
	_ "github.com/taskcluster/taskcluster-worker/plugins/logprefix"
	_ "github.com/taskcluster/taskcluster-worker/plugins/maxruntime"
	_ "github.com/taskcluster/taskcluster-worker/plugins/plugintest"
	_ "github.com/taskcluster/taskcluster-worker/plugins/reboot"
	_ "github.com/taskcluster/taskcluster-worker/plugins/success"
	_ "github.com/taskcluster/taskcluster-worker/plugins/tasklog"
	_ "github.com/taskcluster/taskcluster-worker/plugins/tcproxy"
	_ "github.com/taskcluster/taskcluster-worker/plugins/watchdog"
)

func main() {
	os.Exit(commands.Run(nil))
}
<|endoftext|>


<commit_before>/*

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

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

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

package main

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

	"github.com/go-logr/zapr"
	opa "github.com/open-policy-agent/frameworks/constraint/pkg/client"
	"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/local"
	"github.com/open-policy-agent/gatekeeper/api"
	configv1alpha1 "github.com/open-policy-agent/gatekeeper/api/v1alpha1"
	"github.com/open-policy-agent/gatekeeper/pkg/audit"
	"github.com/open-policy-agent/gatekeeper/pkg/controller"
	configController "github.com/open-policy-agent/gatekeeper/pkg/controller/config"
	"github.com/open-policy-agent/gatekeeper/pkg/controller/constrainttemplate"
	"github.com/open-policy-agent/gatekeeper/pkg/metrics"
	"github.com/open-policy-agent/gatekeeper/pkg/readiness"
	"github.com/open-policy-agent/gatekeeper/pkg/target"
	"github.com/open-policy-agent/gatekeeper/pkg/upgrade"
	"github.com/open-policy-agent/gatekeeper/pkg/util"
	"github.com/open-policy-agent/gatekeeper/pkg/watch"
	"github.com/open-policy-agent/gatekeeper/pkg/webhook"
	"github.com/open-policy-agent/gatekeeper/third_party/sigs.k8s.io/controller-runtime/pkg/dynamiccache"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	"k8s.io/client-go/rest"
	ctrl "sigs.k8s.io/controller-runtime"
	k8sCli "sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
	"sigs.k8s.io/controller-runtime/pkg/healthz"
	crzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
	// +kubebuilder:scaffold:imports
)

const (
	secretName     = "gatekeeper-webhook-server-cert"
	vwhName        = "gatekeeper-validating-webhook-configuration"
	serviceName    = "gatekeeper-webhook-service"
	caName         = "gatekeeper-ca"
	caOrganization = "gatekeeper"
)

var (
	// DNSName is <service name>.<namespace>.svc
	dnsName    = fmt.Sprintf("%s.%s.svc", serviceName, util.GetNamespace())
	scheme     = runtime.NewScheme()
	setupLog   = ctrl.Log.WithName("setup")
	operations = newOperationSet()
)

var (
	logLevel            = flag.String("log-level", "INFO", "Minimum log level. For example, DEBUG, INFO, WARNING, ERROR. Defaulted to INFO if unspecified.")
	healthAddr          = flag.String("health-addr", ":9090", "The address to which the health endpoint binds.")
	metricsAddr         = flag.String("metrics-addr", "0", "The address the metric endpoint binds to.")
	port                = flag.Int("port", 443, "port for the server. defaulted to 443 if unspecified ")
	certDir             = flag.String("cert-dir", "/certs", "The directory where certs are stored, defaults to /certs")
	disableCertRotation = flag.Bool("disable-cert-rotation", false, "disable automatic generation and rotation of webhook TLS certificates/keys")
)

func init() {
	_ = clientgoscheme.AddToScheme(scheme)

	_ = api.AddToScheme(scheme)

	_ = configv1alpha1.AddToScheme(scheme)
	// +kubebuilder:scaffold:scheme
	flag.Var(operations, "operation", "The operation to be performed by this instance. e.g. audit, webhook. This flag can be declared more than once. Omitting will default to supporting all operations.")
}

type opSet map[string]bool

var _ flag.Value = opSet{}

func newOperationSet() opSet {
	return make(map[string]bool)
}

func (l opSet) String() string {
	contents := make([]string, 0)
	for k := range l {
		contents = append(contents, k)
	}
	return fmt.Sprintf("%s", contents)
}

func (l opSet) Set(s string) error {
	l[s] = true
	return nil
}

func main() {
	flag.Parse()

	switch *logLevel {
	case "DEBUG":
		ctrl.SetLogger(crzap.New(crzap.UseDevMode(true)))
	case "WARNING", "ERROR":
		setLoggerForProduction()
	case "INFO":
		fallthrough
	default:
		ctrl.SetLogger(crzap.New(crzap.UseDevMode(false)))
	}

	// set default if --operation is not provided
	if len(operations) == 0 {
		operations["audit"] = true
		operations["webhook"] = true
	}

	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
		NewCache:               dynamiccache.New,
		Scheme:                 scheme,
		MetricsBindAddress:     *metricsAddr,
		LeaderElection:         false,
		Port:                   *port,
		CertDir:                *certDir,
		HealthProbeBindAddress: *healthAddr,
		MapperProvider: func(c *rest.Config) (meta.RESTMapper, error) {
			return apiutil.NewDynamicRESTMapper(c)
		},
	})
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		os.Exit(1)
	}

	// Make sure certs are generated and valid if cert rotation is enabled.
	setupFinished := make(chan struct{})
	if !*disableCertRotation && operations["webhook"] {
		setupLog.Info("setting up cert rotation")
		if err := webhook.AddRotator(mgr, &webhook.CertRotator{
			SecretKey: types.NamespacedName{
				Namespace: util.GetNamespace(),
				Name:      secretName,
			},
			CertDir:        *certDir,
			CAName:         caName,
			CAOrganization: caOrganization,
			DNSName:        dnsName,
			CertsMounted:   setupFinished,
		}, vwhName); err != nil {
			setupLog.Error(err, "unable to set up cert rotation")
			os.Exit(1)
		}
	} else {
		close(setupFinished)
	}

	// ControllerSwitch will be used to disable controllers during our teardown process,
	// avoiding conflicts in finalizer cleanup.
	sw := watch.NewSwitch()

	// Setup tracker and register readiness probe.
	tracker, err := readiness.SetupTracker(mgr)
	if err != nil {
		setupLog.Error(err, "unable to register readiness tracker")
		os.Exit(1)
	}

	// +kubebuilder:scaffold:builder

	if err := mgr.AddHealthzCheck("default", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to create health check")
		os.Exit(1)
	}
	// Setup controllers asynchronously, they will block for certificate generation if needed.
	go setupControllers(mgr, sw, tracker, setupFinished)

	setupLog.Info("starting manager")
	hadError := false
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		hadError = true
	}

	// Manager stops controllers asynchronously.
	// Instead, we use ControllerSwitch to synchronously prevent them from doing more work.
	// This can be removed when finalizer and status teardown is removed.
	setupLog.Info("disabling controllers...")
	sw.Stop()

	// Create a fresh client to be sure RESTmapper is up-to-date
	setupLog.Info("cleaning state...")
	cli, err := k8sCli.New(mgr.GetConfig(), k8sCli.Options{Scheme: mgr.GetScheme(), Mapper: nil})
	if err != nil {
		setupLog.Error(err, "unable to create cleanup client")
		os.Exit(1)
	}

	// Clean up sync finalizers
	// This logic should be disabled if OPA is run as a sidecar
	syncCleaned := make(chan struct{})
	go configController.TearDownState(cli, syncCleaned)

	// Clean up constraint finalizers
	templatesCleaned := make(chan struct{})
	go constrainttemplate.TearDownState(cli, templatesCleaned)

	<-syncCleaned
	<-templatesCleaned
	setupLog.Info("state cleaned")
	if hadError {
		os.Exit(1)
	}
}

func setupControllers(mgr ctrl.Manager, sw *watch.ControllerSwitch, tracker *readiness.Tracker, setupFinished chan struct{}) {
	// Block until the setup (certificate generation) finishes.
	<-setupFinished

	// initialize OPA
	driver := local.New(local.Tracing(false))
	backend, err := opa.NewBackend(opa.Driver(driver))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA backend")
		os.Exit(1)
	}
	client, err := backend.NewClient(opa.Targets(&target.K8sValidationTarget{}))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA client")
	}

	c := mgr.GetCache()
	dc, ok := c.(watch.RemovableCache)
	if !ok {
		err := fmt.Errorf("expected dynamic cache, got: %T", c)
		setupLog.Error(err, "fetching dynamic cache")
		os.Exit(1)
	}
	wm, err := watch.New(dc)
	if err != nil {
		setupLog.Error(err, "unable to create watch manager")
		os.Exit(1)
	}
	if err := mgr.Add(wm); err != nil {
		setupLog.Error(err, "unable to register watch manager to the manager")
		os.Exit(1)
	}

	// Setup all Controllers
	setupLog.Info("setting up controller")
	opts := controller.Dependencies{
		Opa:              client,
		WatchManger:      wm,
		ControllerSwitch: sw,
		Tracker:          tracker,
	}
	if err := controller.AddToManager(mgr, opts); err != nil {
		setupLog.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

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

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

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

func setLoggerForProduction() {
	sink := zapcore.AddSync(os.Stderr)
	var opts []zap.Option
	encCfg := zap.NewProductionEncoderConfig()
	enc := zapcore.NewJSONEncoder(encCfg)
	lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
	opts = append(opts, zap.AddStacktrace(zap.ErrorLevel),
		zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewSampler(core, time.Second, 100, 100)
		}))
	opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
	zlog := zap.New(zapcore.NewCore(&crzap.KubeAwareEncoder{Encoder: enc, Verbose: false}, sink, lvl))
	zlog = zlog.WithOptions(opts...)
	newlogger := zapr.NewLogger(zlog)
	ctrl.SetLogger(newlogger)
}
<commit_msg>Add ability to set log severity format (#644)<commit_after>/*

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

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

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

package main

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

	"github.com/go-logr/zapr"
	opa "github.com/open-policy-agent/frameworks/constraint/pkg/client"
	"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/local"
	"github.com/open-policy-agent/gatekeeper/api"
	configv1alpha1 "github.com/open-policy-agent/gatekeeper/api/v1alpha1"
	"github.com/open-policy-agent/gatekeeper/pkg/audit"
	"github.com/open-policy-agent/gatekeeper/pkg/controller"
	configController "github.com/open-policy-agent/gatekeeper/pkg/controller/config"
	"github.com/open-policy-agent/gatekeeper/pkg/controller/constrainttemplate"
	"github.com/open-policy-agent/gatekeeper/pkg/metrics"
	"github.com/open-policy-agent/gatekeeper/pkg/readiness"
	"github.com/open-policy-agent/gatekeeper/pkg/target"
	"github.com/open-policy-agent/gatekeeper/pkg/upgrade"
	"github.com/open-policy-agent/gatekeeper/pkg/util"
	"github.com/open-policy-agent/gatekeeper/pkg/watch"
	"github.com/open-policy-agent/gatekeeper/pkg/webhook"
	"github.com/open-policy-agent/gatekeeper/third_party/sigs.k8s.io/controller-runtime/pkg/dynamiccache"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	"k8s.io/client-go/rest"
	ctrl "sigs.k8s.io/controller-runtime"
	k8sCli "sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
	"sigs.k8s.io/controller-runtime/pkg/healthz"
	crzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
	// +kubebuilder:scaffold:imports
)

const (
	secretName     = "gatekeeper-webhook-server-cert"
	vwhName        = "gatekeeper-validating-webhook-configuration"
	serviceName    = "gatekeeper-webhook-service"
	caName         = "gatekeeper-ca"
	caOrganization = "gatekeeper"
)

var (
	// DNSName is <service name>.<namespace>.svc
	dnsName          = fmt.Sprintf("%s.%s.svc", serviceName, util.GetNamespace())
	scheme           = runtime.NewScheme()
	setupLog         = ctrl.Log.WithName("setup")
	operations       = newOperationSet()
	logLevelEncoders = map[string]zapcore.LevelEncoder{
		"lower":        zapcore.LowercaseLevelEncoder,
		"capital":      zapcore.CapitalLevelEncoder,
		"color":        zapcore.LowercaseColorLevelEncoder,
		"capitalcolor": zapcore.CapitalColorLevelEncoder,
	}
)

var (
	logLevel            = flag.String("log-level", "INFO", "Minimum log level. For example, DEBUG, INFO, WARNING, ERROR. Defaulted to INFO if unspecified.")
	logLevelKey         = flag.String("log-level-key", "level", "JSON key for the log level field, defaults to `level`")
	logLevelEncoder     = flag.String("log-level-encoder", "lower", "Encoder for the value of the log level field. Valid values: [`lower`, `capital`, `color`, `capitalcolor`], default: `lower`")
	healthAddr          = flag.String("health-addr", ":9090", "The address to which the health endpoint binds.")
	metricsAddr         = flag.String("metrics-addr", "0", "The address the metric endpoint binds to.")
	port                = flag.Int("port", 443, "port for the server. defaulted to 443 if unspecified ")
	certDir             = flag.String("cert-dir", "/certs", "The directory where certs are stored, defaults to /certs")
	disableCertRotation = flag.Bool("disable-cert-rotation", false, "disable automatic generation and rotation of webhook TLS certificates/keys")
)

func init() {
	_ = clientgoscheme.AddToScheme(scheme)

	_ = api.AddToScheme(scheme)

	_ = configv1alpha1.AddToScheme(scheme)
	// +kubebuilder:scaffold:scheme
	flag.Var(operations, "operation", "The operation to be performed by this instance. e.g. audit, webhook. This flag can be declared more than once. Omitting will default to supporting all operations.")
}

type opSet map[string]bool

var _ flag.Value = opSet{}

func newOperationSet() opSet {
	return make(map[string]bool)
}

func (l opSet) String() string {
	contents := make([]string, 0)
	for k := range l {
		contents = append(contents, k)
	}
	return fmt.Sprintf("%s", contents)
}

func (l opSet) Set(s string) error {
	l[s] = true
	return nil
}

func main() {
	flag.Parse()
	encoder, ok := logLevelEncoders[*logLevelEncoder]
	if !ok {
		setupLog.Error(fmt.Errorf("invalid log level encoder: %v", *logLevelEncoder), "Invalid log level encoder")
		os.Exit(1)
	}

	switch *logLevel {
	case "DEBUG":
		eCfg := zap.NewDevelopmentEncoderConfig()
		eCfg.LevelKey = *logLevelKey
		eCfg.EncodeLevel = encoder
		ctrl.SetLogger(crzap.New(crzap.UseDevMode(true), crzap.Encoder(zapcore.NewConsoleEncoder(eCfg))))
	case "WARNING", "ERROR":
		setLoggerForProduction(encoder)
	case "INFO":
		fallthrough
	default:
		eCfg := zap.NewProductionEncoderConfig()
		eCfg.LevelKey = *logLevelKey
		eCfg.EncodeLevel = encoder
		ctrl.SetLogger(crzap.New(crzap.UseDevMode(false), crzap.Encoder(zapcore.NewJSONEncoder(eCfg))))
	}

	// set default if --operation is not provided
	if len(operations) == 0 {
		operations["audit"] = true
		operations["webhook"] = true
	}

	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
		NewCache:               dynamiccache.New,
		Scheme:                 scheme,
		MetricsBindAddress:     *metricsAddr,
		LeaderElection:         false,
		Port:                   *port,
		CertDir:                *certDir,
		HealthProbeBindAddress: *healthAddr,
		MapperProvider: func(c *rest.Config) (meta.RESTMapper, error) {
			return apiutil.NewDynamicRESTMapper(c)
		},
	})
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		os.Exit(1)
	}

	// Make sure certs are generated and valid if cert rotation is enabled.
	setupFinished := make(chan struct{})
	if !*disableCertRotation && operations["webhook"] {
		setupLog.Info("setting up cert rotation")
		if err := webhook.AddRotator(mgr, &webhook.CertRotator{
			SecretKey: types.NamespacedName{
				Namespace: util.GetNamespace(),
				Name:      secretName,
			},
			CertDir:        *certDir,
			CAName:         caName,
			CAOrganization: caOrganization,
			DNSName:        dnsName,
			CertsMounted:   setupFinished,
		}, vwhName); err != nil {
			setupLog.Error(err, "unable to set up cert rotation")
			os.Exit(1)
		}
	} else {
		close(setupFinished)
	}

	// ControllerSwitch will be used to disable controllers during our teardown process,
	// avoiding conflicts in finalizer cleanup.
	sw := watch.NewSwitch()

	// Setup tracker and register readiness probe.
	tracker, err := readiness.SetupTracker(mgr)
	if err != nil {
		setupLog.Error(err, "unable to register readiness tracker")
		os.Exit(1)
	}

	// +kubebuilder:scaffold:builder

	if err := mgr.AddHealthzCheck("default", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to create health check")
		os.Exit(1)
	}
	// Setup controllers asynchronously, they will block for certificate generation if needed.
	go setupControllers(mgr, sw, tracker, setupFinished)

	setupLog.Info("starting manager")
	hadError := false
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		hadError = true
	}

	// Manager stops controllers asynchronously.
	// Instead, we use ControllerSwitch to synchronously prevent them from doing more work.
	// This can be removed when finalizer and status teardown is removed.
	setupLog.Info("disabling controllers...")
	sw.Stop()

	// Create a fresh client to be sure RESTmapper is up-to-date
	setupLog.Info("cleaning state...")
	cli, err := k8sCli.New(mgr.GetConfig(), k8sCli.Options{Scheme: mgr.GetScheme(), Mapper: nil})
	if err != nil {
		setupLog.Error(err, "unable to create cleanup client")
		os.Exit(1)
	}

	// Clean up sync finalizers
	// This logic should be disabled if OPA is run as a sidecar
	syncCleaned := make(chan struct{})
	go configController.TearDownState(cli, syncCleaned)

	// Clean up constraint finalizers
	templatesCleaned := make(chan struct{})
	go constrainttemplate.TearDownState(cli, templatesCleaned)

	<-syncCleaned
	<-templatesCleaned
	setupLog.Info("state cleaned")
	if hadError {
		os.Exit(1)
	}
}

func setupControllers(mgr ctrl.Manager, sw *watch.ControllerSwitch, tracker *readiness.Tracker, setupFinished chan struct{}) {
	// Block until the setup (certificate generation) finishes.
	<-setupFinished

	// initialize OPA
	driver := local.New(local.Tracing(false))
	backend, err := opa.NewBackend(opa.Driver(driver))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA backend")
		os.Exit(1)
	}
	client, err := backend.NewClient(opa.Targets(&target.K8sValidationTarget{}))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA client")
	}

	c := mgr.GetCache()
	dc, ok := c.(watch.RemovableCache)
	if !ok {
		err := fmt.Errorf("expected dynamic cache, got: %T", c)
		setupLog.Error(err, "fetching dynamic cache")
		os.Exit(1)
	}
	wm, err := watch.New(dc)
	if err != nil {
		setupLog.Error(err, "unable to create watch manager")
		os.Exit(1)
	}
	if err := mgr.Add(wm); err != nil {
		setupLog.Error(err, "unable to register watch manager to the manager")
		os.Exit(1)
	}

	// Setup all Controllers
	setupLog.Info("setting up controller")
	opts := controller.Dependencies{
		Opa:              client,
		WatchManger:      wm,
		ControllerSwitch: sw,
		Tracker:          tracker,
	}
	if err := controller.AddToManager(mgr, opts); err != nil {
		setupLog.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

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

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

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

func setLoggerForProduction(encoder zapcore.LevelEncoder) {
	sink := zapcore.AddSync(os.Stderr)
	var opts []zap.Option
	encCfg := zap.NewProductionEncoderConfig()
	encCfg.LevelKey = *logLevelKey
	encCfg.EncodeLevel = encoder
	enc := zapcore.NewJSONEncoder(encCfg)
	lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
	opts = append(opts, zap.AddStacktrace(zap.ErrorLevel),
		zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewSampler(core, time.Second, 100, 100)
		}))
	opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
	zlog := zap.New(zapcore.NewCore(&crzap.KubeAwareEncoder{Encoder: enc, Verbose: false}, sink, lvl))
	zlog = zlog.WithOptions(opts...)
	newlogger := zapr.NewLogger(zlog)
	ctrl.SetLogger(newlogger)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"golang.org/x/build/kubernetes/api"
	"log"
	"net/http"
	"os"
	"time"
)

type Stream struct {
	Type  string    `json:"type,omitempty"`
	Event api.Event `json:"object"`
}

func main() {
	apiAddr := os.Getenv("OPENSHIFT_API_URL")
	apiToken := os.Getenv("OPENSHIFT_TOKEN")

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", apiAddr+"/api/v1/events?watch=true", nil)
	if err != nil {
		log.Fatal("## Error while opening connection to openshift api", err)
	}
	req.Header.Add("Authorization", "Bearer "+apiToken)

	for {
		resp, err := client.Do(req)

		if err != nil {
			log.Println("## Error while connecting to:", apiAddr, err)
			time.Sleep(5 * time.Second)
			continue
		}

		reader := bufio.NewReader(resp.Body)

		for {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				log.Println("## Error reading from response stream.", err)
				resp.Body.Close()
				break
			}

			event := Stream{}
			decErr := json.Unmarshal(line, &event)
			if decErr != nil {
				log.Println("## Error decoding json", err)
				resp.Body.Close()
				break
			}

			fmt.Printf("%v | Project: %v | Name: %v | Kind: %v | Reason: %v | Message: %v\n",
				event.Event.LastTimestamp,
				event.Event.Namespace, event.Event.Name,
				event.Event.Kind, event.Event.Reason, event.Event.Message)
		}
	}
}
<commit_msg>Timestamp format<commit_after>package main

import (
	"bufio"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"golang.org/x/build/kubernetes/api"
	"log"
	"net/http"
	"os"
	"time"
)

type Stream struct {
	Type  string    `json:"type,omitempty"`
	Event api.Event `json:"object"`
}

func main() {
	apiAddr := os.Getenv("OPENSHIFT_API_URL")
	apiToken := os.Getenv("OPENSHIFT_TOKEN")

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", apiAddr+"/api/v1/events?watch=true", nil)
	if err != nil {
		log.Fatal("## Error while opening connection to openshift api", err)
	}
	req.Header.Add("Authorization", "Bearer "+apiToken)

	for {
		resp, err := client.Do(req)

		if err != nil {
			log.Println("## Error while connecting to:", apiAddr, err)
			time.Sleep(5 * time.Second)
			continue
		}

		reader := bufio.NewReader(resp.Body)

		for {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				log.Println("## Error reading from response stream.", err)
				resp.Body.Close()
				break
			}

			event := Stream{}
			decErr := json.Unmarshal(line, &event)
			if decErr != nil {
				log.Println("## Error decoding json", err)
				resp.Body.Close()
				break
			}

			fmt.Printf("%v | Project: %v | Name: %v | Kind: %v | Reason: %v | Message: %v\n",
				event.Event.LastTimestamp.Format(time.RFC3339),
				event.Event.Namespace, event.Event.Name,
				event.Event.Kind, event.Event.Reason, event.Event.Message)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"honnef.co/go/importer"

	"code.google.com/p/go.tools/go/types"
	"github.com/kisielk/gotool"

	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	interfacesFrom string
	typesFrom      string
	reverse        bool
	printHelp      bool
)

func init() {
	flag.StringVar(&interfacesFrom, "interfaces", "std", "Comma-separated list of which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&typesFrom, "types", "", "Comma-separated list of packages whose types to check for implemented interfaces. Required.")
	flag.BoolVar(&reverse, "reverse", false, "Print 'implemented by' as opposed to 'implements' relations.")
	flag.BoolVar(&printHelp, "help", false, "Print a help text and exit.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Context
}

func NewContext() *Context {
	importer := importer.NewImporter()
	ctx := &Context{
		allImports: importer.Imports,
		context: types.Context{
			Import: importer.Import,
		},
	}

	return ctx
}

func (ctx *Context) getTypes(paths ...string) ([]Type, []error) {
	var errors []error
	var typs []Type

pathLoop:
	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
				continue
			}
		} else {
			if len(buildPkg.GoFiles) == 0 {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: No (non cgo) Go files", path))
				continue pathLoop
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					errors = append(errors, fmt.Errorf("Couldn't parse %s: %s", err))
					continue pathLoop
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: %s\n", path, err))
				continue pathLoop
			}
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs, errors
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles...)
}

func listErrors(errors []error) {
	for _, err := range errors {
		fmt.Println(err)
	}
}

func doesImplement(typ types.Type, iface *types.Interface) bool {
	fnc, _ := types.MissingMethod(typ, iface)
	return fnc == nil
}

func listImplementedInterfaces(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, typ := range toCheck {
		var implements []Interface
		var implementsPointer []Interface
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implements = append(implements, iface)
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementsPointer = append(implementsPointer, iface)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implements {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implementsPointer {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
	}
}

func listImplementers(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, iface := range interfaces {
		var implementedBy []string
		for _, typ := range toCheck {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implementedBy = append(implementedBy, fmt.Sprintf("%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementedBy = append(implementedBy, fmt.Sprintf("*%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
				}
			}
		}

		if len(implementedBy) > 0 {
			fmt.Printf("%s.%s is implemented by...\n", iface.Obj.Pkg().Path(), iface.Name)
			for _, s := range implementedBy {
				fmt.Printf("\t%s\n", s)
			}
		}
	}
}

func main() {
	if printHelp {
		flag.Usage()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr,
			`implements is a tool that will tell you which types implement which
interfaces, or alternatively by which types interfaces are
implemented.

You use it by specifying a set of packages to scan for interfaces and
another set of packages to scan for types. The two sets can but don't
have to overlap.

When specifying packages, "std" will stand for all of the standard
library. Also, the "..." pattern as understood by the go tool is
supported as well.

By default, implements will iterate all types and list the interfaces
they implement. By supplying the -reverse flag, however, it will
iterate all interfaces and list the types that implement the
interfaces.

Example: For all interfaces in the fmt package you want to know the
types in the standard library that implement them:

    implements -interfaces fmt -types std -reverse

Another example: For all types in your own package you want to know
which interfaces from the standard library they implement:

    implements -interfaces std -types my/own/package`)

		os.Exit(0)
	}

	if typesFrom == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	universe, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(interfacesFrom, ","))...)
	listErrors(errs)
	toCheck, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(typesFrom, ","))...)
	listErrors(errs)

	if reverse {
		listImplementers(universe, toCheck)
	} else {
		listImplementedInterfaces(universe, toCheck)
	}
}
<commit_msg>update for new go/types API<commit_after>package main

import (
	"honnef.co/go/importer"

	"code.google.com/p/go.tools/go/types"
	"github.com/kisielk/gotool"

	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	interfacesFrom string
	typesFrom      string
	reverse        bool
	printHelp      bool
)

func init() {
	flag.StringVar(&interfacesFrom, "interfaces", "std", "Comma-separated list of which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&typesFrom, "types", "", "Comma-separated list of packages whose types to check for implemented interfaces. Required.")
	flag.BoolVar(&reverse, "reverse", false, "Print 'implemented by' as opposed to 'implements' relations.")
	flag.BoolVar(&printHelp, "help", false, "Print a help text and exit.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Context
}

func NewContext() *Context {
	importer := importer.NewImporter()
	ctx := &Context{
		allImports: importer.Imports,
		context: types.Context{
			Import: importer.Import,
		},
	}

	return ctx
}

func (ctx *Context) getTypes(paths ...string) ([]Type, []error) {
	var errors []error
	var typs []Type

pathLoop:
	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
				continue
			}
		} else {
			if len(buildPkg.GoFiles) == 0 {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: No (non cgo) Go files", path))
				continue pathLoop
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					errors = append(errors, fmt.Errorf("Couldn't parse %s: %s", err))
					continue pathLoop
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: %s\n", path, err))
				continue pathLoop
			}
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs, errors
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles, nil)
}

func listErrors(errors []error) {
	for _, err := range errors {
		fmt.Println(err)
	}
}

func doesImplement(typ types.Type, iface *types.Interface) bool {
	fnc, _ := types.MissingMethod(typ, iface)
	return fnc == nil
}

func listImplementedInterfaces(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, typ := range toCheck {
		var implements []Interface
		var implementsPointer []Interface
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implements = append(implements, iface)
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementsPointer = append(implementsPointer, iface)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implements {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implementsPointer {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
	}
}

func listImplementers(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, iface := range interfaces {
		var implementedBy []string
		for _, typ := range toCheck {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implementedBy = append(implementedBy, fmt.Sprintf("%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementedBy = append(implementedBy, fmt.Sprintf("*%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
				}
			}
		}

		if len(implementedBy) > 0 {
			fmt.Printf("%s.%s is implemented by...\n", iface.Obj.Pkg().Path(), iface.Name)
			for _, s := range implementedBy {
				fmt.Printf("\t%s\n", s)
			}
		}
	}
}

func main() {
	if printHelp {
		flag.Usage()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr,
			`implements is a tool that will tell you which types implement which
interfaces, or alternatively by which types interfaces are
implemented.

You use it by specifying a set of packages to scan for interfaces and
another set of packages to scan for types. The two sets can but don't
have to overlap.

When specifying packages, "std" will stand for all of the standard
library. Also, the "..." pattern as understood by the go tool is
supported as well.

By default, implements will iterate all types and list the interfaces
they implement. By supplying the -reverse flag, however, it will
iterate all interfaces and list the types that implement the
interfaces.

Example: For all interfaces in the fmt package you want to know the
types in the standard library that implement them:

    implements -interfaces fmt -types std -reverse

Another example: For all types in your own package you want to know
which interfaces from the standard library they implement:

    implements -interfaces std -types my/own/package`)

		os.Exit(0)
	}

	if typesFrom == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	universe, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(interfacesFrom, ","))...)
	listErrors(errs)
	toCheck, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(typesFrom, ","))...)
	listErrors(errs)

	if reverse {
		listImplementers(universe, toCheck)
	} else {
		listImplementedInterfaces(universe, toCheck)
	}
}
<|endoftext|>