<commit_before>package main

import (
	"github.com/danryan/hal"
	_ "github.com/danryan/hal/adapter/shell"
	_ "github.com/danryan/hal/store/memory"
	"os"
)

var canYouHandler = hal.Hear("(Tim|tim).*can you.*", func(res *hal.Response) error {
	return res.Send("on it!")
})

var echoHandler = hal.Respond(`echo (.+)`, func(res *hal.Response) error {
	return res.Reply(res.Match[1])
})

func run() int {
	robot, err := hal.NewRobot()
        hal.Logger.Info("Starting")

	if err != nil {
		hal.Logger.Error(err)
		return 1
	}

	robot.Handle(
		canYouHandler,
		echoHandler,
	)

	if err := robot.Run(); err != nil {
		hal.Logger.Error(err)
		return 1
	}
	hal.Logger.Info("Started")
	return 0
}

func main() {
	os.Exit(run())
}
<commit_msg>Add Slack Adapter.<commit_after>package main

import (
	"github.com/danryan/hal"
	_ "github.com/danryan/hal/adapter/shell"
	_ "github.com/danryan/hal/adapter/slack"
	_ "github.com/danryan/hal/store/memory"
	"os"
)

var canYouHandler = hal.Hear("(Tim|tim).*can you.*", func(res *hal.Response) error {
	return res.Send("on it!")
})

var echoHandler = hal.Respond(`echo (.+)`, func(res *hal.Response) error {
	return res.Reply(res.Match[1])
})

func run() int {
	robot, err := hal.NewRobot()

	if err != nil {
		hal.Logger.Error(err)
		return 1
	}

	robot.Handle(
		canYouHandler,
		echoHandler,
	)

	if err := robot.Run(); err != nil {
		hal.Logger.Error(err)
		return 1
	}
	return 0
}

func main() {
	os.Exit(run())
}
<|endoftext|>


<commit_before>package main

import (
	// "database/sql"
	"encoding/json"
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/nu7hatch/gouuid"
)

var db *sqlx.DB

type User struct {
	Id       string `json:"id" db:"id"`
	Email    string `json:"email" db:"email"`
	Password string `json:"password" db:"password"`
}

type Notification struct {
	Id      string `json:"id" db:"id"`
	Message string `json:"message" db:"message"`
	UserId  string `json:"user_id" db:"user_id"`
}

type Token struct {
	Id     string `json:"id" db:"id"`
	Token  string `json:"token" db:"token"`
	UserId string `json:"user_id" db:"user_id"`
	Status bool   `json:"status" db:"status"`
}

func DBConnection() *sqlx.DB {
	dbURL := os.Getenv("DATABASE_URL")

	if dbURL == "" {
		log.Fatal("$DATABASE_URL environment variable must be set")
	} else {
		fmt.Println("Connected to database: " + dbURL)
	}

	db, err := sqlx.Connect("postgres", dbURL)
	if err != nil {
		log.Fatal(err)
	}

	return db
}

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		log.Fatal("$PORT environment variable must be set")
	} else {
		fmt.Println("Running on port: " + port)
	}

	db = DBConnection()
	router := mux.NewRouter().StrictSlash(true)

	router.HandleFunc("/", Index)
	router.HandleFunc("/users/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}/notifications", ListUserNotifications).Methods("GET")
	router.HandleFunc("/notifications", CreateNotification).Methods("POST")
	router.HandleFunc("/login", UserLogin).Methods("POST")
	router.HandleFunc("/tokens", CreateToken).Methods("POST")

	log.Fatal(http.ListenAndServe(":"+port, router))
}

/// UserLogin will register a user with the service so that they can receive notifications
func UserLogin(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var user User

	err := decoder.Decode(&user)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	user.Id = id.String()
	query := "INSERT INTO \"user\" (id, email, password) VALUES (:id, :email, :password)"
	_, err = db.NamedExec(query, &user)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(user)

	w.Write(jsonString)
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "OK")
}

func ListUserNotifications(w http.ResponseWriter, r *http.Request) {
	// Get all notifications for user
	vars := mux.Vars(r)
	id, _ := vars["id"]
	query := `SELECT id, message, user_id FROM notification WHERE user_id = $1`

	fmt.Printf("User ID %v", id)

	var notifications []*Notification

	db.Select(&notifications, query, id)
	fmt.Printf("Notifications: %v", notifications)
	w.Header().Set("Content-Type", "application/json")

	jsonString, _ := json.Marshal(notifications)

	w.Write(jsonString)
}

func CreateNotification(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var notification Notification

	err := decoder.Decode(&notification)
	if err != nil {
		log.Fatal(err)
	}

	u, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	notification.Id = u.String()
	query := "INSERT INTO notification (id, message, user_id) VALUES (:id, :message, :user_id)"
	_, err = db.NamedExec(query, &notification)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(notification)

	w.Write(jsonString)

}

func CreateToken(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var token Token

	err := decoder.Decode(&token)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	token.Id = id.String()
	query := "INSERT INTO token (id, token, user_id, status) VALUES (:id, :token, :user_id, :status)"
	_, err = db.NamedExec(query, &token)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(token)

	w.Write(jsonString)
}
<commit_msg>order endpoints<commit_after>package main

import (
	// "database/sql"
	"encoding/json"
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/nu7hatch/gouuid"
)

var db *sqlx.DB

type User struct {
	Id       string `json:"id" db:"id"`
	Email    string `json:"email" db:"email"`
	Password string `json:"password" db:"password"`
}

type Notification struct {
	Id      string `json:"id" db:"id"`
	Message string `json:"message" db:"message"`
	UserId  string `json:"user_id" db:"user_id"`
}

type Token struct {
	Id     string `json:"id" db:"id"`
	Token  string `json:"token" db:"token"`
	UserId string `json:"user_id" db:"user_id"`
	Status bool   `json:"status" db:"status"`
}

func DBConnection() *sqlx.DB {
	dbURL := os.Getenv("DATABASE_URL")

	if dbURL == "" {
		log.Fatal("$DATABASE_URL environment variable must be set")
	} else {
		fmt.Println("Connected to database: " + dbURL)
	}

	db, err := sqlx.Connect("postgres", dbURL)
	if err != nil {
		log.Fatal(err)
	}

	return db
}

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		log.Fatal("$PORT environment variable must be set")
	} else {
		fmt.Println("Running on port: " + port)
	}

	db = DBConnection()
	router := mux.NewRouter().StrictSlash(true)

	router.HandleFunc("/", Index)
	router.HandleFunc("/login", UserLogin).Methods("POST")
	router.HandleFunc("/tokens", CreateToken).Methods("POST")
	router.HandleFunc("/notifications", CreateNotification).Methods("POST")
	router.HandleFunc("/users/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}/notifications", ListUserNotifications).Methods("GET")

	log.Fatal(http.ListenAndServe(":"+port, router))
}

/// UserLogin will register a user with the service so that they can receive notifications
func UserLogin(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var user User

	err := decoder.Decode(&user)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	user.Id = id.String()
	query := "INSERT INTO \"user\" (id, email, password) VALUES (:id, :email, :password)"
	_, err = db.NamedExec(query, &user)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(user)

	w.Write(jsonString)
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "OK")
}

func ListUserNotifications(w http.ResponseWriter, r *http.Request) {
	// Get all notifications for user
	vars := mux.Vars(r)
	id, _ := vars["id"]
	query := `SELECT id, message, user_id FROM notification WHERE user_id = $1`

	fmt.Printf("User ID %v", id)

	var notifications []*Notification

	db.Select(&notifications, query, id)
	fmt.Printf("Notifications: %v", notifications)
	w.Header().Set("Content-Type", "application/json")

	jsonString, _ := json.Marshal(notifications)

	w.Write(jsonString)
}

func CreateNotification(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var notification Notification

	err := decoder.Decode(&notification)
	if err != nil {
		log.Fatal(err)
	}

	u, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	notification.Id = u.String()
	query := "INSERT INTO notification (id, message, user_id) VALUES (:id, :message, :user_id)"
	_, err = db.NamedExec(query, &notification)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(notification)

	// TODO: Make call to Apple Servers to broadcast notification to user's device

	w.Write(jsonString)

}

func CreateToken(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var token Token

	err := decoder.Decode(&token)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	token.Id = id.String()
	query := "INSERT INTO token (id, token, user_id, status) VALUES (:id, :token, :user_id, :status)"
	_, err = db.NamedExec(query, &token)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(token)

	w.Write(jsonString)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/jbuchbinder/go-gmetric/gmetric"
	"log"
	"net"
	"regexp"
	"sort"
	"strconv"
	"time"
)

const (
	TCP = "tcp"
	UDP = "udp"
)

type Packet struct {
	Bucket   string
	Value    int
	Modifier string
	Sampling float32
}

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	graphiteAddress  = flag.String("graphite", "localhost:2003", "Graphite service address")
	gangliaAddress   = flag.String("ganglia", "localhost", "Ganglia gmond service address")
	gangliaPort      = flag.Int("ganglia-port", 8649, "Ganglia gmond service port")
	gangliaSpoofHost = flag.String("ganglia-spoof-host", "", "Ganglia gmond spoof host string")
	flushInterval    = flag.Int64("flush-interval", 10, "Flush interval")
	percentThreshold = flag.Int("percent-threshold", 90, "Threshold percent")
)

var (
	In       = make(chan Packet, 10000)
	counters = make(map[string]int)
	timers   = make(map[string][]int)
	gauges   = make(map[string]int)
)

func monitor() {
	var err error
	if err != nil {
		log.Println(err)
	}
	t := time.NewTicker(time.Duration(*flushInterval) * time.Second)
	for {
		select {
		case <-t.C:
			submit()
		case s := <-In:
			if s.Modifier == "ms" {
				_, ok := timers[s.Bucket]
				if !ok {
					var t []int
					timers[s.Bucket] = t
				}
				timers[s.Bucket] = append(timers[s.Bucket], s.Value)
			} else if s.Modifier == "g" {
				_, ok := gauges[s.Bucket]
				if !ok {
					gauges[s.Bucket] = 0
				}
				gauges[s.Bucket] += s.Value
			} else {
				_, ok := counters[s.Bucket]
				if !ok {
					counters[s.Bucket] = 0
				}
				counters[s.Bucket] += int(float32(s.Value) * (1 / s.Sampling))
			}
		}
	}
}

func submit() {
	var clientGraphite net.Conn
	if clientGraphite != nil {
		log.Println(clientGraphite)
	}
	var err error
	if err != nil {
		log.Println(err)
	}
	if *graphiteAddress != "" {
		clientGraphite, err := net.Dial(TCP, *graphiteAddress)
		if clientGraphite != nil {
			// This is a really painful hack to get around the inability of
			// the Go compiler to notice that I'm using clientGraphite.
			if clientGraphite.LocalAddr() == nil {
			}

			// Run this when we're all done, only if clientGraphite was opened.
			defer clientGraphite.Close()
		}
		if err != nil {
			log.Printf(err.Error())
		}
	}
	var useGanglia bool
	var gm gmetric.Gmetric
	gmSubmit := func(name string, value uint32) {
		if useGanglia {
			m_value := fmt.Sprint(value)
			m_units := "count"
			m_type := uint32(gmetric.VALUE_UNSIGNED_INT)
			m_slope := uint32(gmetric.SLOPE_BOTH)
			m_grp := "statsd"
			m_ival := uint32(*flushInterval * int64(2))

			go gm.SendMetric(name, m_value, m_type, m_units, m_slope, m_ival, m_ival, m_grp)
		}
	}
	if *gangliaAddress != "" {
		gIP, err := net.ResolveIPAddr("ip4", *gangliaAddress)
		if err != nil {
			panic("Could not look up ganglia address")
		}
		gm := gmetric.Gmetric{gIP.IP, *gangliaPort, *gangliaSpoofHost, *gangliaSpoofHost}
		if gm.GangliaPort == 0 {
		}
		useGanglia = true
	} else {
		useGanglia = false
	}
	numStats := 0
	now := time.Now()
	buffer := bytes.NewBufferString("")
	for s, c := range counters {
		value := int64(c) / ((*flushInterval * int64(time.Second)) / 1e3)
		fmt.Fprintf(buffer, "stats.%s %d %d\n", s, value, now)
		gmSubmit(fmt.Sprintf("stats_%s", s), uint32(value))
		fmt.Fprintf(buffer, "stats_counts.%s %d %d\n", s, c, now)
		gmSubmit(fmt.Sprintf("stats_counts_%s", s), uint32(c))
		counters[s] = 0
		numStats++
	}
	for i, g := range gauges {
		value := int64(g)
		fmt.Fprintf(buffer, "stats.%s %d %d\n", i, value, now)
		gmSubmit(fmt.Sprintf("stats_%s", i), uint32(value))
		numStats++
	}
	for u, t := range timers {
		if len(t) > 0 {
			sort.Ints(t)
			min := t[0]
			max := t[len(t)-1]
			mean := min
			maxAtThreshold := max
			count := len(t)
			if len(t) > 1 {
				var thresholdIndex int
				thresholdIndex = ((100 - *percentThreshold) / 100) * count
				numInThreshold := count - thresholdIndex
				values := t[0:numInThreshold]

				sum := 0
				for i := 0; i < numInThreshold; i++ {
					sum += values[i]
				}
				mean = sum / numInThreshold
			}
			var z []int
			timers[u] = z

			fmt.Fprintf(buffer, "stats.timers.%s.mean %d %d\n", u, mean, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_mean", u), uint32(mean))
			fmt.Fprintf(buffer, "stats.timers.%s.upper %d %d\n", u, max, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_upper", u), uint32(max))
			fmt.Fprintf(buffer, "stats.timers.%s.upper_%d %d %d\n", u,
				*percentThreshold, maxAtThreshold, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_upper_%d", u, *percentThreshold), uint32(maxAtThreshold))
			fmt.Fprintf(buffer, "stats.timers.%s.lower %d %d\n", u, min, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_lower", u), uint32(min))
			fmt.Fprintf(buffer, "stats.timers.%s.count %d %d\n", u, count, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_count", u), uint32(count))
		}
		numStats++
	}
	fmt.Fprintf(buffer, "statsd.numStats %d %d\n", numStats, now)
	gmSubmit("statsd_numStats", uint32(numStats))
	if clientGraphite != nil {
		clientGraphite.Write(buffer.Bytes())
	}
}

func handleMessage(conn *net.UDPConn, remaddr net.Addr, buf *bytes.Buffer) {
	var packet Packet
	var sanitizeRegexp = regexp.MustCompile("[^a-zA-Z0-9\\-_\\.:\\|@]")
	var packetRegexp = regexp.MustCompile("([a-zA-Z0-9_]+):([0-9]+)\\|(c|ms)(\\|@([0-9\\.]+))?")
	s := sanitizeRegexp.ReplaceAllString(buf.String(), "")
	for _, item := range packetRegexp.FindAllStringSubmatch(s, -1) {
		value, err := strconv.Atoi(item[2])
		if err != nil {
			if item[3] == "ms" {
				value = 0
			} else {
				value = 1
			}
		}

		sampleRate, err := strconv.ParseFloat(item[5], 32)
		if err != nil {
			sampleRate = 1
		}

		packet.Bucket = item[1]
		packet.Value = value
		packet.Modifier = item[3]
		packet.Sampling = float32(sampleRate)
		In <- packet
	}
}

func udpListener() {
	address, _ := net.ResolveUDPAddr(UDP, *serviceAddress)
	listener, err := net.ListenUDP(UDP, address)
	defer listener.Close()
	if err != nil {
		log.Fatalf("ListenAndServe: %s", err.Error())
	}
	for {
		message := make([]byte, 512)
		n, remaddr, error := listener.ReadFrom(message)
		if error != nil {
			continue
		}
		buf := bytes.NewBuffer(message[0:n])
		go handleMessage(listener, remaddr, buf)
	}
}

func main() {
	flag.Parse()
	go udpListener()
	monitor()
}
<commit_msg>Adjust to work with modern go-gmetric library.<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/jbuchbinder/go-gmetric/gmetric"
	"log"
	"net"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"
)

const (
	TCP = "tcp"
	UDP = "udp"
)

type Packet struct {
	Bucket   string
	Value    int
	Modifier string
	Sampling float32
}

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	graphiteAddress  = flag.String("graphite", "localhost:2003", "Graphite service address")
	gangliaAddress   = flag.String("ganglia", "localhost", "Ganglia gmond service address")
	gangliaPort      = flag.Int("ganglia-port", 8649, "Ganglia gmond service port")
	gangliaSpoofHost = flag.String("ganglia-spoof-host", "", "Ganglia gmond spoof host string")
	flushInterval    = flag.Int64("flush-interval", 10, "Flush interval")
	percentThreshold = flag.Int("percent-threshold", 90, "Threshold percent")
)

var (
	In       = make(chan Packet, 10000)
	counters = make(map[string]int)
	timers   = make(map[string][]int)
	gauges   = make(map[string]int)
)

func monitor() {
	var err error
	if err != nil {
		log.Println(err)
	}
	t := time.NewTicker(time.Duration(*flushInterval) * time.Second)
	for {
		select {
		case <-t.C:
			submit()
		case s := <-In:
			if s.Modifier == "ms" {
				_, ok := timers[s.Bucket]
				if !ok {
					var t []int
					timers[s.Bucket] = t
				}
				timers[s.Bucket] = append(timers[s.Bucket], s.Value)
			} else if s.Modifier == "g" {
				_, ok := gauges[s.Bucket]
				if !ok {
					gauges[s.Bucket] = 0
				}
				gauges[s.Bucket] += s.Value
			} else {
				_, ok := counters[s.Bucket]
				if !ok {
					counters[s.Bucket] = 0
				}
				counters[s.Bucket] += int(float32(s.Value) * (1 / s.Sampling))
			}
		}
	}
}

func submit() {
	var clientGraphite net.Conn
	if clientGraphite != nil {
		log.Println(clientGraphite)
	}
	var err error
	if err != nil {
		log.Println(err)
	}
	if *graphiteAddress != "" {
		clientGraphite, err := net.Dial(TCP, *graphiteAddress)
		if clientGraphite != nil {
			// This is a really painful hack to get around the inability of
			// the Go compiler to notice that I'm using clientGraphite.
			if clientGraphite.LocalAddr() == nil {
			}

			// Run this when we're all done, only if clientGraphite was opened.
			defer clientGraphite.Close()
		}
		if err != nil {
			log.Printf(err.Error())
		}
	}
	var useGanglia bool
	var gm gmetric.Gmetric
	gmSubmit := func(name string, value uint32) {
		if useGanglia {
			m_value := fmt.Sprint(value)
			m_units := "count"
			m_type := uint32(gmetric.VALUE_UNSIGNED_INT)
			m_slope := uint32(gmetric.SLOPE_BOTH)
			m_grp := "statsd"
			m_ival := uint32(*flushInterval * int64(2))

			go gm.SendMetric(name, m_value, m_type, m_units, m_slope, m_ival, m_ival, m_grp)
		}
	}
	if *gangliaAddress != "" {
		gm = gmetric.Gmetric{
			Host:  *gangliaSpoofHost,
			Spoof: *gangliaSpoofHost,
		}
		gm.SetVerbose(false)

		if strings.Contains(*gangliaAddress, ",") {
			segs := strings.Split(*gangliaAddress, ",")
			for i := 0; i < len(segs); i++ {
				gIP, err := net.ResolveIPAddr("ip4", segs[i])
				if err != nil {
					panic(err.Error())
				}
				gm.AddServer(gmetric.GmetricServer{gIP.IP, *gangliaPort})
			}
		} else {
			gIP, err := net.ResolveIPAddr("ip4", *gangliaAddress)
			if err != nil {
				panic(err.Error())
			}
			gm.AddServer(gmetric.GmetricServer{gIP.IP, *gangliaPort})
		}
		useGanglia = true
	} else {
		useGanglia = false
	}
	numStats := 0
	now := time.Now()
	buffer := bytes.NewBufferString("")
	for s, c := range counters {
		value := int64(c) / ((*flushInterval * int64(time.Second)) / 1e3)
		fmt.Fprintf(buffer, "stats.%s %d %d\n", s, value, now)
		gmSubmit(fmt.Sprintf("stats_%s", s), uint32(value))
		fmt.Fprintf(buffer, "stats_counts.%s %d %d\n", s, c, now)
		gmSubmit(fmt.Sprintf("stats_counts_%s", s), uint32(c))
		counters[s] = 0
		numStats++
	}
	for i, g := range gauges {
		value := int64(g)
		fmt.Fprintf(buffer, "stats.%s %d %d\n", i, value, now)
		gmSubmit(fmt.Sprintf("stats_%s", i), uint32(value))
		numStats++
	}
	for u, t := range timers {
		if len(t) > 0 {
			sort.Ints(t)
			min := t[0]
			max := t[len(t)-1]
			mean := min
			maxAtThreshold := max
			count := len(t)
			if len(t) > 1 {
				var thresholdIndex int
				thresholdIndex = ((100 - *percentThreshold) / 100) * count
				numInThreshold := count - thresholdIndex
				values := t[0:numInThreshold]

				sum := 0
				for i := 0; i < numInThreshold; i++ {
					sum += values[i]
				}
				mean = sum / numInThreshold
			}
			var z []int
			timers[u] = z

			fmt.Fprintf(buffer, "stats.timers.%s.mean %d %d\n", u, mean, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_mean", u), uint32(mean))
			fmt.Fprintf(buffer, "stats.timers.%s.upper %d %d\n", u, max, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_upper", u), uint32(max))
			fmt.Fprintf(buffer, "stats.timers.%s.upper_%d %d %d\n", u,
				*percentThreshold, maxAtThreshold, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_upper_%d", u, *percentThreshold), uint32(maxAtThreshold))
			fmt.Fprintf(buffer, "stats.timers.%s.lower %d %d\n", u, min, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_lower", u), uint32(min))
			fmt.Fprintf(buffer, "stats.timers.%s.count %d %d\n", u, count, now)
			gmSubmit(fmt.Sprintf("stats_timers_%s_count", u), uint32(count))
		}
		numStats++
	}
	fmt.Fprintf(buffer, "statsd.numStats %d %d\n", numStats, now)
	gmSubmit("statsd_numStats", uint32(numStats))
	if clientGraphite != nil {
		clientGraphite.Write(buffer.Bytes())
	}
}

func handleMessage(conn *net.UDPConn, remaddr net.Addr, buf *bytes.Buffer) {
	var packet Packet
	var sanitizeRegexp = regexp.MustCompile("[^a-zA-Z0-9\\-_\\.:\\|@]")
	var packetRegexp = regexp.MustCompile("([a-zA-Z0-9_]+):([0-9]+)\\|(c|ms)(\\|@([0-9\\.]+))?")
	s := sanitizeRegexp.ReplaceAllString(buf.String(), "")
	for _, item := range packetRegexp.FindAllStringSubmatch(s, -1) {
		value, err := strconv.Atoi(item[2])
		if err != nil {
			if item[3] == "ms" {
				value = 0
			} else {
				value = 1
			}
		}

		sampleRate, err := strconv.ParseFloat(item[5], 32)
		if err != nil {
			sampleRate = 1
		}

		packet.Bucket = item[1]
		packet.Value = value
		packet.Modifier = item[3]
		packet.Sampling = float32(sampleRate)
		In <- packet
	}
}

func udpListener() {
	address, _ := net.ResolveUDPAddr(UDP, *serviceAddress)
	listener, err := net.ListenUDP(UDP, address)
	defer listener.Close()
	if err != nil {
		log.Fatalf("ListenAndServe: %s", err.Error())
	}
	for {
		message := make([]byte, 512)
		n, remaddr, error := listener.ReadFrom(message)
		if error != nil {
			continue
		}
		buf := bytes.NewBuffer(message[0:n])
		go handleMessage(listener, remaddr, buf)
	}
}

func main() {
	flag.Parse()
	go udpListener()
	monitor()
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	loudp2p "github.com/matiasinsaurralde/loudp2p/core"
	crypto "github.com/matiasinsaurralde/loudp2p/crypto"
)

func main() {
	log.Println("loudp2p starts")

	var err error

	var settings *loudp2p.Settings
	settings = loudp2p.LoadSettings()

	if settings == nil {
		log.Println("No keys present, generating.")
		privKey, pubKey, peerID := crypto.GenerateKeys()
		settings = &loudp2p.Settings{
			PrivKeyBytes: privKey,
			PubKeyBytes:  pubKey,
			PeerID:       peerID,
		}
		err = settings.Persist()
		if err != nil {
			log.Println("Couldn't persist settings!")
			panic(err)
		}
	} else {
		log.Println("Using existing keys.")
	}

	log.Println("Peer ID is", settings.PeerID)

	var client loudp2p.Client
	var server loudp2p.Server

	client, err = loudp2p.NewClient(settings)
	if err != nil {
		log.Println("Couldn't initialize client!")
		panic(err)
	}
	server = loudp2p.NewServer(settings)

	// go client.StartDiscovery()
	// go server.Start()
	for {
	}
	log.Println(1, client, server)
}
<commit_msg>Load keys after creation.<commit_after>package main

import (
	"log"

	"crypto/ecdsa"

	loudp2p "github.com/matiasinsaurralde/loudp2p/core"
	crypto "github.com/matiasinsaurralde/loudp2p/crypto"
)

func main() {
	log.Println("loudp2p starts")

	var err error

	var settings *loudp2p.Settings
	settings = loudp2p.LoadSettings()

	if settings == nil {
		log.Println("No keys present, generating.")

		var privateKey *ecdsa.PrivateKey
		var publicKey *ecdsa.PublicKey
		var privateKeyBytes, publicKeyBytes []byte
		var peerID string

		privateKey, privateKeyBytes, publicKey, publicKeyBytes, peerID, err = crypto.GenerateKeys()

		if err != nil {
			log.Println("Couldn't generate keys!")
			panic(err)
		}

		settings = &loudp2p.Settings{
			PrivateKey:   privateKey,
			PublicKey:    publicKey,
			PrivKeyBytes: privateKeyBytes,
			PubKeyBytes:  publicKeyBytes,
			PeerID:       peerID,
		}
		err = settings.Persist()
		if err != nil {
			log.Println("Couldn't persist settings!")
			panic(err)
		}
	} else {
		log.Println("Using existing keys.")
	}

	log.Println("Peer ID is", settings.PeerID)

	var client loudp2p.Client
	var server loudp2p.Server

	client, err = loudp2p.NewClient(settings)
	if err != nil {
		log.Println("Couldn't initialize client!")
		panic(err)
	}
	server = loudp2p.NewServer(settings)

	// go client.StartDiscovery()
	// go server.Start()
	for {
	}
	log.Println(1, client, server)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/reexec"
	"github.com/ehazlett/simplelog"
	"github.com/rancher/norman/pkg/dump"
	"github.com/rancher/norman/signal"
	"github.com/rancher/rancher/app"
	"github.com/rancher/rancher/k8s"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

var (
	VERSION = "dev"
)

func main() {
	if reexec.Init() {
		return
	}

	os.Unsetenv("SSH_AUTH_SOCK")
	os.Unsetenv("SSH_AGENT_PID")

	if dir, err := os.Getwd(); err == nil {
		dmPath := filepath.Join(dir, "management-state", "bin")
		os.MkdirAll(dmPath, 0700)
		newPath := fmt.Sprintf("%s%s%s", dmPath, string(os.PathListSeparator), os.Getenv("PATH"))

		os.Setenv("PATH", newPath)
	}

	var config app.Config

	app := cli.NewApp()
	app.Version = VERSION
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "kubeconfig",
			Usage:       "Kube config for accessing k8s cluster",
			EnvVar:      "KUBECONFIG",
			Destination: &config.KubeConfig,
		},
		cli.BoolFlag{
			Name:        "debug",
			Usage:       "Enable debug logs",
			Destination: &config.Debug,
		},
		cli.StringFlag{
			Name:        "add-local",
			Usage:       "Add local cluster (true, false, auto)",
			Value:       "auto",
			Destination: &config.AddLocal,
		},
		cli.IntFlag{
			Name:        "http-listen-port",
			Usage:       "HTTP listen port",
			Value:       8080,
			Destination: &config.HTTPListenPort,
		},
		cli.IntFlag{
			Name:        "https-listen-port",
			Usage:       "HTTPS listen port",
			Value:       8443,
			Destination: &config.HTTPSListenPort,
		},
		cli.StringFlag{
			Name:        "k8s-mode",
			Usage:       "Mode to run or access k8s API server for management API (embedded, external, auto)",
			Value:       "auto",
			Destination: &config.K8sMode,
		},
		cli.StringFlag{
			Name:  "log-format",
			Usage: "Log formatter used (json, text, simple)",
			Value: "simple",
		},
		cli.StringSliceFlag{
			Name:  "acme-domain",
			Usage: "Domain to register with LetsEncrypt",
		},
	}

	app.Action = func(c *cli.Context) error {
		// enable profiler
		go func() {
			log.Println(http.ListenAndServe("localhost:6060", nil))
		}()

		config.ACMEDomains = c.GlobalStringSlice("acme-domain")
		initLogs(c, config)
		return run(config)
	}

	app.ExitErrHandler = func(c *cli.Context, err error) {
		logrus.Fatal(err)
	}

	app.Run(os.Args)
}

func initLogs(c *cli.Context, cfg app.Config) {
	if cfg.Debug {
		logrus.SetLevel(logrus.DebugLevel)
	}

	switch c.String("log-format") {
	case "simple":
		logrus.SetFormatter(&simplelog.StandardFormatter{})
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	}
	logrus.SetOutput(os.Stdout)
	//server.StartServerWithDefaults()
}

func run(cfg app.Config) error {
	dump.GoroutineDumpOn(syscall.SIGUSR1, syscall.SIGILL)
	ctx := signal.SigTermCancelContext(context.Background())

	embedded, ctx, kubeConfig, err := k8s.GetConfig(ctx, cfg.K8sMode, cfg.KubeConfig)
	if err != nil {
		return err
	}
	cfg.Embedded = embedded

	os.Unsetenv("KUBECONFIG")
	kubeConfig.Timeout = 30 * time.Second
	return app.Run(ctx, *kubeConfig, &cfg)
}
<commit_msg>Add leo's log server for dynamic log levels<commit_after>package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/reexec"
	"github.com/ehazlett/simplelog"
	"github.com/leodotcloud/log/server"
	"github.com/rancher/norman/pkg/dump"
	"github.com/rancher/norman/signal"
	"github.com/rancher/rancher/app"
	"github.com/rancher/rancher/k8s"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

var (
	VERSION = "dev"
)

func main() {
	if reexec.Init() {
		return
	}

	os.Unsetenv("SSH_AUTH_SOCK")
	os.Unsetenv("SSH_AGENT_PID")

	if dir, err := os.Getwd(); err == nil {
		dmPath := filepath.Join(dir, "management-state", "bin")
		os.MkdirAll(dmPath, 0700)
		newPath := fmt.Sprintf("%s%s%s", dmPath, string(os.PathListSeparator), os.Getenv("PATH"))

		os.Setenv("PATH", newPath)
	}

	var config app.Config

	app := cli.NewApp()
	app.Version = VERSION
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "kubeconfig",
			Usage:       "Kube config for accessing k8s cluster",
			EnvVar:      "KUBECONFIG",
			Destination: &config.KubeConfig,
		},
		cli.BoolFlag{
			Name:        "debug",
			Usage:       "Enable debug logs",
			Destination: &config.Debug,
		},
		cli.StringFlag{
			Name:        "add-local",
			Usage:       "Add local cluster (true, false, auto)",
			Value:       "auto",
			Destination: &config.AddLocal,
		},
		cli.IntFlag{
			Name:        "http-listen-port",
			Usage:       "HTTP listen port",
			Value:       8080,
			Destination: &config.HTTPListenPort,
		},
		cli.IntFlag{
			Name:        "https-listen-port",
			Usage:       "HTTPS listen port",
			Value:       8443,
			Destination: &config.HTTPSListenPort,
		},
		cli.StringFlag{
			Name:        "k8s-mode",
			Usage:       "Mode to run or access k8s API server for management API (embedded, external, auto)",
			Value:       "auto",
			Destination: &config.K8sMode,
		},
		cli.StringFlag{
			Name:  "log-format",
			Usage: "Log formatter used (json, text, simple)",
			Value: "simple",
		},
		cli.StringSliceFlag{
			Name:  "acme-domain",
			Usage: "Domain to register with LetsEncrypt",
		},
	}

	app.Action = func(c *cli.Context) error {
		// enable profiler
		go func() {
			log.Println(http.ListenAndServe("localhost:6060", nil))
		}()

		config.ACMEDomains = c.GlobalStringSlice("acme-domain")
		initLogs(c, config)
		return run(config)
	}

	app.ExitErrHandler = func(c *cli.Context, err error) {
		logrus.Fatal(err)
	}

	app.Run(os.Args)
}

func initLogs(c *cli.Context, cfg app.Config) {
	if cfg.Debug {
		logrus.SetLevel(logrus.DebugLevel)
	}

	switch c.String("log-format") {
	case "simple":
		logrus.SetFormatter(&simplelog.StandardFormatter{})
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	}
	logrus.SetOutput(os.Stdout)
	server.StartServerWithDefaults()
}

func run(cfg app.Config) error {
	dump.GoroutineDumpOn(syscall.SIGUSR1, syscall.SIGILL)
	ctx := signal.SigTermCancelContext(context.Background())

	embedded, ctx, kubeConfig, err := k8s.GetConfig(ctx, cfg.K8sMode, cfg.KubeConfig)
	if err != nil {
		return err
	}
	cfg.Embedded = embedded

	os.Unsetenv("KUBECONFIG")
	kubeConfig.Timeout = 30 * time.Second
	return app.Run(ctx, *kubeConfig, &cfg)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	statsite "github.com/armon/go-metrics"
	"github.com/pshima/go-passenger-metrics/metrics"
	"log"
	"os"
	"time"
)

const (
	passengerPath string = "/usr/sbin/passenger-status"
	appname       string = "go-passenger-metrics"
)

var quiet bool = false

func main() {
	args := os.Args
	if len(args) > 1 {
		if args[1] == "-quiet" {
			quiet = true
		}
	}

	statsite_host := os.Getenv("GRAPHITE_HOST")
	statsite_port := os.Getenv("GRAPHITE_PORT")
	if statsite_host == "" {
		log.Fatal("GRAPHITE_HOST is empty, exiting")
	}
	if statsite_port == "" {
		log.Fatal("GRAPHITE_PORT is empty, exiting")
	}
	statsite_addr := fmt.Sprintf("%s:%s", statsite_host, statsite_port)
	log.Printf("%s Starting metrics output to %s", appname, statsite_addr)
	sink, err := statsite.NewStatsiteSink(statsite_addr)
	if err != nil {
		log.Fatalf("Error connecting", err)
	}
	if _, err := statsite.NewGlobal(statsite.DefaultConfig(appname), sink); err != nil {
		log.Fatalf("Error starting metrics layer")
	}
	ticker := time.NewTicker(10 * time.Second)
	for range ticker.C {
		run()
	}

}

func run() {
	p := &passengermetrics.PassengerCollection{}
	p.PassengerPath = passengerPath
	if err := p.RunPassengerStatus(); err != nil {
		log.Fatalf("%s Error running passenger status: %v", appname, err)
	}
	if err := p.ParseRawOutput(); err != nil {
		log.Fatalf("%s %v", appname, err)
	}

	if quiet != true {
		log.Printf("%s Queue Depth: %v", appname, p.ParsedOutput.QueueLength)
	}

	statsite.SetGauge([]string{"passenger-queue-depth"}, float32(p.ParsedOutput.QueueLength))
}
<commit_msg>Pass through go vet and linting<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"time"

	statsite "github.com/armon/go-metrics"
	"github.com/pshima/go-passenger-metrics/metrics"
)

const (
	passengerPath string = "/usr/sbin/passenger-status"
	appName       string = "go-passenger-metrics"
)

var quiet bool

func main() {
	args := os.Args
	if len(args) > 1 {
		if args[1] == "-quiet" {
			quiet = true
		}
	}

	statsiteHost := os.Getenv("GRAPHITE_HOST")
	statsitePort := os.Getenv("GRAPHITE_PORT")
	if statsiteHost == "" {
		log.Fatal("GRAPHITE_HOST is empty, exiting")
	}
	if statsitePort == "" {
		log.Fatal("GRAPHITE_PORT is empty, exiting")
	}
	statsiteAddr := fmt.Sprintf("%s:%s", statsiteHost, statsitePort)
	log.Printf("%s Starting metrics output to %s", appName, statsiteAddr)
	sink, err := statsite.NewStatsiteSink(statsiteAddr)
	if err != nil {
		log.Fatalf("Error connecting: %v", err)
	}
	if _, err := statsite.NewGlobal(statsite.DefaultConfig(appName), sink); err != nil {
		log.Fatalf("Error starting metrics layer")
	}
	ticker := time.NewTicker(10 * time.Second)
	for range ticker.C {
		run()
	}

}

func run() {
	p := passengermetrics.PassengerCollection{
		PassengerPath: passengerPath,
	}
	if err := p.RunPassengerStatus(); err != nil {
		log.Fatalf("%s Error running passenger status: %v", appName, err)
	}
	if err := p.ParseRawOutput(); err != nil {
		log.Fatalf("%s %v", appName, err)
	}

	if quiet != true {
		log.Printf("%s Queue Depth: %v", appName, p.ParsedOutput.QueueLength)
	}

	statsite.SetGauge([]string{"passenger-queue-depth"}, float32(p.ParsedOutput.QueueLength))
}
<|endoftext|>


<commit_before>package main

import (
    "io/ioutil"
    "os"
    "os/exec"
    "strconv"
    "strings"
    "time"
    "github.com/fatih/color"
)

var (
    progPath string
    progName string
    testDir string
    ioStyle int
    isPython bool
)

func main() {
    initVars()

    // chdir to directory containing test cases
    os.Chdir(testDir)

    setIOStyle()

    i := 1

    if ioStyle == 1 {
        for {
            if _, err := os.Stat(strconv.Itoa(i) + ".in"); os.IsNotExist(err) {
                // TODO: Add number of total test cases passed
                color.White("Finished testing")
                os.Exit(0)
            }

            copyTestData(strconv.Itoa(i) + ".in")

            timeElapsed := runProgram()

            a := readOutput(progName + ".out")
            b := readOutput(strconv.Itoa(i) + ".out")

            if compareOutput(a, b) != -1 {
                color.Red("Wrong output for test case %d:\nExpected:\n%sFound:\n%s\n", i, string(b[:]), string(a[:]))
            } else {
                color.Green("Test case %d passed in %.3f seconds", i, timeElapsed.Seconds());
            }
            i++
        }
    } else if ioStyle == 2 {
        for {
            if _, err := os.Stat("I." + strconv.Itoa(i)); os.IsNotExist(err) {
                // TODO: Add number of total test cases passed
                color.White("Finished testing")
                os.Exit(0)
            }

            copyTestData("I." + strconv.Itoa(i))

            timeElapsed := runProgram()

            a := readOutput(progName + ".out")
            b := readOutput("O." + strconv.Itoa(i))

            if compareOutput(a, b) != -1 {
                color.Red("Wrong output for test case %d:\nExpected:\n%sFound:\n%s\n", i, string(b[:]), string(a[:]))
            } else {
                color.Green("Test case %d passed in %.3f seconds", i, timeElapsed.Seconds());
            }
            i++
        }

    }
}

func initVars() {
    numArgs := len(os.Args)
    if numArgs >= 2 {
        progPath = os.Args[1]
    } else {
        color.Red("Please specify program path as first argument")
        os.Exit(0)
    }

    if numArgs >= 3 {
        testDir = os.Args[2]
    } else {
        x, err := os.Getwd()
        if err != nil {
            color.Red("Error getting current working directory:\n" + err.Error())
            os.Exit(0)
        }
        testDir = x
    }

    progName = getProgName()

    if progName[len(progName) - 3:] == ".py" {
        isPython = true
        progName = progName[:len(progName) - 3]
    }
}

func getProgName() string {
    pos := strings.LastIndex(progPath, "/")
    if pos == -1 {
        pos = strings.LastIndex(progPath, "\\")
    }
    return progPath[pos + 1:]
}

func copyTestData(fileName string) {
    b, err := ioutil.ReadFile(fileName)
    if err != nil {
        panic(err)
    }

    err = ioutil.WriteFile(progName + ".in", b, 0644)
    if err != nil {
        panic(err)
    }
}

// if outputs are not same, return position of nonequivalence; otherwise return -1
func compareOutput(a, b []byte) int {
    fileLen := len(a)
    bLen := len(b)
    if fileLen != bLen {
        if fileLen > bLen {
            return fileLen - bLen
        }
        return bLen - fileLen
    }
    for i := 0; i < fileLen; i++ {
        if a[i] != b[i] {
            return i
        }
    }
    return -1
}

func readOutput(fileName string) []byte {
    b, err := ioutil.ReadFile(fileName)
    if err != nil {
        panic(err)
    }
    return b
}

// ioStyle 1 is of form "X.in"; ioStyle 2 is of form "I.X";
// TODO: Change function to check if list of files in "testDir" contains "X.in" or "I.X" files using regex
func setIOStyle() {
    if _, err := os.Stat("1.in"); err == nil {
        ioStyle = 1
        return
    } else if _, err = os.Stat("I.1"); err == nil {
        ioStyle = 2
        return
    }
    color.Red("Could not find test input/ouput files in " + testDir)
    os.Exit(0)
}

func runProgram() time.Duration {
    cmd := exec.Command(progPath)
    if isPython {
        // TODO: Think of fix for python command name on different OSes (python2, python3)
        cmd = exec.Command("python", progPath)
    }
    timeStart := time.Now()
    err := cmd.Run()
    timeEnd := time.Now()
    if err != nil {
        color.Red("Error running program:\n" + err.Error())
        os.Exit(0)
    }
    return timeEnd.Sub(timeStart)
}
<commit_msg>add error messages in output<commit_after>package main

import (
    "io/ioutil"
    "os"
    "os/exec"
    "strconv"
    "strings"
    "time"
    "github.com/fatih/color"
)

var (
    progPath string
    progName string
    testDir string
    ioStyle int
    isPython bool
)

func main() {
    initVars()

    // chdir to directory containing test cases
    os.Chdir(testDir)

    setIOStyle()

    i := 1

    if ioStyle == 1 {
        for {
            if _, err := os.Stat(strconv.Itoa(i) + ".in"); os.IsNotExist(err) {
                // TODO: Add number of total test cases passed
                color.White("Finished testing")
                os.Exit(0)
            }

            copyTestData(strconv.Itoa(i) + ".in")

            timeElapsed, err := runProgram()

            if err != nil {
                color.Red("Error executing test case %d\n%s\n", i, err.Error())
                i++
                continue
            }

            a := readOutput(progName + ".out")
            b := readOutput(strconv.Itoa(i) + ".out")

            if compareOutput(a, b) != -1 {
                color.Red("Wrong output for test case %d:\nExpected:\n%s\nFound:\n%s\n", i, string(b[:]), string(a[:]))
            } else {
                color.Green("Test case %d passed in %.3f seconds\n", i, timeElapsed.Seconds());
            }
            i++
        }
    } else if ioStyle == 2 {
        for {
            if _, err := os.Stat("I." + strconv.Itoa(i)); os.IsNotExist(err) {
                // TODO: Add number of total test cases passed
                color.White("Finished testing")
                os.Exit(0)
            }

            copyTestData("I." + strconv.Itoa(i))

            timeElapsed, err := runProgram()

            if err != nil {
                color.Red("Error executing test case %d\n%s\n", i, err.Error())
                i++
                continue
            }

            a := readOutput(progName + ".out")
            b := readOutput("O." + strconv.Itoa(i))

            if compareOutput(a, b) != -1 {
                color.Red("Wrong output for test case %d:\nExpected:\n%s\nFound:\n%s\n", i, string(b[:]), string(a[:]))
            } else {
                color.Green("Test case %d passed in %.3f seconds\n", i, timeElapsed.Seconds());
            }
            i++
        }

    }
}

func initVars() {
    numArgs := len(os.Args)
    if numArgs >= 2 {
        progPath = os.Args[1]
    } else {
        color.Red("Please specify program path as first argument")
        os.Exit(0)
    }

    if numArgs >= 3 {
        testDir = os.Args[2]
    } else {
        x, err := os.Getwd()
        if err != nil {
            color.Red("Error getting current working directory:\n" + err.Error())
            os.Exit(0)
        }
        testDir = x
    }

    progName = getProgName()

    if progName[len(progName) - 3:] == ".py" {
        isPython = true
        progName = progName[:len(progName) - 3]
    }
}

func getProgName() string {
    pos := strings.LastIndex(progPath, "/")
    if pos == -1 {
        pos = strings.LastIndex(progPath, "\\")
    }
    return progPath[pos + 1:]
}

func copyTestData(fileName string) {
    b, err := ioutil.ReadFile(fileName)
    if err != nil {
        panic(err)
    }

    err = ioutil.WriteFile(progName + ".in", b, 0644)
    if err != nil {
        panic(err)
    }
}

// if outputs are not same, return position of nonequivalence; otherwise return -1
func compareOutput(a, b []byte) int {
    fileLen := len(a)
    bLen := len(b)
    if fileLen != bLen {
        if fileLen > bLen {
            return fileLen - bLen
        }
        return bLen - fileLen
    }
    for i := 0; i < fileLen; i++ {
        if a[i] != b[i] {
            return i
        }
    }
    return -1
}

func readOutput(fileName string) []byte {
    b, err := ioutil.ReadFile(fileName)
    if err != nil {
        panic(err)
    }
    return b
}

// ioStyle 1 is of form "X.in"; ioStyle 2 is of form "I.X";
// TODO: Change function to check if list of files in "testDir" contains "X.in" or "I.X" files using regex
func setIOStyle() {
    if _, err := os.Stat("1.in"); err == nil {
        ioStyle = 1
        return
    } else if _, err = os.Stat("I.1"); err == nil {
        ioStyle = 2
        return
    }
    color.Red("Could not find test input/ouput files in " + testDir)
    os.Exit(0)
}

func runProgram() (time.Duration, error) {
    cmd := exec.Command(progPath)
    if isPython {
        // TODO: Think of fix for python command name on different OSes (python2, python3)
        cmd = exec.Command("python", progPath)
    }
    timeStart := time.Now()
    err := cmd.Run()
    timeEnd := time.Now()
    if err != nil {
        return -1, err
    }
    return timeEnd.Sub(timeStart), nil
}
<|endoftext|>


<commit_before>/*
gitlab-git-http-server handles 'smart' Git HTTP requests for GitLab

This HTTP server can service 'git clone', 'git push' etc. commands
from Git clients that use the 'smart' Git HTTP protocol (git-upload-pack
and git-receive-pack). It is intended to be deployed behind NGINX
(for request routing and SSL termination) with access to a GitLab
backend (for authentication and authorization) and local disk access
to Git repositories managed by GitLab.

This HTTP server replaces gitlab-grack.
*/
package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
)

type gitHandler struct {
	httpClient  *http.Client
	repoRoot    string
	authBackend string
}

type gitService struct {
	method     string
	suffix     string
	handleFunc func(gitEnv, string, string, http.ResponseWriter, *http.Request)
	rpc        string
}

type gitEnv struct {
	GL_ID string
}

var Version string // Set at build time in the Makefile

// Command-line options
var printVersion = flag.Bool("version", false, "Print version and exit")
var listenAddr = flag.String("listenAddr", "localhost:8181", "Listen address for HTTP server")
var listenNetwork = flag.String("listenNetwork", "tcp", "Listen 'network' (protocol)")
var listenUmask = flag.Int("listenUmask", 022, "Umask for Unix socket, default: 022")
var authBackend = flag.String("authBackend", "http://localhost:8080", "Authentication/authorization backend")

// Routing table
var gitServices = [...]gitService{
	gitService{"GET", "/info/refs", handleGetInfoRefs, ""},
	gitService{"POST", "/git-upload-pack", handlePostRPC, "git-upload-pack"},
	gitService{"POST", "/git-receive-pack", handlePostRPC, "git-receive-pack"},
}

func main() {
	// Parse the command-line
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\n  %s [OPTIONS] REPO_ROOT\n\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	if *printVersion {
		fmt.Printf("gitlab-git-http-server %s\n", Version)
		os.Exit(0)
	}
	repoRoot := flag.Arg(0)
	if repoRoot == "" {
		flag.Usage()
		os.Exit(1)
	}
	log.Printf("repoRoot: %s", repoRoot)

	// Good housekeeping for Unix sockets: unlink before binding
	if *listenNetwork == "unix" {
		if err := os.Remove(*listenAddr); err != nil && !os.IsNotExist(err) {
			log.Fatal(err)
		}
	}

	// Change the umask only around net.Listen()
	oldUmask := syscall.Umask(*listenUmask)
	listener, err := net.Listen(*listenNetwork, *listenAddr)
	syscall.Umask(oldUmask)
	if err != nil {
		log.Fatal(err)
	}

	http.Handle("/", newGitHandler(repoRoot, *authBackend))
	log.Fatal(http.Serve(listener, nil))
}

func newGitHandler(repoRoot, authBackend string) *gitHandler {
	return &gitHandler{&http.Client{}, repoRoot, authBackend}
}

func (h *gitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var env gitEnv
	var g gitService

	log.Print(r.Method, " ", r.URL)

	// Look for a matching Git service
	foundService := false
	for _, g = range gitServices {
		if r.Method == g.method && strings.HasSuffix(r.URL.Path, g.suffix) {
			foundService = true
			break
		}
	}
	if !foundService {
		// The protocol spec in git/Documentation/technical/http-protocol.txt
		// says we must return 403 if no matching service is found.
		http.Error(w, "Forbidden", 403)
		return
	}

	// Ask the auth backend if the request is allowed, and what the
	// user ID (GL_ID) is.
	authResponse, err := h.doAuthRequest(r)
	if err != nil {
		fail500(w, err)
		return
	}
	defer authResponse.Body.Close()

	if authResponse.StatusCode != 200 {
		// The Git request is not allowed by the backend. Maybe the
		// client needs to send HTTP Basic credentials.  Forward the
		// response from the auth backend to our client. This includes
		// the 'WWW-Authentication' header that acts as a hint that
		// Basic auth credentials are needed.
		for k, v := range authResponse.Header {
			w.Header()[k] = v
		}
		w.WriteHeader(authResponse.StatusCode)
		io.Copy(w, authResponse.Body)
		return
	}

	// The auth backend validated the client request and told us who
	// the user is according to them (GL_ID). We must extract this
	// information from the auth response body.
	dec := json.NewDecoder(authResponse.Body)
	if err := dec.Decode(&env); err != nil {
		fail500(w, err)
		return
	}
	// Don't hog a TCP connection in CLOSE_WAIT, we can already close it now
	authResponse.Body.Close()

	// About path traversal: the Go net/http HTTP server, or
	// rather ServeMux, makes the following promise: "ServeMux
	// also takes care of sanitizing the URL request path, redirecting
	// any request containing . or .. elements to an equivalent
	// .- and ..-free URL.". In other words, we may assume that
	// r.URL.Path does not contain '/../', so there is no possibility
	// of path traversal here.
	repoPath := path.Join(h.repoRoot, strings.TrimSuffix(r.URL.Path, g.suffix))
	if !looksLikeRepo(repoPath) {
		http.Error(w, "Not Found", 404)
		return
	}

	g.handleFunc(env, g.rpc, repoPath, w, r)
}

func looksLikeRepo(p string) bool {
	// If /path/to/foo.git/objects exists then let's assume it is a valid Git
	// repository.
	if _, err := os.Stat(path.Join(p, "objects")); err != nil {
		log.Print(err)
		return false
	}
	return true
}

func (h *gitHandler) doAuthRequest(r *http.Request) (result *http.Response, err error) {
	url := h.authBackend + r.URL.RequestURI()
	authReq, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	// Forward all headers from our client to the auth backend. This includes
	// HTTP Basic authentication credentials (the 'Authorization' header).
	for k, v := range r.Header {
		authReq.Header[k] = v
	}
	return h.httpClient.Do(authReq)
}

func handleGetInfoRefs(env gitEnv, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	if !(rpc == "git-upload-pack" || rpc == "git-receive-pack") {
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not Found", 404)
		return
	}

	// Prepare our Git subprocess
	cmd := gitCommand(env, "git", subCommand(rpc), "--stateless-rpc", "--advertise-refs", path)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
	w.Header().Add("Cache-Control", "no-cache")
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if err := pktLine(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
		panic(err)
	}
	if err := pktFlush(w); err != nil {
		panic(err)
	}
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func handlePostRPC(env gitEnv, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	// The client request body may have been gzipped.
	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail500(w, err)
			return
		}
	} else {
		body = r.Body
	}

	// Prepare our Git subprocess
	cmd := gitCommand(env, "git", subCommand(rpc), "--stateless-rpc", path)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdin.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up

	// Write the client request body to Git's standard input
	if _, err := io.Copy(stdin, body); err != nil {
		fail500(w, err)
		return
	}
	stdin.Close()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	w.Header().Add("Cache-Control", "no-cache")
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func fail500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

// Git subprocess helpers
func subCommand(rpc string) string {
	return strings.TrimPrefix(rpc, "git-")
}

func gitCommand(env gitEnv, name string, args ...string) *exec.Cmd {
	cmd := exec.Command(name, args...)
	// Start the command in its own process group (nice for signalling)
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	// Explicitly set the environment for the Git command
	cmd.Env = []string{
		fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		fmt.Sprintf("GL_ID=%s", env.GL_ID),
	}
	return cmd
}

func cleanUpProcessGroup(cmd *exec.Cmd) {
	if cmd == nil {
		return
	}

	process := cmd.Process
	if process != nil && process.Pid > 0 {
		// Send SIGKILL (kill -9) to the process group of cmd
		syscall.Kill(-process.Pid, syscall.SIGKILL)
	}

	// reap our child process
	cmd.Wait()
}

// Git HTTP line protocol functions
func pktLine(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pktFlush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}
<commit_msg>We only use flags in the main function<commit_after>/*
gitlab-git-http-server handles 'smart' Git HTTP requests for GitLab

This HTTP server can service 'git clone', 'git push' etc. commands
from Git clients that use the 'smart' Git HTTP protocol (git-upload-pack
and git-receive-pack). It is intended to be deployed behind NGINX
(for request routing and SSL termination) with access to a GitLab
backend (for authentication and authorization) and local disk access
to Git repositories managed by GitLab.

This HTTP server replaces gitlab-grack.
*/
package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
)

type gitHandler struct {
	httpClient  *http.Client
	repoRoot    string
	authBackend string
}

type gitService struct {
	method     string
	suffix     string
	handleFunc func(gitEnv, string, string, http.ResponseWriter, *http.Request)
	rpc        string
}

type gitEnv struct {
	GL_ID string
}

var Version string // Set at build time in the Makefile

// Routing table
var gitServices = [...]gitService{
	gitService{"GET", "/info/refs", handleGetInfoRefs, ""},
	gitService{"POST", "/git-upload-pack", handlePostRPC, "git-upload-pack"},
	gitService{"POST", "/git-receive-pack", handlePostRPC, "git-receive-pack"},
}

func main() {
	printVersion := flag.Bool("version", false, "Print version and exit")
	listenAddr := flag.String("listenAddr", "localhost:8181", "Listen address for HTTP server")
	listenNetwork := flag.String("listenNetwork", "tcp", "Listen 'network' (protocol)")
	listenUmask := flag.Int("listenUmask", 022, "Umask for Unix socket, default: 022")
	authBackend := flag.String("authBackend", "http://localhost:8080", "Authentication/authorization backend")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\n  %s [OPTIONS] REPO_ROOT\n\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	if *printVersion {
		fmt.Printf("gitlab-git-http-server %s\n", Version)
		os.Exit(0)
	}

	repoRoot := flag.Arg(0)
	if repoRoot == "" {
		flag.Usage()
		os.Exit(1)
	}
	log.Printf("repoRoot: %s", repoRoot)

	// Good housekeeping for Unix sockets: unlink before binding
	if *listenNetwork == "unix" {
		if err := os.Remove(*listenAddr); err != nil && !os.IsNotExist(err) {
			log.Fatal(err)
		}
	}

	// Change the umask only around net.Listen()
	oldUmask := syscall.Umask(*listenUmask)
	listener, err := net.Listen(*listenNetwork, *listenAddr)
	syscall.Umask(oldUmask)
	if err != nil {
		log.Fatal(err)
	}

	http.Handle("/", newGitHandler(repoRoot, *authBackend))
	log.Fatal(http.Serve(listener, nil))
}

func newGitHandler(repoRoot, authBackend string) *gitHandler {
	return &gitHandler{&http.Client{}, repoRoot, authBackend}
}

func (h *gitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var env gitEnv
	var g gitService

	log.Print(r.Method, " ", r.URL)

	// Look for a matching Git service
	foundService := false
	for _, g = range gitServices {
		if r.Method == g.method && strings.HasSuffix(r.URL.Path, g.suffix) {
			foundService = true
			break
		}
	}
	if !foundService {
		// The protocol spec in git/Documentation/technical/http-protocol.txt
		// says we must return 403 if no matching service is found.
		http.Error(w, "Forbidden", 403)
		return
	}

	// Ask the auth backend if the request is allowed, and what the
	// user ID (GL_ID) is.
	authResponse, err := h.doAuthRequest(r)
	if err != nil {
		fail500(w, err)
		return
	}
	defer authResponse.Body.Close()

	if authResponse.StatusCode != 200 {
		// The Git request is not allowed by the backend. Maybe the
		// client needs to send HTTP Basic credentials.  Forward the
		// response from the auth backend to our client. This includes
		// the 'WWW-Authentication' header that acts as a hint that
		// Basic auth credentials are needed.
		for k, v := range authResponse.Header {
			w.Header()[k] = v
		}
		w.WriteHeader(authResponse.StatusCode)
		io.Copy(w, authResponse.Body)
		return
	}

	// The auth backend validated the client request and told us who
	// the user is according to them (GL_ID). We must extract this
	// information from the auth response body.
	dec := json.NewDecoder(authResponse.Body)
	if err := dec.Decode(&env); err != nil {
		fail500(w, err)
		return
	}
	// Don't hog a TCP connection in CLOSE_WAIT, we can already close it now
	authResponse.Body.Close()

	// About path traversal: the Go net/http HTTP server, or
	// rather ServeMux, makes the following promise: "ServeMux
	// also takes care of sanitizing the URL request path, redirecting
	// any request containing . or .. elements to an equivalent
	// .- and ..-free URL.". In other words, we may assume that
	// r.URL.Path does not contain '/../', so there is no possibility
	// of path traversal here.
	repoPath := path.Join(h.repoRoot, strings.TrimSuffix(r.URL.Path, g.suffix))
	if !looksLikeRepo(repoPath) {
		http.Error(w, "Not Found", 404)
		return
	}

	g.handleFunc(env, g.rpc, repoPath, w, r)
}

func looksLikeRepo(p string) bool {
	// If /path/to/foo.git/objects exists then let's assume it is a valid Git
	// repository.
	if _, err := os.Stat(path.Join(p, "objects")); err != nil {
		log.Print(err)
		return false
	}
	return true
}

func (h *gitHandler) doAuthRequest(r *http.Request) (result *http.Response, err error) {
	url := h.authBackend + r.URL.RequestURI()
	authReq, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	// Forward all headers from our client to the auth backend. This includes
	// HTTP Basic authentication credentials (the 'Authorization' header).
	for k, v := range r.Header {
		authReq.Header[k] = v
	}
	return h.httpClient.Do(authReq)
}

func handleGetInfoRefs(env gitEnv, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	if !(rpc == "git-upload-pack" || rpc == "git-receive-pack") {
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not Found", 404)
		return
	}

	// Prepare our Git subprocess
	cmd := gitCommand(env, "git", subCommand(rpc), "--stateless-rpc", "--advertise-refs", path)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
	w.Header().Add("Cache-Control", "no-cache")
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if err := pktLine(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
		panic(err)
	}
	if err := pktFlush(w); err != nil {
		panic(err)
	}
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func handlePostRPC(env gitEnv, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	// The client request body may have been gzipped.
	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail500(w, err)
			return
		}
	} else {
		body = r.Body
	}

	// Prepare our Git subprocess
	cmd := gitCommand(env, "git", subCommand(rpc), "--stateless-rpc", path)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdin.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up

	// Write the client request body to Git's standard input
	if _, err := io.Copy(stdin, body); err != nil {
		fail500(w, err)
		return
	}
	stdin.Close()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	w.Header().Add("Cache-Control", "no-cache")
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func fail500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

// Git subprocess helpers
func subCommand(rpc string) string {
	return strings.TrimPrefix(rpc, "git-")
}

func gitCommand(env gitEnv, name string, args ...string) *exec.Cmd {
	cmd := exec.Command(name, args...)
	// Start the command in its own process group (nice for signalling)
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	// Explicitly set the environment for the Git command
	cmd.Env = []string{
		fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		fmt.Sprintf("GL_ID=%s", env.GL_ID),
	}
	return cmd
}

func cleanUpProcessGroup(cmd *exec.Cmd) {
	if cmd == nil {
		return
	}

	process := cmd.Process
	if process != nil && process.Pid > 0 {
		// Send SIGKILL (kill -9) to the process group of cmd
		syscall.Kill(-process.Pid, syscall.SIGKILL)
	}

	// reap our child process
	cmd.Wait()
}

// Git HTTP line protocol functions
func pktLine(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pktFlush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/sha1"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"sync"
)

// Filter reads a sequence of strings from a channel and produces a
// sequence on another channel.  Many implementations of Filter are
// provided.
type Filter func(<-chan string, chan<- string)

// Each() returns a channel that contains all output emitted by a
// sequence of filters. The sequence of filters is fed an empty stream
// as the input.
func Each(filters ...Filter) <-chan string {
	in := make(chan string, 0)
	close(in) // No data sent to first filter
	out := make(chan string, 10000)
	go runAndClose(Sequence(filters...), in, out)
	return out
}

func Sequence(filters ...Filter) Filter {
	return func(in <-chan string, out chan<- string) {
		if len(filters) == 0 {
			copydata(in, out)
			return
		}
		for i, f := range filters {
			if i < len(filters)-1 {
				c := make(chan string, 10000)
				go runAndClose(f, in, c)
				in = c
			} else {
				go runAndClose(f, in, out)
			}
		}
	}
}

// Print prints all output emitted by a sequence of filters. The
// sequence of filters is fed an empty stream as the input.
func Print(filters ...Filter) {
	for s := range Each(filters...) {
		fmt.Println(s)
	}
}

func runAndClose(f Filter, in <-chan string, out chan<- string) {
	f(in, out)
	close(out)
}

// copydata copies all items read from in to out.
func copydata(in <-chan string, out chan<- string) {
	for s := range in {
		out <- s
	}
}

// Echo copies its input and then emits item.
func Echo(items ...string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for _, s := range items {
			out <- s
		}
	}
}

// Numbers copies its input and then emits the integers x..y
func Numbers(x, y int) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for i := x; i <= y; i++ {
			out <- fmt.Sprintf("%d", i)
		}
	}
}

// If emits every input x for which fn(x) is true.
func If(fn func(string) bool) Filter {
	return func(in <-chan string, out chan<- string) {
		for s := range in {
			if fn(s) {
				out <- s
			}
		}
	}
}

// Grep emits every input x that matches the regular expression r.
func Grep(r string) Filter {
	re := regexp.MustCompile(r)
	return If(re.MatchString)
}

// GrepNot emits every input x that does not match the regular expression r.
func GrepNot(r string) Filter {
	re := regexp.MustCompile(r)
	return If(func(s string) bool { return !re.MatchString(s) })
}

// Uniq squashes adjacent identical items in in into a single output.
func Uniq(in <-chan string, out chan<- string) {
	first := true
	last := ""
	for s := range in {
		if first || last != s {
			out <- s
		}
		last = s
		first = false
	}
}

// UniqWithCount squashes adjacent identical items in in into a single
// output prefixed with the count of identical items.
func UniqWithCount(in <-chan string, out chan<- string) {
	current := ""
	count := 0
	for s := range in {
		if s != current {
			if count > 0 {
				out <- fmt.Sprintf("%d %s", count, current)
			}
			count = 0
			current = s
		}
		count++
	}
	if count > 0 {
		out <- fmt.Sprintf("%d %s", count, current)
	}
}

// Apply calls fn(x, out) in order for every item x.
func Apply(fn func(string, chan<- string)) Filter {
	return func(in <-chan string, out chan<- string) {
		for s := range in {
			fn(s, out)
		}
	}
}

// ApplyParallel calls fn(x, out) for every item x in a pool of n goroutines.
func ApplyParallel(n int, fn func(string, chan<- string)) Filter {
	// TODO: Maintain input order?
	// (a) Input goroutine generates <index, str> pairs
	// (b) n appliers read pairs and produce <index, fn(str)> pairs
	// (c) Output goroutine reads and emits in order
	return func(in <-chan string, out chan<- string) {
		wg := &sync.WaitGroup{}
		wg.Add(n)
		for i := 0; i < n; i++ {
			go func() {
				for s := range in {
					fn(s, out)
				}
				wg.Done()
			}()
		}
		wg.Wait()
	}
}

func ReplaceMatch(r, replacement string) Filter {
	re := regexp.MustCompile(r)
	return Apply(func(s string, out chan<- string) {
		out <- re.ReplaceAllString(s, replacement)
	})
}

func DeleteMatch(r string) Filter {
	return ReplaceMatch(r, "")
}

func Sort(in <-chan string, out chan<- string) {
	var data []string
	for s := range in {
		data = append(data, s)
	}
	sort.Strings(data)
	for _, s := range data {
		out <- s
	}
}

type fnStringSlice struct {
	sort.StringSlice
	fn func(string, string) bool
}

func (fs fnStringSlice) Less(i, j int) bool {
	return fs.fn(fs.StringSlice[i], fs.StringSlice[j])
}

func SortBy(fn func(string, string) bool) Filter {
	return func(in <-chan string, out chan<- string) {
		var data fnStringSlice
		data.fn = fn
		for s := range in {
			data.StringSlice = append(data.StringSlice, s)
		}
		sort.Sort(data)
		for _, s := range data.StringSlice {
			out <- s
		}
	}
}

func SortNumeric(column int) Filter {
	toNum := func(s string) (int, int64) {
		r := regexp.MustCompile(`\s+`).Split(s, -1)
		for len(r) > 0 && r[0] == "" {
			r = r[1:]
		}
		for len(r) > 0 && r[len(r)-1] == "" {
			r = r[:len(r)-1]
		}
		if len(r) <= column {
			// Missing data is sorted before all numbers
			return -1, 0
		}
		x, err := strconv.ParseInt(r[column], 0, 64)
		if err != nil {
			// Bad data is sorted after all numbers
			return +1, 0
		}
		return 0, x
	}
	return SortBy(func(a, b string) bool {
		a1, a2 := toNum(a)
		b1, b2 := toNum(b)
		if a1 != b1 {
			return a1 < b1
		}
		return a2 < b2
	})
}

func Reverse(in <-chan string, out chan<- string) {
	var data []string
	for s := range in {
		data = append(data, s)
	}
	for i := len(data) - 1; i >= 0; i-- {
		out <- data[i]
	}
}

type FindType int

const (
	FILES    FindType = 1
	DIRS     FindType = 2
	SYMLINKS FindType = 4
	ALL      FindType = FILES | DIRS | SYMLINKS
)

func Find(ft FindType, dir string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		filepath.Walk(dir, func(f string, s os.FileInfo, e error) error {
			if ft&FILES != 0 && s.Mode().IsRegular() ||
				ft&DIRS != 0 && s.Mode().IsDir() ||
				ft&SYMLINKS != 0 && s.Mode()&os.ModeSymlink != 0 {
				out <- f
			}
			return nil
		})
	}
}

func Cat(filenames ...string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for _, f := range filenames {
			file, err := os.Open(f)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
			scanner := bufio.NewScanner(file)
			for scanner.Scan() {
				out <- scanner.Text()
			}
			file.Close()
		}
	}
}

func First(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		emitted := 0
		for s := range in {
			if emitted < n {
				out <- s
				emitted++
			}
		}
	}
}

func DropFirst(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		emitted := 0
		for s := range in {
			if emitted >= n {
				out <- s
			}
			emitted++
		}
	}
}

func Last(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		var buf []string
		for s := range in {
			buf = append(buf, s)
			if len(buf) > n {
				buf = buf[1:]
			}
		}
		for _, s := range buf {
			out <- s
		}
	}
}

func DropLast(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		var buf []string
		for s := range in {
			buf = append(buf, s)
			if len(buf) > n {
				out <- buf[0]
				buf = buf[1:]
			}
		}
	}
}

func NumberLines(in <-chan string, out chan<- string) {
	line := 1
	for s := range in {
		out <- fmt.Sprintf("%5d %s", line, s)
		line++
	}
}

func Cut(start, end int) Filter {
	return Apply(func(s string, out chan<- string) {
		if len(s) > end {
			s = s[:end+1]
		}
		if len(s) < start {
			s = ""
		} else {
			s = s[start:]
		}
		out <- s
	})
}

func main() {
	dbl := func(in <-chan string, out chan<- string) {
		for s := range in {
			out <- s
			out <- s
		}
	}

	hash := func(f string, out chan<- string) {
		file, err := os.Open(f)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		hasher := sha1.New()
		_, err = io.Copy(hasher, file)
		file.Close()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		out <- fmt.Sprintf("%x %s", hasher.Sum(nil), f)
	}

	Print(Sequence())
	Print(Sequence(Echo("1 of 1")))
	Print(Sequence(Echo("1 of 2"), Echo("2 of 2")))

	Print(Numbers(1, 100),
		Grep("3"),
		GrepNot("7"),
		dbl,
		Uniq,
		ReplaceMatch("^(.)$", "x$1"),
		Sort,
		ReplaceMatch("^(.)", "$1 "),
		dbl,
		DeleteMatch(" .$"),
		UniqWithCount,
		SortNumeric(1),
		Reverse,
		Echo("==="))

	Print(Find(FILES, "/home/sanjay/tmp"),
		Grep("/tmp/x"),
		GrepNot("/sub2/"),
		ApplyParallel(4, hash),
		ReplaceMatch(" /home/sanjay/", " HOME/"))

	Print(Echo("a"), Echo("b"), Echo("c"))

	Print(Cat("/home/sanjay/.bashrc"),
		First(10),
		NumberLines,
		Cut(1, 50),
		ReplaceMatch("^", "LINE:"),
		Last(3))

	Print(Numbers(1, 10), DropFirst(8))
	Print(Numbers(1, 10), DropLast(7))

	Print(Echo("=== all ==="), Find(ALL, "/home/sanjay/tmp/x"))
	Print(Echo("=== dirs ==="), Find(FILES, "/home/sanjay/tmp/x"))
	Print(Echo("=== files ==="), Find(DIRS, "/home/sanjay/tmp/x"))

	// Reconcile part 1
	Print(Echo("------------"))
	Print(
		Find(FILES, "/home/sanjay/tmp/y"),
		ApplyParallel(4, hash),
	)
}
<commit_msg>checkpoint<commit_after>package main

import (
	"bufio"
	"crypto/sha1"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"sync"
)

// Filter reads a sequence of strings from a channel and produces a
// sequence on another channel.  Many implementations of Filter are
// provided.
type Filter func(<-chan string, chan<- string)

// Each() returns a channel that contains all output emitted by a
// sequence of filters. The sequence of filters is fed an empty stream
// as the input.
func Each(filters ...Filter) <-chan string {
	in := make(chan string, 0)
	close(in) // No data sent to first filter
	out := make(chan string, 10000)
	go runAndClose(Sequence(filters...), in, out)
	return out
}

func Sequence(filters ...Filter) Filter {
	return func(in <-chan string, out chan<- string) {
		for _, f := range filters {
			c := make(chan string, 10000)
			go runAndClose(f, in, c)
			in = c
		}
		copydata(in, out)
	}
}

// Print prints all output emitted by a sequence of filters. The
// sequence of filters is fed an empty stream as the input.
func Print(filters ...Filter) {
	for s := range Each(filters...) {
		fmt.Println(s)
	}
}

func runAndClose(f Filter, in <-chan string, out chan<- string) {
	f(in, out)
	close(out)
}

// copydata copies all items read from in to out.
func copydata(in <-chan string, out chan<- string) {
	for s := range in {
		out <- s
	}
}

// Echo copies its input and then emits item.
func Echo(items ...string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for _, s := range items {
			out <- s
		}
	}
}

// Numbers copies its input and then emits the integers x..y
func Numbers(x, y int) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for i := x; i <= y; i++ {
			out <- fmt.Sprintf("%d", i)
		}
	}
}

// If emits every input x for which fn(x) is true.
func If(fn func(string) bool) Filter {
	return func(in <-chan string, out chan<- string) {
		for s := range in {
			if fn(s) {
				out <- s
			}
		}
	}
}

// Grep emits every input x that matches the regular expression r.
func Grep(r string) Filter {
	re := regexp.MustCompile(r)
	return If(re.MatchString)
}

// GrepNot emits every input x that does not match the regular expression r.
func GrepNot(r string) Filter {
	re := regexp.MustCompile(r)
	return If(func(s string) bool { return !re.MatchString(s) })
}

// Uniq squashes adjacent identical items in in into a single output.
func Uniq(in <-chan string, out chan<- string) {
	first := true
	last := ""
	for s := range in {
		if first || last != s {
			out <- s
		}
		last = s
		first = false
	}
}

// UniqWithCount squashes adjacent identical items in in into a single
// output prefixed with the count of identical items.
func UniqWithCount(in <-chan string, out chan<- string) {
	current := ""
	count := 0
	for s := range in {
		if s != current {
			if count > 0 {
				out <- fmt.Sprintf("%d %s", count, current)
			}
			count = 0
			current = s
		}
		count++
	}
	if count > 0 {
		out <- fmt.Sprintf("%d %s", count, current)
	}
}

// Apply calls fn(x, out) in order for every item x.
func Apply(fn func(string, chan<- string)) Filter {
	return func(in <-chan string, out chan<- string) {
		for s := range in {
			fn(s, out)
		}
	}
}

// ApplyParallel calls fn(x, out) for every item x in a pool of n goroutines.
func ApplyParallel(n int, fn func(string, chan<- string)) Filter {
	// TODO: Maintain input order?
	// (a) Input goroutine generates <index, str> pairs
	// (b) n appliers read pairs and produce <index, fn(str)> pairs
	// (c) Output goroutine reads and emits in order
	return func(in <-chan string, out chan<- string) {
		wg := &sync.WaitGroup{}
		wg.Add(n)
		for i := 0; i < n; i++ {
			go func() {
				for s := range in {
					fn(s, out)
				}
				wg.Done()
			}()
		}
		wg.Wait()
	}
}

func ReplaceMatch(r, replacement string) Filter {
	re := regexp.MustCompile(r)
	return Apply(func(s string, out chan<- string) {
		out <- re.ReplaceAllString(s, replacement)
	})
}

func DeleteMatch(r string) Filter {
	return ReplaceMatch(r, "")
}

func Sort(in <-chan string, out chan<- string) {
	var data []string
	for s := range in {
		data = append(data, s)
	}
	sort.Strings(data)
	for _, s := range data {
		out <- s
	}
}

type fnStringSlice struct {
	sort.StringSlice
	fn func(string, string) bool
}

func (fs fnStringSlice) Less(i, j int) bool {
	return fs.fn(fs.StringSlice[i], fs.StringSlice[j])
}

func SortBy(fn func(string, string) bool) Filter {
	return func(in <-chan string, out chan<- string) {
		var data fnStringSlice
		data.fn = fn
		for s := range in {
			data.StringSlice = append(data.StringSlice, s)
		}
		sort.Sort(data)
		for _, s := range data.StringSlice {
			out <- s
		}
	}
}

func SortNumeric(column int) Filter {
	toNum := func(s string) (int, int64) {
		r := regexp.MustCompile(`\s+`).Split(s, -1)
		for len(r) > 0 && r[0] == "" {
			r = r[1:]
		}
		for len(r) > 0 && r[len(r)-1] == "" {
			r = r[:len(r)-1]
		}
		if len(r) <= column {
			// Missing data is sorted before all numbers
			return -1, 0
		}
		x, err := strconv.ParseInt(r[column], 0, 64)
		if err != nil {
			// Bad data is sorted after all numbers
			return +1, 0
		}
		return 0, x
	}
	return SortBy(func(a, b string) bool {
		a1, a2 := toNum(a)
		b1, b2 := toNum(b)
		if a1 != b1 {
			return a1 < b1
		}
		return a2 < b2
	})
}

func Reverse(in <-chan string, out chan<- string) {
	var data []string
	for s := range in {
		data = append(data, s)
	}
	for i := len(data) - 1; i >= 0; i-- {
		out <- data[i]
	}
}

type FindType int

const (
	FILES    FindType = 1
	DIRS     FindType = 2
	SYMLINKS FindType = 4
	ALL      FindType = FILES | DIRS | SYMLINKS
)

func Find(ft FindType, dir string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		filepath.Walk(dir, func(f string, s os.FileInfo, e error) error {
			if ft&FILES != 0 && s.Mode().IsRegular() ||
				ft&DIRS != 0 && s.Mode().IsDir() ||
				ft&SYMLINKS != 0 && s.Mode()&os.ModeSymlink != 0 {
				out <- f
			}
			return nil
		})
	}
}

func Cat(filenames ...string) Filter {
	return func(in <-chan string, out chan<- string) {
		copydata(in, out)
		for _, f := range filenames {
			file, err := os.Open(f)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
			scanner := bufio.NewScanner(file)
			for scanner.Scan() {
				out <- scanner.Text()
			}
			file.Close()
		}
	}
}

func First(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		emitted := 0
		for s := range in {
			if emitted < n {
				out <- s
				emitted++
			}
		}
	}
}

func DropFirst(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		emitted := 0
		for s := range in {
			if emitted >= n {
				out <- s
			}
			emitted++
		}
	}
}

func Last(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		var buf []string
		for s := range in {
			buf = append(buf, s)
			if len(buf) > n {
				buf = buf[1:]
			}
		}
		for _, s := range buf {
			out <- s
		}
	}
}

func DropLast(n int) Filter {
	return func(in <-chan string, out chan<- string) {
		var buf []string
		for s := range in {
			buf = append(buf, s)
			if len(buf) > n {
				out <- buf[0]
				buf = buf[1:]
			}
		}
	}
}

func NumberLines(in <-chan string, out chan<- string) {
	line := 1
	for s := range in {
		out <- fmt.Sprintf("%5d %s", line, s)
		line++
	}
}

func Cut(start, end int) Filter {
	return Apply(func(s string, out chan<- string) {
		if len(s) > end {
			s = s[:end+1]
		}
		if len(s) < start {
			s = ""
		} else {
			s = s[start:]
		}
		out <- s
	})
}

func main() {
	dbl := func(in <-chan string, out chan<- string) {
		for s := range in {
			out <- s
			out <- s
		}
	}

	hash := func(f string, out chan<- string) {
		file, err := os.Open(f)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		hasher := sha1.New()
		_, err = io.Copy(hasher, file)
		file.Close()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		out <- fmt.Sprintf("%x %s", hasher.Sum(nil), f)
	}

	Print(Sequence())
	Print(Sequence(Echo("1 of 1")))
	Print(Sequence(Echo("1 of 2"), Echo("2 of 2")))

	Print(Numbers(1, 100),
		Grep("3"),
		GrepNot("7"),
		dbl,
		Uniq,
		ReplaceMatch("^(.)$", "x$1"),
		Sort,
		ReplaceMatch("^(.)", "$1 "),
		dbl,
		DeleteMatch(" .$"),
		UniqWithCount,
		SortNumeric(1),
		Reverse,
		Echo("==="))

	Print(Find(FILES, "/home/sanjay/tmp"),
		Grep("/tmp/x"),
		GrepNot("/sub2/"),
		ApplyParallel(4, hash),
		ReplaceMatch(" /home/sanjay/", " HOME/"))

	Print(Echo("a"), Echo("b"), Echo("c"))

	Print(Cat("/home/sanjay/.bashrc"),
		First(10),
		NumberLines,
		Cut(1, 50),
		ReplaceMatch("^", "LINE:"),
		Last(3))

	Print(Numbers(1, 10), DropFirst(8))
	Print(Numbers(1, 10), DropLast(7))

	Print(Echo("=== all ==="), Find(ALL, "/home/sanjay/tmp/x"))
	Print(Echo("=== dirs ==="), Find(FILES, "/home/sanjay/tmp/x"))
	Print(Echo("=== files ==="), Find(DIRS, "/home/sanjay/tmp/x"))

	// Reconcile part 1
	Print(Echo("------------"))
	Print(
		Find(FILES, "/home/sanjay/tmp/y"),
		ApplyParallel(4, hash),
	)
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/Sirupsen/logrus"
	vc "github.com/containers/virtcontainers"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

// name holds the name of this program
const name = "cc-runtime"

// version is the runtime version. It is be specified at compilation time (see
// Makefile).
var version = ""

// commit is the git commit the runtime is compiled from. It is specified at
// compilation time (see Makefile)
var commit = ""

// specConfig is the name of the file holding the containers configuration
const specConfig = "config.json"

const usage = `Clear Containers runtime

cc-runtime is a command line program for running applications packaged
according to the Open Container Initiative (OCI).`

var ccLog = logrus.New()

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = usage

	v := make([]string, 0, 3)
	if version != "" {
		v = append(v, "runtime  : "+version)
	}
	if commit != "" {
		v = append(v, "   commit   : "+commit)
	}
	v = append(v, "   OCI specs: "+specs.Version)
	app.Version = strings.Join(v, "\n")

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for logging",
		},
		cli.StringFlag{
			Name:  "log",
			Value: "/dev/null",
			Usage: "set the log file path where internal debug information is written",
		},
		cli.StringFlag{
			Name:  "log-format",
			Value: "text",
			Usage: "set the format used by logs ('text' (default), or 'json')",
		},
		cli.StringFlag{
			Name:  "root",
			Value: "/run/clear-containers",
			Usage: "root directory for storage of container state (this should be located in tmpfs)",
		},
	}

	app.Commands = []cli.Command{
		createCommand,
		deleteCommand,
		execCommand,
		killCommand,
		runCommand,
		startCommand,
		stateCommand,
	}

	app.Before = func(context *cli.Context) error {
		if context.NArg() == 0 ||
			(context.NArg() == 1 && context.Args()[0] == "help") {
			// No setup required if the user just
			// wants to see the usage statement.
			return nil
		}

		if context.GlobalBool("debug") {
			ccLog.Level = logrus.DebugLevel
		}
		if path := context.GlobalString("log"); path != "" {
			f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0640)
			if err != nil {
				return err
			}
			ccLog.Out = f
		}

		switch context.GlobalString("log-format") {
		case "text":
			// retain logrus's default.
		case "json":
			ccLog.Formatter = new(logrus.JSONFormatter)
		default:
			return fmt.Errorf("unknown log-format %q", context.GlobalString("log-format"))
		}

		// Set virtcontainers logger.
		vc.SetLog(ccLog)

		runtimeConfig, err := loadConfiguration("")
		if err != nil {
			return err
		}

		ccLog.Infof("%v (version %v, commit %v) called as: %v", name, version, commit, context.Args())

		// make the data accessible to the sub-commands.
		context.App.Metadata = map[string]interface{}{
			"runtimeConfig": runtimeConfig,
		}

		return nil
	}

	// If the command returns an error, cli takes upon itself to print
	// the error on cli.ErrWriter and exit.
	// Use our own writer here to ensure the log gets sent to the right
	// location.
	cli.ErrWriter = &fatalWriter{cli.ErrWriter}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// fatal prints the error's details exits the program.
func fatal(err error) {
	ccLog.Error(err)
	fmt.Fprintln(os.Stderr, err)
	os.Exit(1)
}

type fatalWriter struct {
	cliErrWriter io.Writer
}

func (f *fatalWriter) Write(p []byte) (n int, err error) {
	ccLog.Error(string(p))
	return f.cliErrWriter.Write(p)
}
<commit_msg>main: Define default root as variable.<commit_after>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/Sirupsen/logrus"
	vc "github.com/containers/virtcontainers"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

// name holds the name of this program
const name = "cc-runtime"

// version is the runtime version. It is be specified at compilation time (see
// Makefile).
var version = ""

// commit is the git commit the runtime is compiled from. It is specified at
// compilation time (see Makefile)
var commit = ""

// specConfig is the name of the file holding the containers configuration
const specConfig = "config.json"

const usage = `Clear Containers runtime

cc-runtime is a command line program for running applications packaged
according to the Open Container Initiative (OCI).`

var defaultRootdirectory = "/run/clear-containers"

var ccLog = logrus.New()

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = usage

	v := make([]string, 0, 3)
	if version != "" {
		v = append(v, "runtime  : "+version)
	}
	if commit != "" {
		v = append(v, "   commit   : "+commit)
	}
	v = append(v, "   OCI specs: "+specs.Version)
	app.Version = strings.Join(v, "\n")

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for logging",
		},
		cli.StringFlag{
			Name:  "log",
			Value: "/dev/null",
			Usage: "set the log file path where internal debug information is written",
		},
		cli.StringFlag{
			Name:  "log-format",
			Value: "text",
			Usage: "set the format used by logs ('text' (default), or 'json')",
		},
		cli.StringFlag{
			Name:  "root",
			Value: defaultRootDirectory,
			Usage: "root directory for storage of container state (this should be located in tmpfs)",
		},
	}

	app.Commands = []cli.Command{
		createCommand,
		deleteCommand,
		execCommand,
		killCommand,
		runCommand,
		startCommand,
		stateCommand,
	}

	app.Before = func(context *cli.Context) error {
		if context.NArg() == 0 ||
			(context.NArg() == 1 && context.Args()[0] == "help") {
			// No setup required if the user just
			// wants to see the usage statement.
			return nil
		}

		if context.GlobalBool("debug") {
			ccLog.Level = logrus.DebugLevel
		}
		if path := context.GlobalString("log"); path != "" {
			f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0640)
			if err != nil {
				return err
			}
			ccLog.Out = f
		}

		switch context.GlobalString("log-format") {
		case "text":
			// retain logrus's default.
		case "json":
			ccLog.Formatter = new(logrus.JSONFormatter)
		default:
			return fmt.Errorf("unknown log-format %q", context.GlobalString("log-format"))
		}

		// Set virtcontainers logger.
		vc.SetLog(ccLog)

		runtimeConfig, err := loadConfiguration("")
		if err != nil {
			return err
		}

		ccLog.Infof("%v (version %v, commit %v) called as: %v", name, version, commit, context.Args())

		// make the data accessible to the sub-commands.
		context.App.Metadata = map[string]interface{}{
			"runtimeConfig": runtimeConfig,
		}

		return nil
	}

	// If the command returns an error, cli takes upon itself to print
	// the error on cli.ErrWriter and exit.
	// Use our own writer here to ensure the log gets sent to the right
	// location.
	cli.ErrWriter = &fatalWriter{cli.ErrWriter}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// fatal prints the error's details exits the program.
func fatal(err error) {
	ccLog.Error(err)
	fmt.Fprintln(os.Stderr, err)
	os.Exit(1)
}

type fatalWriter struct {
	cliErrWriter io.Writer
}

func (f *fatalWriter) Write(p []byte) (n int, err error) {
	ccLog.Error(string(p))
	return f.cliErrWriter.Write(p)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/meshbird/meshbird/common"
	"github.com/meshbird/meshbird/secure"
	log "github.com/mgutz/logxi/v1"
	"net"
	"os"
	"os/signal"
	"time"
)

const (
	MeshbirdKeyEnv = "MESHBIRD_KEY"
)

var (
	// VERSION var using for auto versioning through Go linker
	VERSION = "dev"
	logger  = log.NewLogger(log.NewConcurrentWriter(os.Stderr), "[main] ")
)

func main() {
	app := cli.NewApp()
	app.Name = "MeshBird"
	app.Usage = "distributed private networking"
	app.Version = VERSION
	app.Commands = []cli.Command{
		{
			Name:      "new",
			Aliases:   []string{"n"},
			Usage:     "create new network",
			Action:    actionNew,
			ArgsUsage: "<key>",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "CIDR",
					Value: "10.7.0.0/16",
					Usage: "Define custom CIDR",
				},
			},
		},
		{
			Name:    "join",
			Aliases: []string{"j"},
			Usage:   "join network",
			Action:  actionJoin,
		},
		{
			Name:      "ip",
			Aliases:   []string{"i"},
			Usage:     "init state",
			Action:    actionGetIP,
			ArgsUsage: "<key>",
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		logger.Error("error: %s", err)
	}
}

func actionGetIP(ctx *cli.Context) {
	keyStr := os.Getenv(MeshbirdKeyEnv)
	if keyStr == "" {
		logger.Fatal(fmt.Sprintf("environment variable %s is not specified", MeshbirdKeyEnv))
	}
	secret, err := secure.NetworkSecretUnmarshal(keyStr)
	if err != nil {
		logger.Fatal(err.Error())
	}
	state := common.NewState(secret)
	state.Save()
	if logger.IsInfo() {
		logger.Info(fmt.Sprintf("Restored private IP address %s from state", state.PrivateIP.String()))
	}
}

func actionNew(ctx *cli.Context) {
	var secret *secure.NetworkSecret
	var err error

	if len(ctx.Args()) > 0 {
		keyStr := ctx.Args().First()
		secret, err = secure.NetworkSecretUnmarshal(keyStr)
		if err != nil {
			logger.Fatal(err.Error())
		}
	} else {
		_, ipnet, err := net.ParseCIDR(ctx.String("CIDR"))
		if err != nil {
			logger.Fatal(fmt.Sprintf("cidr parse error: %s", err))
		}
		secret = secure.NewNetworkSecret(ipnet)
	}
	fmt.Printf("key: %s\n", secret.Marshal())
}

func actionJoin(ctx *cli.Context) {
	key := os.Getenv(MeshbirdKeyEnv)
	if key == "" {
		logger.Fatal(fmt.Sprintf("environment variable %s is not specified", MeshbirdKeyEnv))
	}

	nodeConfig := &common.Config{
		SecretKey: key,
	}
	node, err := common.NewLocalNode(nodeConfig)
	if err != nil {
		logger.Fatal(fmt.Sprintf("local node init error: %s", err))
	}
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, os.Kill)
	defer signal.Stop(signalChan)

	go func() {
		s := <-signalChan
		if logger.IsInfo() {

			logger.Info(fmt.Sprintf("received signal %s, stopping...", s))
		}
		node.Stop()

		time.Sleep(2 * time.Second)
		os.Exit(0)
	}()

	err = node.Start()
	if err != nil {
		logger.Fatal(fmt.Sprintf("node start error: %s", err))
	}

	node.WaitStop()
}
<commit_msg>Print key with no prefix<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/meshbird/meshbird/common"
	"github.com/meshbird/meshbird/secure"
	log "github.com/mgutz/logxi/v1"
	"net"
	"os"
	"os/signal"
	"time"
)

const (
	MeshbirdKeyEnv = "MESHBIRD_KEY"
)

var (
	// VERSION var using for auto versioning through Go linker
	VERSION = "dev"
	logger  = log.NewLogger(log.NewConcurrentWriter(os.Stderr), "[main] ")
)

func main() {
	app := cli.NewApp()
	app.Name = "MeshBird"
	app.Usage = "distributed private networking"
	app.Version = VERSION
	app.Commands = []cli.Command{
		{
			Name:      "new",
			Aliases:   []string{"n"},
			Usage:     "create new network",
			Action:    actionNew,
			ArgsUsage: "<key>",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "CIDR",
					Value: "10.7.0.0/16",
					Usage: "Define custom CIDR",
				},
			},
		},
		{
			Name:    "join",
			Aliases: []string{"j"},
			Usage:   "join network",
			Action:  actionJoin,
		},
		{
			Name:      "ip",
			Aliases:   []string{"i"},
			Usage:     "init state",
			Action:    actionGetIP,
			ArgsUsage: "<key>",
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		logger.Error("error: %s", err)
	}
}

func actionGetIP(ctx *cli.Context) {
	keyStr := os.Getenv(MeshbirdKeyEnv)
	if keyStr == "" {
		logger.Fatal(fmt.Sprintf("environment variable %s is not specified", MeshbirdKeyEnv))
	}
	secret, err := secure.NetworkSecretUnmarshal(keyStr)
	if err != nil {
		logger.Fatal(err.Error())
	}
	state := common.NewState(secret)
	state.Save()
	if logger.IsInfo() {
		logger.Info(fmt.Sprintf("Restored private IP address %s from state", state.PrivateIP.String()))
	}
}

func actionNew(ctx *cli.Context) {
	var secret *secure.NetworkSecret
	var err error

	if len(ctx.Args()) > 0 {
		keyStr := ctx.Args().First()
		secret, err = secure.NetworkSecretUnmarshal(keyStr)
		if err != nil {
			logger.Fatal(err.Error())
		}
	} else {
		_, ipnet, err := net.ParseCIDR(ctx.String("CIDR"))
		if err != nil {
			logger.Fatal(fmt.Sprintf("cidr parse error: %s", err))
		}
		secret = secure.NewNetworkSecret(ipnet)
	}
	fmt.Println(secret.Marshal())
}

func actionJoin(ctx *cli.Context) {
	key := os.Getenv(MeshbirdKeyEnv)
	if key == "" {
		logger.Fatal(fmt.Sprintf("environment variable %s is not specified", MeshbirdKeyEnv))
	}

	nodeConfig := &common.Config{
		SecretKey: key,
	}
	node, err := common.NewLocalNode(nodeConfig)
	if err != nil {
		logger.Fatal(fmt.Sprintf("local node init error: %s", err))
	}
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, os.Kill)
	defer signal.Stop(signalChan)

	go func() {
		s := <-signalChan
		if logger.IsInfo() {

			logger.Info(fmt.Sprintf("received signal %s, stopping...", s))
		}
		node.Stop()

		time.Sleep(2 * time.Second)
		os.Exit(0)
	}()

	err = node.Start()
	if err != nil {
		logger.Fatal(fmt.Sprintf("node start error: %s", err))
	}

	node.WaitStop()
}
<|endoftext|>