<commit_before>package models

import (
	"time"

	"github.com/jackc/pgx"
)

// ServiceCheck represents a row from 'cyboard.service_check'.
type ServiceCheck struct {
	CreatedAt time.Time  `json:"created_at"` // created_at
	TeamID    int        `json:"team_id"`    // team_id
	ServiceID int        `json:"service_id"` // service_id
	Status    ExitStatus `json:"status"`     // status
	ExitCode  int16      `json:"exit_code"`  // exit_code
}

var (
	serviceCheckTableIdent   = pgx.Identifier{"cyboard", "service_check"}
	serviceCheckTableColumns = []string{
		"created_at", "team_id", "service_id", "status", "exit_code",
	}
)

// ServiceCheckSlice is an array of ServiceChecks, suitable to insert many of at once.
type ServiceCheckSlice []ServiceCheck

// serviceCheckCopyFromRows implements the pgx.CopyFromSource interface, allowing
// a ServiceCheckSlice to be inserted into the database.
type serviceCheckCopyFromRows struct {
	rows ServiceCheckSlice
	idx  int
}

func (ctr *serviceCheckCopyFromRows) Next() bool {
	ctr.idx++
	return ctr.idx < len(ctr.rows)
}

func (ctr *serviceCheckCopyFromRows) Values() ([]interface{}, error) {
	sc := ctr.rows[ctr.idx]
	val := []interface{}{
		sc.CreatedAt, sc.TeamID, sc.ServiceID, sc.Status, sc.ExitCode,
	}
	return val, nil
}

func (ctr *serviceCheckCopyFromRows) Err() error {
	return nil
}

// Insert a batch of service monitor results efficiently into the database.
func (sc ServiceCheckSlice) Insert(db DB) error {
	_, err := db.CopyFrom(
		serviceCheckTableIdent,
		serviceCheckTableColumns,
		&serviceCheckCopyFromRows{rows: sc, idx: -1},
	)
	return err
}

// LatestServiceCheckRun retrieves the timestamp of the last run of the service monitor.
// See: `LatestScoreChange` in `scoring.go`. This delta check is specific to services.
func LatestServiceCheckRun(db DB) (time.Time, error) {
	const sqlstr = `SELECT created_at FROM service_check UNION ALL SELECT 'epoch' ORDER BY created_at DESC LIMIT 1`
	var timestamp time.Time
	err := db.QueryRow(sqlstr).Scan(&timestamp)
	return timestamp, err
}

// TeamServiceStatusesView represents the current, calculated
// service's status (pass, fail, timeout), for all teams.
type TeamServiceStatusesView struct {
	ServiceID   int          `json:"service_id"`
	ServiceName string       `json:"service_name"`
	Statuses    []ExitStatus `json:"statuses"`
}

// TeamServiceStatuses gets the current service status (pass, fail, timeout)
// for each team, for each non-disabled service.
func TeamServiceStatuses(db DB) ([]TeamServiceStatusesView, error) {
	const sqlstr = `
	SELECT ss.service, ss.service_name, jsonb_agg(ss.status) AS statuses
	FROM (SELECT * FROM blueteam AS team,
	LATERAL (SELECT id AS service, name AS service_name, COALESCE(last(sc.status, sc.created_at), 'timeout') AS status
		FROM service
			LEFT JOIN service_check AS sc ON id = sc.service_id AND team.id = sc.team_id
		WHERE service.disabled = false
		GROUP BY service.id, team.name) AS ss
		ORDER BY ss.service, team.id) AS ss
	GROUP BY ss.service, ss.service_name`
	rows, err := db.Query(sqlstr)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	xs := []TeamServiceStatusesView{}
	for rows.Next() {
		x := TeamServiceStatusesView{}
		if err = rows.Scan(&x.ServiceID, &x.ServiceName, &x.Statuses); err != nil {
			return nil, err
		}
		xs = append(xs, x)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}

	return xs, nil
}

type MonitorTeamService struct {
	Team struct { // `cyboard.team` table
		ID   int    // id
		Name string // name
		IP   int16  // blueteam_ip
	}
	Service struct { // `cyboard.service` table
		ID       int       // id
		Name     string    // name
		Script   string    // script
		Args     []string  // args
		StartsAt time.Time // starts_at
	}
}

// MonitorTeamsAndServices fetches every active service and blueteam from the
// database, at the same time. Returns an empty array for no rows, or an error
// if there is a problem fetching data from postgres.
func MonitorTeamsAndServices(db DBClient) ([]MonitorTeamService, error) {
	const sqlstr = `SELECT
		t.id, t.name, t.blueteam_ip,
		s.id, s.name, s.script, s.args, s.starts_at
	FROM service AS s CROSS JOIN blueteam AS t
	WHERE s.disabled = false`
	rows, err := db.Query(sqlstr)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	xs := []MonitorTeamService{}
	for rows.Next() {
		x := MonitorTeamService{}
		err = rows.Scan(&x.Team.ID, &x.Team.Name, &x.Team.IP,
			&x.Service.ID, &x.Service.Name, &x.Service.Script, &x.Service.Args, &x.Service.StartsAt)
		if err != nil {
			return nil, err
		}
		xs = append(xs, x)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}

	return xs, nil
}
<commit_msg>Only display services that have started on the scoreboard<commit_after>package models

import (
	"time"

	"github.com/jackc/pgx"
)

// ServiceCheck represents a row from 'cyboard.service_check'.
type ServiceCheck struct {
	CreatedAt time.Time  `json:"created_at"` // created_at
	TeamID    int        `json:"team_id"`    // team_id
	ServiceID int        `json:"service_id"` // service_id
	Status    ExitStatus `json:"status"`     // status
	ExitCode  int16      `json:"exit_code"`  // exit_code
}

var (
	serviceCheckTableIdent   = pgx.Identifier{"cyboard", "service_check"}
	serviceCheckTableColumns = []string{
		"created_at", "team_id", "service_id", "status", "exit_code",
	}
)

// ServiceCheckSlice is an array of ServiceChecks, suitable to insert many of at once.
type ServiceCheckSlice []ServiceCheck

// serviceCheckCopyFromRows implements the pgx.CopyFromSource interface, allowing
// a ServiceCheckSlice to be inserted into the database.
type serviceCheckCopyFromRows struct {
	rows ServiceCheckSlice
	idx  int
}

func (ctr *serviceCheckCopyFromRows) Next() bool {
	ctr.idx++
	return ctr.idx < len(ctr.rows)
}

func (ctr *serviceCheckCopyFromRows) Values() ([]interface{}, error) {
	sc := ctr.rows[ctr.idx]
	val := []interface{}{
		sc.CreatedAt, sc.TeamID, sc.ServiceID, sc.Status, sc.ExitCode,
	}
	return val, nil
}

func (ctr *serviceCheckCopyFromRows) Err() error {
	return nil
}

// Insert a batch of service monitor results efficiently into the database.
func (sc ServiceCheckSlice) Insert(db DB) error {
	_, err := db.CopyFrom(
		serviceCheckTableIdent,
		serviceCheckTableColumns,
		&serviceCheckCopyFromRows{rows: sc, idx: -1},
	)
	return err
}

// LatestServiceCheckRun retrieves the timestamp of the last run of the service monitor.
// See: `LatestScoreChange` in `scoring.go`. This delta check is specific to services.
func LatestServiceCheckRun(db DB) (time.Time, error) {
	const sqlstr = `SELECT created_at FROM service_check UNION ALL SELECT 'epoch' ORDER BY created_at DESC LIMIT 1`
	var timestamp time.Time
	err := db.QueryRow(sqlstr).Scan(&timestamp)
	return timestamp, err
}

// TeamServiceStatusesView represents the current, calculated
// service's status (pass, fail, timeout), for all teams.
type TeamServiceStatusesView struct {
	ServiceID   int          `json:"service_id"`
	ServiceName string       `json:"service_name"`
	Statuses    []ExitStatus `json:"statuses"`
}

// TeamServiceStatuses gets the current service status (pass, fail, timeout)
// for each team, for each service that has started and isn't disabled.
func TeamServiceStatuses(db DB) ([]TeamServiceStatusesView, error) {
	const sqlstr = `
	SELECT ss.service, ss.service_name, jsonb_agg(ss.status) AS statuses
	FROM (SELECT * FROM blueteam AS team,
	LATERAL (SELECT id AS service, name AS service_name, COALESCE(last(sc.status, sc.created_at), 'timeout') AS status
		FROM service
			LEFT JOIN service_check AS sc ON id = sc.service_id AND team.id = sc.team_id
		WHERE service.disabled = false AND service.starts_at < current_timestamp
		GROUP BY service.id, team.name) AS ss
		ORDER BY ss.service, team.id) AS ss
	GROUP BY ss.service, ss.service_name`
	rows, err := db.Query(sqlstr)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	xs := []TeamServiceStatusesView{}
	for rows.Next() {
		x := TeamServiceStatusesView{}
		if err = rows.Scan(&x.ServiceID, &x.ServiceName, &x.Statuses); err != nil {
			return nil, err
		}
		xs = append(xs, x)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}

	return xs, nil
}

type MonitorTeamService struct {
	Team struct { // `cyboard.team` table
		ID   int    // id
		Name string // name
		IP   int16  // blueteam_ip
	}
	Service struct { // `cyboard.service` table
		ID       int       // id
		Name     string    // name
		Script   string    // script
		Args     []string  // args
		StartsAt time.Time // starts_at
	}
}

// MonitorTeamsAndServices fetches every active service and blueteam from the
// database, at the same time. Returns an empty array for no rows, or an error
// if there is a problem fetching data from postgres.
func MonitorTeamsAndServices(db DBClient) ([]MonitorTeamService, error) {
	const sqlstr = `SELECT
		t.id, t.name, t.blueteam_ip,
		s.id, s.name, s.script, s.args, s.starts_at
	FROM service AS s CROSS JOIN blueteam AS t
	WHERE s.disabled = false`
	rows, err := db.Query(sqlstr)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	xs := []MonitorTeamService{}
	for rows.Next() {
		x := MonitorTeamService{}
		err = rows.Scan(&x.Team.ID, &x.Team.Name, &x.Team.IP,
			&x.Service.ID, &x.Service.Name, &x.Service.Script, &x.Service.Args, &x.Service.StartsAt)
		if err != nil {
			return nil, err
		}
		xs = append(xs, x)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}

	return xs, nil
}
<|endoftext|>


<commit_before>package veneur

import (
	"net"
	"sync"

	"github.com/DataDog/datadog-go/statsd"
	"github.com/Sirupsen/logrus"
	"github.com/getsentry/raven-go"
)

type Server struct {
	Workers []*Worker

	statsd *statsd.Client
	logger *logrus.Logger
	sentry *raven.Client

	Hostname string
	Tags     []string

	DDHostname string
	DDAPIKey   string

	UDPAddr     *net.UDPAddr
	RcvbufBytes int

	HistogramPercentiles []float64
	HistogramCounter     bool
}

func NewFromConfig(conf Config) (ret Server, err error) {
	ret.Hostname = conf.Hostname
	ret.Tags = conf.Tags
	ret.DDHostname = conf.APIHostname
	ret.DDAPIKey = conf.Key
	ret.HistogramCounter = conf.HistCounters
	ret.HistogramPercentiles = conf.Percentiles

	ret.statsd, err = statsd.NewBuffered(conf.StatsAddr, 1024)
	if err != nil {
		return
	}
	ret.statsd.Namespace = "veneur."
	ret.statsd.Tags = ret.Tags

	// nil is a valid sentry client that noops all methods, if there is no DSN
	// we can just leave it as nil
	if conf.SentryDSN != "" {
		ret.sentry, err = raven.New(conf.SentryDSN)
		if err != nil {
			return
		}
	}

	ret.logger = logrus.New()
	if conf.Debug {
		ret.logger.Level = logrus.DebugLevel
	}
	ret.logger.Hooks.Add(sentryHook{
		c:        ret.sentry,
		hostname: ret.Hostname,
		lv: []logrus.Level{
			logrus.ErrorLevel,
			logrus.FatalLevel,
			logrus.PanicLevel,
		},
	})

	ret.logger.WithField("number", conf.NumWorkers).Info("Starting workers")
	ret.Workers = make([]*Worker, conf.NumWorkers)
	for i := range ret.Workers {
		ret.Workers[i] = NewWorker(i+1, ret.statsd, ret.logger)
		// do not close over loop index
		go func(w *Worker) {
			defer func() {
				ret.ConsumePanic(recover())
			}()
			w.Work()
		}(ret.Workers[i])
	}

	ret.UDPAddr, err = net.ResolveUDPAddr("udp", conf.UDPAddr)
	if err != nil {
		return
	}
	ret.RcvbufBytes = conf.ReadBufferSizeBytes

	conf.Key = "REDACTED"
	conf.SentryDSN = "REDACTED"
	ret.logger.WithField("config", conf).Debug("Initialized server")

	return
}

func (s *Server) HandlePacket(packet []byte, packetPool *sync.Pool) {
	metric, err := ParseMetric(packet)
	if err != nil {
		s.logger.WithFields(logrus.Fields{
			logrus.ErrorKey: err,
			"packet":        string(packet),
		}).Error("Could not parse packet")
		s.statsd.Count("packet.error_total", 1, nil, 1.0)
	}

	if len(s.Tags) > 0 {
		metric.Tags = append(metric.Tags, s.Tags...)
	}

	s.Workers[metric.Digest%uint32(len(s.Workers))].WorkChan <- *metric

	// the Metric struct has no byte slices in it, only strings
	// therefore there are no outstanding references to this byte slice, and we
	// can return it to the pool
	packetPool.Put(packet[:cap(packet)])
}

func (s *Server) ReadSocket(packetPool *sync.Pool) {
	// each goroutine gets its own socket
	// if the sockets support SO_REUSEPORT, then this will cause the
	// kernel to distribute datagrams across them, for better read
	// performance
	s.logger.WithField("address", s.UDPAddr).Info("UDP server listening")
	serverConn, err := NewSocket(s.UDPAddr, s.RcvbufBytes)
	if err != nil {
		// if any goroutine fails to create the socket, we can't really
		// recover, so we just blow up
		// this probably indicates a systemic issue, eg lack of
		// SO_REUSEPORT support
		s.logger.WithError(err).Fatal("Error listening for UDP")
	}

	for {
		buf := packetPool.Get().([]byte)
		n, _, err := serverConn.ReadFrom(buf)
		if err != nil {
			s.logger.WithError(err).Error("Error reading from UDP")
			continue
		}
		s.HandlePacket(buf[:n], packetPool)
	}
}
<commit_msg>Do not feed malformed packets to workers<commit_after>package veneur

import (
	"net"
	"sync"

	"github.com/DataDog/datadog-go/statsd"
	"github.com/Sirupsen/logrus"
	"github.com/getsentry/raven-go"
)

type Server struct {
	Workers []*Worker

	statsd *statsd.Client
	logger *logrus.Logger
	sentry *raven.Client

	Hostname string
	Tags     []string

	DDHostname string
	DDAPIKey   string

	UDPAddr     *net.UDPAddr
	RcvbufBytes int

	HistogramPercentiles []float64
	HistogramCounter     bool
}

func NewFromConfig(conf Config) (ret Server, err error) {
	ret.Hostname = conf.Hostname
	ret.Tags = conf.Tags
	ret.DDHostname = conf.APIHostname
	ret.DDAPIKey = conf.Key
	ret.HistogramCounter = conf.HistCounters
	ret.HistogramPercentiles = conf.Percentiles

	ret.statsd, err = statsd.NewBuffered(conf.StatsAddr, 1024)
	if err != nil {
		return
	}
	ret.statsd.Namespace = "veneur."
	ret.statsd.Tags = ret.Tags

	// nil is a valid sentry client that noops all methods, if there is no DSN
	// we can just leave it as nil
	if conf.SentryDSN != "" {
		ret.sentry, err = raven.New(conf.SentryDSN)
		if err != nil {
			return
		}
	}

	ret.logger = logrus.New()
	if conf.Debug {
		ret.logger.Level = logrus.DebugLevel
	}
	ret.logger.Hooks.Add(sentryHook{
		c:        ret.sentry,
		hostname: ret.Hostname,
		lv: []logrus.Level{
			logrus.ErrorLevel,
			logrus.FatalLevel,
			logrus.PanicLevel,
		},
	})

	ret.logger.WithField("number", conf.NumWorkers).Info("Starting workers")
	ret.Workers = make([]*Worker, conf.NumWorkers)
	for i := range ret.Workers {
		ret.Workers[i] = NewWorker(i+1, ret.statsd, ret.logger)
		// do not close over loop index
		go func(w *Worker) {
			defer func() {
				ret.ConsumePanic(recover())
			}()
			w.Work()
		}(ret.Workers[i])
	}

	ret.UDPAddr, err = net.ResolveUDPAddr("udp", conf.UDPAddr)
	if err != nil {
		return
	}
	ret.RcvbufBytes = conf.ReadBufferSizeBytes

	conf.Key = "REDACTED"
	conf.SentryDSN = "REDACTED"
	ret.logger.WithField("config", conf).Debug("Initialized server")

	return
}

func (s *Server) HandlePacket(packet []byte) {
	metric, err := ParseMetric(packet)
	if err != nil {
		s.logger.WithFields(logrus.Fields{
			logrus.ErrorKey: err,
			"packet":        string(packet),
		}).Error("Could not parse packet")
		s.statsd.Count("packet.error_total", 1, nil, 1.0)
		return
	}

	if len(s.Tags) > 0 {
		metric.Tags = append(metric.Tags, s.Tags...)
	}

	s.Workers[metric.Digest%uint32(len(s.Workers))].WorkChan <- *metric
}

func (s *Server) ReadSocket(packetPool *sync.Pool) {
	// each goroutine gets its own socket
	// if the sockets support SO_REUSEPORT, then this will cause the
	// kernel to distribute datagrams across them, for better read
	// performance
	s.logger.WithField("address", s.UDPAddr).Info("UDP server listening")
	serverConn, err := NewSocket(s.UDPAddr, s.RcvbufBytes)
	if err != nil {
		// if any goroutine fails to create the socket, we can't really
		// recover, so we just blow up
		// this probably indicates a systemic issue, eg lack of
		// SO_REUSEPORT support
		s.logger.WithError(err).Fatal("Error listening for UDP")
	}

	for {
		buf := packetPool.Get().([]byte)
		n, _, err := serverConn.ReadFrom(buf)
		if err != nil {
			s.logger.WithError(err).Error("Error reading from UDP")
			continue
		}
		s.HandlePacket(buf[:n])
		// the Metric struct created by HandlePacket has no byte slices in it,
		// only strings
		// therefore there are no outstanding references to this byte slice, we
		// can return it to the pool
		packetPool.Put(buf)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ssm"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

var verbose = os.Getenv("ENV_INJECTOR_VERBOSE") == "1"

// For lazy initialization
var service *ssm.SSM

func main() {
	injectEnviron()

	args := os.Args
	if len(args) <= 1 {
		log.Fatal("missing command")
	}

	path, err := exec.LookPath(args[1])
	if err != nil {
		log.Fatal(err)
	}
	err = syscall.Exec(path, args[1:], os.Environ())
	if err != nil {
		log.Fatal(err)
	}
}

func trace(v ...interface{}) {
	if verbose {
		log.Println(v...)
	}
}

func tracef(format string, v ...interface{}) {
	if verbose {
		log.Printf(format, v...)
	}
}

func injectEnviron() {
	injectEnvironByPath()
	injectEnvironByPrefix()
}

func injectEnvironByPath() {
	path := os.Getenv("ENV_INJECTOR_PATH")
	if path == "" {
		trace("no parameter path specified, skipping injection by path")
		return
	}
	tracef("parameter path: %s", path)

	svc := getSSMService()
	if svc == nil {
		return
	}

	var nextToken *string
	for {
		result, err := svc.GetParametersByPath(&ssm.GetParametersByPathInput{
			Path:           aws.String(path),
			WithDecryption: aws.Bool(true),
			NextToken:      nextToken,
		})
		if err != nil {
			tracef("failed to get by path: %s", path)
			trace(err)
			return
		}

		for _, param := range result.Parameters {
			key, err := filepath.Rel(path, aws.StringValue(param.Name))
			if err != nil {
				trace(err)
				continue
			}
			if os.Getenv(key) == "" {
				os.Setenv(key, aws.StringValue(param.Value))
				tracef("env injected: %s", key)
			}
		}
		nextToken = result.NextToken
		if nextToken == nil || aws.StringValue(nextToken) == "" {
			break
		}
	}
}

func injectEnvironByPrefix() {
	prefix := os.Getenv("ENV_INJECTOR_PREFIX")

	if prefix == "" {
		trace("no parameter prefix specified, skipping injection by prefix")
		return
	}
	tracef("parameter prefix: %s", prefix)
	if !strings.HasSuffix(prefix, ".") {
		prefix += "."
	}

	names := []*string{}
	for _, env := range os.Environ() {
		parts := strings.SplitN(env, "=", 2)
		if len(parts) == 2 && parts[1] == "" {
			names = append(names, aws.String(prefix+parts[0]))
		}
	}
	if len(names) == 0 {
		trace("nothing to be injected by prefix")
		return
	}

	svc := getSSMService()
	if svc == nil {
		return
	}

	// 'GetParameters' fails entirely when any one of parameters is not permitted to get.
	// So call 'GetParameters' one by one.
	for _, n := range names {
		result, err := svc.GetParameters(&ssm.GetParametersInput{
			Names:          []*string{n},
			WithDecryption: aws.Bool(true),
		})
		if err != nil {
			tracef("failed to get: %s", *n)
			trace(err)
			continue
		}

		for _, key := range result.InvalidParameters {
			tracef("invalid parameter: %s", aws.StringValue(key))
		}
		for _, param := range result.Parameters {
			key := strings.TrimPrefix(aws.StringValue(param.Name), prefix)
			os.Setenv(key, aws.StringValue(param.Value))
			tracef("env injected: %s", key)
		}
	}
}

// Initialize SSM service lazily, and return it.
func getSSMService() *ssm.SSM {
	if service != nil {
		return service
	}

	sess, err := session.NewSessionWithOptions(session.Options{
		SharedConfigState: session.SharedConfigEnable,
	})
	if err != nil {
		trace(err)
		trace("failed to create session")
		return nil
	}
	if *sess.Config.Region == "" {
		trace("no explicit region configuration. So now retrieving ec2metadata...")
		region, err := ec2metadata.New(sess).Region()
		if err != nil {
			trace(err)
			trace("could not find region configuration")
			return nil
		}
		sess.Config.Region = aws.String(region)
	}

	if arn := os.Getenv("ENV_INJECTOR_ASSUME_ROLE_ARN"); arn != "" {
		creds := stscreds.NewCredentials(sess, arn)
		service = ssm.New(sess, &aws.Config{Credentials: creds})
	} else {
		service = ssm.New(sess)
	}
	return service
}
<commit_msg>treat as a fatal error in some cases (#1)<commit_after>package main

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ssm"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

var verbose = os.Getenv("ENV_INJECTOR_VERBOSE") == "1"

// For lazy initialization
var service *ssm.SSM

func main() {
	injectEnviron()

	args := os.Args
	if len(args) <= 1 {
		log.Fatal("missing command")
	}

	path, err := exec.LookPath(args[1])
	if err != nil {
		log.Fatal(err)
	}
	err = syscall.Exec(path, args[1:], os.Environ())
	if err != nil {
		log.Fatal(err)
	}
}

func trace(v ...interface{}) {
	if verbose {
		log.Println(v...)
	}
}

func tracef(format string, v ...interface{}) {
	if verbose {
		log.Printf(format, v...)
	}
}

func injectEnviron() {
	injectEnvironByPath()
	injectEnvironByPrefix()
}

func injectEnvironByPath() {
	path := os.Getenv("ENV_INJECTOR_PATH")
	if path == "" {
		trace("no parameter path specified, skipping injection by path")
		return
	}
	tracef("parameter path: %s", path)

	svc := getSSMService()

	var nextToken *string
	for {
		result, err := svc.GetParametersByPath(&ssm.GetParametersByPathInput{
			Path:           aws.String(path),
			WithDecryption: aws.Bool(true),
			NextToken:      nextToken,
		})
		if err != nil {
			log.Fatalf("ssm:GetParametersByPath failed. (path: %s)\n %v", path, err)
		}

		for _, param := range result.Parameters {
			key, err := filepath.Rel(path, aws.StringValue(param.Name))
			if err != nil {
				trace(err)
				continue
			}
			if os.Getenv(key) == "" {
				os.Setenv(key, aws.StringValue(param.Value))
				tracef("env injected: %s", key)
			}
		}
		nextToken = result.NextToken
		if nextToken == nil || aws.StringValue(nextToken) == "" {
			break
		}
	}
}

func injectEnvironByPrefix() {
	prefix := os.Getenv("ENV_INJECTOR_PREFIX")

	if prefix == "" {
		trace("no parameter prefix specified, skipping injection by prefix")
		return
	}
	tracef("parameter prefix: %s", prefix)
	if !strings.HasSuffix(prefix, ".") {
		prefix += "."
	}

	names := []*string{}
	for _, env := range os.Environ() {
		parts := strings.SplitN(env, "=", 2)
		if len(parts) == 2 && parts[1] == "" {
			names = append(names, aws.String(prefix+parts[0]))
		}
	}
	if len(names) == 0 {
		trace("nothing to be injected by prefix")
		return
	}

	svc := getSSMService()

	// 'GetParameters' fails entirely when any one of parameters is not permitted to get.
	// So call 'GetParameters' one by one.
	for _, n := range names {
		result, err := svc.GetParameters(&ssm.GetParametersInput{
			Names:          []*string{n},
			WithDecryption: aws.Bool(true),
		})
		if err != nil {
			tracef("failed to get: %s", *n)
			trace(err)
			continue
		}

		for _, key := range result.InvalidParameters {
			tracef("invalid parameter: %s", aws.StringValue(key))
		}
		for _, param := range result.Parameters {
			key := strings.TrimPrefix(aws.StringValue(param.Name), prefix)
			os.Setenv(key, aws.StringValue(param.Value))
			tracef("env injected: %s", key)
		}
	}
}

// Initialize SSM service lazily, and return it.
func getSSMService() *ssm.SSM {
	if service != nil {
		return service
	}

	sess, err := session.NewSessionWithOptions(session.Options{
		SharedConfigState: session.SharedConfigEnable,
	})
	if err != nil {
		log.Fatalf("failed to create a new session.\n %v", err)
	}
	if *sess.Config.Region == "" {
		trace("no explicit region configuration. So now retrieving ec2metadata...")
		region, err := ec2metadata.New(sess).Region()
		if err != nil {
			trace(err)
			log.Fatalf("could not find region configurations")
		}
		sess.Config.Region = aws.String(region)
	}

	if arn := os.Getenv("ENV_INJECTOR_ASSUME_ROLE_ARN"); arn != "" {
		creds := stscreds.NewCredentials(sess, arn)
		service = ssm.New(sess, &aws.Config{Credentials: creds})
	} else {
		service = ssm.New(sess)
	}
	return service
}
<|endoftext|>


<commit_before>package restkit

import (
	"encoding/json"
	"net/http"
)

// JSON creates a application/json content-type header, sets the given HTTP
// status code and encodes the given result object to the response writer.
func JSON(resp http.ResponseWriter, result interface{}, code int) error {
	resp.Header().Add("Content-Type", "application/json")
	resp.WriteHeader(code)
	if result != nil {
		return maskAny(json.NewEncoder(resp).Encode(result))
	}
	return nil
}

// Text creates a text/plain content-type header, sets the given HTTP
// status code and writes the given content to the response writer.
func Text(resp http.ResponseWriter, content string, code int) error {
	resp.Header().Add("Content-Type", "text/plain")
	resp.WriteHeader(code)
	_, err := resp.Write([]byte(content))
	return maskAny(err)
}

// Html creates a text/html content-type header, sets the given HTTP
// status code and writes the given content to the response writer.
func Html(resp http.ResponseWriter, content string, code int) error {
	resp.Header().Add("Content-Type", "text/html")
	resp.WriteHeader(code)
	_, err := resp.Write([]byte(content))
	return maskAny(err)
}

// Error sends an error message back to the given response writer.
func Error(resp http.ResponseWriter, err error) error {
	code := http.StatusBadRequest
	message := err.Error()
	if IsForbidden(err) {
		code = http.StatusForbidden
	} else if IsInternalServer(err) {
		code = http.StatusInternalServerError
	} else if IsInvalidArgument(err) {
		code = http.StatusBadRequest
	} else if IsNotFound(err) {
		code = http.StatusNotFound
	} else if IsUnauthorizedError(err) {
		code = http.StatusUnauthorized
	}

	if er, ok := err.(*ErrorResponse); ok {
		return maskAny(JSON(resp, er, code))
	}

	er := ErrorResponse{}
	er.TheError.Message = message
	return maskAny(JSON(resp, er, code))
}
<commit_msg>Improved `Error` function with errgo.Cause<commit_after>package restkit

import (
	"encoding/json"
	"net/http"

	"github.com/juju/errgo"
)

// JSON creates a application/json content-type header, sets the given HTTP
// status code and encodes the given result object to the response writer.
func JSON(resp http.ResponseWriter, result interface{}, code int) error {
	resp.Header().Add("Content-Type", "application/json")
	resp.WriteHeader(code)
	if result != nil {
		return maskAny(json.NewEncoder(resp).Encode(result))
	}
	return nil
}

// Text creates a text/plain content-type header, sets the given HTTP
// status code and writes the given content to the response writer.
func Text(resp http.ResponseWriter, content string, code int) error {
	resp.Header().Add("Content-Type", "text/plain")
	resp.WriteHeader(code)
	_, err := resp.Write([]byte(content))
	return maskAny(err)
}

// Html creates a text/html content-type header, sets the given HTTP
// status code and writes the given content to the response writer.
func Html(resp http.ResponseWriter, content string, code int) error {
	resp.Header().Add("Content-Type", "text/html")
	resp.WriteHeader(code)
	_, err := resp.Write([]byte(content))
	return maskAny(err)
}

// Error sends an error message back to the given response writer.
func Error(resp http.ResponseWriter, err error) error {
	code := http.StatusBadRequest
	message := err.Error()
	if IsForbidden(err) {
		code = http.StatusForbidden
	} else if IsInternalServer(err) {
		code = http.StatusInternalServerError
	} else if IsInvalidArgument(err) {
		code = http.StatusBadRequest
	} else if IsNotFound(err) {
		code = http.StatusNotFound
	} else if IsUnauthorizedError(err) {
		code = http.StatusUnauthorized
	}

	if er, ok := err.(*ErrorResponse); ok {
		return maskAny(JSON(resp, er, code))
	}
	if er, ok := errgo.Cause(err).(*ErrorResponse); ok {
		return maskAny(JSON(resp, er, code))
	}

	er := ErrorResponse{}
	er.TheError.Message = message
	er.TheError.Code = -1
	return maskAny(JSON(resp, er, code))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
)

var commands = []*Command{
	helpCmd,
	listCmd,
	tagsCmd,
}

func main() {
	flag.Usage = func() {
		helpFunc(helpCmd)
	}
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
		return
	}

	Load()
	defer Save()

	sub, args := args[0], args[1:]
	for _, cmd := range commands {
		if cmd.Name == sub {
			cmd.Exec(args)
			return
		}
	}

	fmt.Fprintf(stdout, "error: unknown command %q\n\n", sub)
	flag.Usage()
}
<commit_msg>allow command prefixes<commit_after>package main

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

var commands = []*Command{
	helpCmd,
	listCmd,
	tagsCmd,
}

func main() {
	flag.Usage = func() {
		helpFunc(helpCmd)
	}
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
		return
	}

	Load()
	defer Save()

	var found *Command
	sub, args := args[0], args[1:]
	for _, cmd := range commands {
		if strings.HasPrefix(cmd.Name, sub) {
			if found != nil {
				fmt.Fprintf(stdout, "error: non-unique prefix %q\n\n", sub)
				os.Exit(1)
			}
			found = cmd
		}
	}
	if found == nil {
		fmt.Fprintf(stdout, "error: unknown command %q\n\n", sub)
		flag.Usage()
		os.Exit(1)
	}
	found.Exec(args)
}
<|endoftext|>


<commit_before>package main

import (
	ggproto "github.com/gogo/protobuf/proto"
	p2p_crypto "github.com/libp2p/go-libp2p-crypto"
	p2p_peer "github.com/libp2p/go-libp2p-peer"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	multihash "github.com/multiformats/go-multihash"
	"log"
	"sync"
)

type ManifestStoreImpl struct {
	mx   sync.Mutex
	mf   map[string]ManifestRecord
	keys map[string]p2p_crypto.PubKey
}

type ManifestRecord struct {
	mf  *pb.Manifest
	src p2p_peer.ID
}

func NewManifestStore() ManifestStore {
	return &ManifestStoreImpl{
		mf:   make(map[string]ManifestRecord),
		keys: make(map[string]p2p_crypto.PubKey),
	}
}

func (mfs *ManifestStoreImpl) Put(src p2p_peer.ID, lst []*pb.Manifest) {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	for _, mf := range lst {
		mfs.putManifest(src, mf)
	}
}

func (mfs *ManifestStoreImpl) putManifest(src p2p_peer.ID, mf *pb.Manifest) {
	mfx, err := hashManifest(mf)
	if err != nil {
		log.Printf("Error hashing manifest; wtf: %s", err.Error())
		return
	}

	mfh := mfx.B58String()

	_, ok := mfs.mf[mfh]
	if ok {
		return
	}

	kid := mf.Entity + ":" + mf.KeyId
	pubk, ok := mfs.keys[kid]

	if !ok {
		// XXX This can take arbitrary long and might need to be throttled
		// XXX and in the meantime, it holds the manifest store lock...
		// XXX The solution to this problem is to fetch keys asynchronously
		// XXX with back-off/retry logic; impl is complicated though, so for now
		// XXX damn the torpedoes (but at least release the lock)
		mfs.mx.Unlock()
		pubk, err = mc.LookupEntityKey(mf.Entity, mf.KeyId)
		mfs.mx.Lock()
		if err != nil {
			log.Printf("Error looking up entity key %s: %s", kid, err.Error())
			return
		}
		mfs.keys[kid] = pubk
	}

	ok, err = verifyManifest(mf, pubk)
	switch {
	case err != nil:
		log.Printf("Error verifying manifest %s: %s", mfh, err.Error())

	case !ok:
		log.Printf("Error verifying manifest %s: signature verification failed", mfh)

	default:
		// yay! a valid manifest.
		mfs.mf[mfh] = ManifestRecord{mf, src}
	}
}

func (mfs *ManifestStoreImpl) Remove(src p2p_peer.ID) {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	for mfh, mfr := range mfs.mf {
		if mfr.src == src {
			delete(mfs.mf, mfh)
		}
	}
}

func (mfs *ManifestStoreImpl) Lookup(entity string) []*pb.Manifest {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	res := make([]*pb.Manifest, 0)
	for _, mfr := range mfs.mf {
		if mfr.mf.Entity == entity {
			res = append(res, mfr.mf)
		}
	}

	return res
}

func hashManifest(mf *pb.Manifest) (multihash.Multihash, error) {
	bytes, err := ggproto.Marshal(mf)
	if err != nil {
		return nil, err
	}

	return mc.Hash(bytes), nil
}

func verifyManifest(mf *pb.Manifest, pubk p2p_crypto.PubKey) (bool, error) {
	sig := mf.Signature
	mf.Signature = nil
	bytes, err := ggproto.Marshal(mf)
	mf.Signature = sig

	if err != nil {
		return false, err
	}

	return pubk.Verify(bytes, sig)
}
<commit_msg>mcdir/mfs: add basic wildcarding for retrieving all manifests<commit_after>package main

import (
	ggproto "github.com/gogo/protobuf/proto"
	p2p_crypto "github.com/libp2p/go-libp2p-crypto"
	p2p_peer "github.com/libp2p/go-libp2p-peer"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	multihash "github.com/multiformats/go-multihash"
	"log"
	"sync"
)

type ManifestStoreImpl struct {
	mx   sync.Mutex
	mf   map[string]ManifestRecord
	keys map[string]p2p_crypto.PubKey
}

type ManifestRecord struct {
	mf  *pb.Manifest
	src p2p_peer.ID
}

func NewManifestStore() ManifestStore {
	return &ManifestStoreImpl{
		mf:   make(map[string]ManifestRecord),
		keys: make(map[string]p2p_crypto.PubKey),
	}
}

func (mfs *ManifestStoreImpl) Put(src p2p_peer.ID, lst []*pb.Manifest) {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	for _, mf := range lst {
		mfs.putManifest(src, mf)
	}
}

func (mfs *ManifestStoreImpl) putManifest(src p2p_peer.ID, mf *pb.Manifest) {
	mfx, err := hashManifest(mf)
	if err != nil {
		log.Printf("Error hashing manifest; wtf: %s", err.Error())
		return
	}

	mfh := mfx.B58String()

	_, ok := mfs.mf[mfh]
	if ok {
		return
	}

	kid := mf.Entity + ":" + mf.KeyId
	pubk, ok := mfs.keys[kid]

	if !ok {
		// XXX This can take arbitrary long and might need to be throttled
		// XXX and in the meantime, it holds the manifest store lock...
		// XXX The solution to this problem is to fetch keys asynchronously
		// XXX with back-off/retry logic; impl is complicated though, so for now
		// XXX damn the torpedoes (but at least release the lock)
		mfs.mx.Unlock()
		pubk, err = mc.LookupEntityKey(mf.Entity, mf.KeyId)
		mfs.mx.Lock()
		if err != nil {
			log.Printf("Error looking up entity key %s: %s", kid, err.Error())
			return
		}
		mfs.keys[kid] = pubk
	}

	ok, err = verifyManifest(mf, pubk)
	switch {
	case err != nil:
		log.Printf("Error verifying manifest %s: %s", mfh, err.Error())

	case !ok:
		log.Printf("Error verifying manifest %s: signature verification failed", mfh)

	default:
		// yay! a valid manifest.
		mfs.mf[mfh] = ManifestRecord{mf, src}
	}
}

func (mfs *ManifestStoreImpl) Remove(src p2p_peer.ID) {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	for mfh, mfr := range mfs.mf {
		if mfr.src == src {
			delete(mfs.mf, mfh)
		}
	}
}

func (mfs *ManifestStoreImpl) Lookup(entity string) []*pb.Manifest {
	mfs.mx.Lock()
	defer mfs.mx.Unlock()

	switch {
	case entity == "":
		fallthrough
	case entity == "*":
		return mfs.lookupManifest(func(*pb.Manifest) bool {
			return true
		})

	default:
		return mfs.lookupManifest(func(mf *pb.Manifest) bool {
			return mf.Entity == entity
		})
	}
}

func (mfs *ManifestStoreImpl) lookupManifest(filter func(*pb.Manifest) bool) []*pb.Manifest {
	res := make([]*pb.Manifest, 0)
	for _, mfr := range mfs.mf {
		if filter(mfr.mf) {
			res = append(res, mfr.mf)
		}
	}
	return res
}

func hashManifest(mf *pb.Manifest) (multihash.Multihash, error) {
	bytes, err := ggproto.Marshal(mf)
	if err != nil {
		return nil, err
	}

	return mc.Hash(bytes), nil
}

func verifyManifest(mf *pb.Manifest, pubk p2p_crypto.PubKey) (bool, error) {
	sig := mf.Signature
	mf.Signature = nil
	bytes, err := ggproto.Marshal(mf)
	mf.Signature = sig

	if err != nil {
		return false, err
	}

	return pubk.Verify(bytes, sig)
}
<|endoftext|>


<commit_before>/*
Copyright 2013 Andrew Medworth

This file is part of Gopoker, a set of miscellaneous poker-related functions
written in the Go programming language (http://golang.org).

Gopoker is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Gopoker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gopoker.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
	"flag"
	"fmt"
	"github.com/amdw/gopoker/poker_http"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
)

// Try some sensible defaults to get the static content path
func defaultStaticBaseDir() string {
	// First try something GOPATH-relative as this is most likely to work
	gopath := os.Getenv("GOPATH")
	if gopath != "" {
		gopaths := filepath.SplitList(gopath)
		for _, p := range gopaths {
			candidate := path.Join(p, "src", "github.com", "amdw", "gopoker", "static")
			log.Println("Trying", candidate)
			dirInfo, err := os.Stat(candidate)
			if err == nil && dirInfo.IsDir() {
				return candidate
			}
		}
	}
	// If that didn't work, try the current directory
	currentDir, err := os.Getwd()
	if err != nil {
		log.Println("Warning: could not get current working directory:", err)
		return "./static"
	}
	return path.Join(currentDir, "static")
}

func main() {
	var port int
	var staticBaseDir string
	flag.IntVar(&port, "port", 8080, "Listen port for HTTP server")
	flag.StringVar(&staticBaseDir, "staticbasedir", defaultStaticBaseDir(), "Base directory containing static content")
	flag.Parse()

	dirInfo, err := os.Stat(staticBaseDir)
	if err != nil {
		log.Fatalf("Could not stat static content base dir '%v' - provide it on the command line or ensure GOPATH is set correctly.\n(Error: %v)", staticBaseDir, err)
	}
	if !dirInfo.IsDir() {
		log.Fatalf("staticbasedir '%v' is not a directory", staticBaseDir)
	}

	log.Println("Using static content base dir", staticBaseDir)
	log.Printf("Listening on port %v...\n", port)

	http.HandleFunc("/", poker_http.Menu)
	http.HandleFunc("/holdem/play", poker_http.PlayHoldem)
	http.HandleFunc("/holdem/simulate", poker_http.SimulateHoldem(staticBaseDir))
	http.HandleFunc("/holdem/startingcards", poker_http.StartingCards(staticBaseDir))
	http.HandleFunc("/holdem/startingcards/sim", poker_http.SimulateStartingCards)
	http.HandleFunc("/omaha8/play", poker_http.PlayOmaha8)
	err = http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Update file header<commit_after>/*
Copyright 2013, 2015, 2017 Andrew Medworth

This file is part of Gopoker, a set of miscellaneous poker-related functions
written in the Go programming language (http://golang.org).

Gopoker is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Gopoker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gopoker.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
	"flag"
	"fmt"
	"github.com/amdw/gopoker/poker_http"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
)

// Try some sensible defaults to get the static content path
func defaultStaticBaseDir() string {
	// First try something GOPATH-relative as this is most likely to work
	gopath := os.Getenv("GOPATH")
	if gopath != "" {
		gopaths := filepath.SplitList(gopath)
		for _, p := range gopaths {
			candidate := path.Join(p, "src", "github.com", "amdw", "gopoker", "static")
			log.Println("Trying", candidate)
			dirInfo, err := os.Stat(candidate)
			if err == nil && dirInfo.IsDir() {
				return candidate
			}
		}
	}
	// If that didn't work, try the current directory
	currentDir, err := os.Getwd()
	if err != nil {
		log.Println("Warning: could not get current working directory:", err)
		return "./static"
	}
	return path.Join(currentDir, "static")
}

func main() {
	var port int
	var staticBaseDir string
	flag.IntVar(&port, "port", 8080, "Listen port for HTTP server")
	flag.StringVar(&staticBaseDir, "staticbasedir", defaultStaticBaseDir(), "Base directory containing static content")
	flag.Parse()

	dirInfo, err := os.Stat(staticBaseDir)
	if err != nil {
		log.Fatalf("Could not stat static content base dir '%v' - provide it on the command line or ensure GOPATH is set correctly.\n(Error: %v)", staticBaseDir, err)
	}
	if !dirInfo.IsDir() {
		log.Fatalf("staticbasedir '%v' is not a directory", staticBaseDir)
	}

	log.Println("Using static content base dir", staticBaseDir)
	log.Printf("Listening on port %v...\n", port)

	http.HandleFunc("/", poker_http.Menu)
	http.HandleFunc("/holdem/play", poker_http.PlayHoldem)
	http.HandleFunc("/holdem/simulate", poker_http.SimulateHoldem(staticBaseDir))
	http.HandleFunc("/holdem/startingcards", poker_http.StartingCards(staticBaseDir))
	http.HandleFunc("/holdem/startingcards/sim", poker_http.SimulateStartingCards)
	http.HandleFunc("/omaha8/play", poker_http.PlayOmaha8)
	err = http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"os"
	"io"
	"io/ioutil"
	"github.com/labstack/echo"
	"github.com/labstack/gommon/log"
)

func main() {
	e := echo.New()

	e.GET("/:filename", func(c echo.Context) error {
		file, err := os.Open(c.Param("filename"))
		if err != nil {
			log.Error(err)
			return err
		}
		data, err := ioutil.ReadAll(file)
		if err != nil {
			log.Error(data)
			return err
		}
		mimeType := http.DetectContentType(data)
		return c.Blob(http.StatusOK, mimeType, data)
	})

	e.POST("/", func(c echo.Context) error {
		photo, err := c.FormFile("photo")
		if err != nil {
			log.Error(err)
			return err
		}
		src, err := photo.Open()
		if err != nil {
			log.Error(err)
			return err
		}
		defer src.Close()

		dst, err := os.Create(photo.Filename)
		if err != nil {
			log.Error(err)
			return err
		}
		defer dst.Close()

		if _, err = io.Copy(dst, src); err != nil {
			log.Error(err)
			return err
		}

		return c.NoContent(http.StatusCreated)
	})

	e.PUT("/:filename", func(c echo.Context) error {
		photo, err := c.FormFile("photo")
		if err != nil {
			log.Error(err)
			return err
		}
		src, err := photo.Open()
		if err != nil {
			log.Error(err)
			return err
		}
		defer src.Close()

		dst, err := os.Create(c.Param("filename"))
		if err != nil {
			log.Error(err)
			return err
		}
		defer dst.Close()

		if _, err = io.Copy(dst, src); err != nil {
			log.Error(err)
			return err
		}

		return c.NoContent(http.StatusOK)
	})

	e.DELETE("/:filename", func(c echo.Context) error {
		if err := os.Remove(c.Param("filename")); err != nil {
			log.Error(err)
			return err
		}

		return c.NoContent(http.StatusOK)
	})

	e.Logger.Debug(e.Start(":1323"))
}
<commit_msg>Change filename<commit_after>package main

import (
	"net/http"
	"os"
	"io"
	"io/ioutil"
	"github.com/labstack/echo"
	"github.com/labstack/gommon/log"
	"crypto/md5"
	"fmt"
	"time"
)

type Created struct {
	Id string
}

func main() {
	e := echo.New()

	e.GET("/:id", func(c echo.Context) error {
		file, err := os.Open(c.Param("id"))
		if err != nil {
			log.Error(err)
			return err
		}
		data, err := ioutil.ReadAll(file)
		if err != nil {
			log.Error(data)
			return err
		}
		mimeType := http.DetectContentType(data)
		return c.Blob(http.StatusOK, mimeType, data)
	})

	e.POST("/", func(c echo.Context) error {
		photo, err := c.FormFile("photo")
		if err != nil {
			log.Error(err)
			return err
		}
		src, err := photo.Open()
		if err != nil {
			log.Error(err)
			return err
		}
		defer src.Close()

		data, err := ioutil.ReadAll(src)
		if err != nil {
			log.Error(err)
			return err
		}

		dataHash := fmt.Sprintf("%x", md5.Sum(data))
		filename := fmt.Sprintf("%x", md5.Sum([]byte(dataHash + time.Now().String())))
		dst, err := os.Create(filename)
		if err != nil {
			log.Error(err)
			return err
		}
		defer dst.Close()

		if _, err = io.Copy(dst, src); err != nil {
			log.Error(err)
			return err
		}

		return c.JSON(http.StatusCreated, Created{filename})
	})

	e.PUT("/:id", func(c echo.Context) error {
		photo, err := c.FormFile("photo")
		if err != nil {
			log.Error(err)
			return err
		}
		src, err := photo.Open()
		if err != nil {
			log.Error(err)
			return err
		}
		defer src.Close()

		dst, err := os.Create(c.Param("id"))
		if err != nil {
			log.Error(err)
			return err
		}
		defer dst.Close()

		if _, err = io.Copy(dst, src); err != nil {
			log.Error(err)
			return err
		}

		return c.NoContent(http.StatusOK)
	})

	e.DELETE("/:id", func(c echo.Context) error {
		if err := os.Remove(c.Param("id")); err != nil {
			log.Error(err)
			return err
		}

		return c.NoContent(http.StatusOK)
	})

	e.Logger.Debug(e.Start())
}
<|endoftext|>


<commit_before>package main

import (
	"./rakefile"
)

func main() {
	rakefile.IsFile("rakefile/rakefile.go")
}
<commit_msg>More.<commit_after>package main

import (
	"./rakefile"
	"github.com/codegangsta/cli"
	"os"
)

func main() {
	rakefile.IsFile("rakefile/rakefile.go")
	cli.NewApp().Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"strconv"
	"sync"
	"time"
)
import (
	"github.com/satori/go.uuid"
	"github.com/speps/go-hashids"
)

var rooms = make(map[int]*Room)
var roomsMU sync.Mutex
var counter int = 0

var cards []Card
var HashID *hashids.HashID
var colors = []string{"Magenta", "LightSlateGray", "PaleVioletRed", "Peru", "RebeccaPurple", "LightSeaGreen", "Tomato", "SeaGreen", "Maroon", "GoldenRod", "DarkSlateBlue"}

type Card struct {
	Name string `json:"name"`
	Path string `json:"path"`
}

type Room struct {
	ID        int
	Players   []Player `json:"players"`
	Started   bool     `json:"started"`
	Location  int      `json:"-"`
	Countdown int      `json:"-"`
}

type Player struct {
	Name  string `json:"name"`
	Color string `json:"color"`
	Admin bool   `json:"-"`
	UUID  string `json:"-"`
	Spy   bool   `json:"-"`
}

func (r Room) playerForUUID(uuid string) (p Player, found bool) {
	for _, value := range r.Players {
		if value.UUID == uuid {
			return value, true
		}
	}
	return Player{}, false
}

func (r Room) playerForCookies(cookies []*http.Cookie) (p Player, found bool) {
	if len(cookies) == 0 {
		return Player{}, false
	}

	return r.playerForUUID(cookies[0].Value) // TODO: dont take first cookie, search for spyfall cookie
}

func (r *Room) setup() {
	r.Location = rand.Intn(len(cards))
	spy := rand.Intn(len(r.Players))
	r.Players[spy].Spy = true

	t := int(time.Now().Unix())
	t = t + (60 * 10)
	r.Countdown = t
	r.Started = true
}

func main() {
	var (
		httpAddr = flag.String("http", ":3000", "HTTP service address")
		salt     = flag.String("salt", "super secret salt", "Salt is the secret used to make the generated id harder to guess")
	)
	flag.Parse()

	cardsJSON, _ := ioutil.ReadFile("static/cards/cards.json")
	json.Unmarshal([]byte(cardsJSON), &cards)

	hd := hashids.NewData()
	hd.Salt = *salt
	hd.MinLength = 5
	hd.Alphabet = "abcdefghijklmnopqrstuvwxyz"
	HashID = hashids.NewWithData(hd)

	http.HandleFunc("/room/new", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()

		c, _ := HashID.Encode([]int{counter})

		uuidS := uuid.NewV4().String()
		admin := Player{Name: colors[0], Color: colors[0], Admin: true, UUID: uuidS, Spy: false}
		players := []Player{admin}
		rooms[counter] = &Room{ID: counter, Players: players, Started: false}

		expiration := time.Now().Add(365 * 24 * time.Hour)
		cookie := http.Cookie{Name: "spyfall", Value: uuidS, Path: "/", Expires: expiration}
		http.SetCookie(w, &cookie)
		fmt.Println("created new room", c, counter)

		counter++
		http.Redirect(w, r, "/room?code="+c, 303)
	})

	http.HandleFunc("/room", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()

		c := r.URL.Query().Get("code")

		d := HashID.Decode(c)
		roomID := d[0]
		if room, ok := rooms[roomID]; ok {
			if room.Started {
				http.Redirect(w, r, "/", 303) // TODO: show error message that room already started
				return
			}
			var player Player

			if p, ok := room.playerForCookies(r.Cookies()); ok {
				player = p
			} else {
				uuidS := uuid.NewV4().String()
				color := colors[len(room.Players)]
				player = Player{Name: color, Color: color, Admin: false, UUID: uuidS, Spy: false}

				expiration := time.Now().Add(365 * 24 * time.Hour)
				cookie := http.Cookie{Name: "spyfall", Value: uuidS, Path: "/", Expires: expiration}
				http.SetCookie(w, &cookie)

				room.Players = append(room.Players, player)
			}

			t, _ := template.ParseFiles("static/room.html")
			data := struct {
				ID     int
				Code   string
				Player Player
			}{
				ID: roomID, Code: c, Player: player,
			}
			t.Execute(w, data)
		} else {
			http.Redirect(w, r, "/", 303)
			return
		}
	})

	http.HandleFunc("/game", func(w http.ResponseWriter, r *http.Request) {
		roomIDStr := r.URL.Query().Get("id")
		roomID, err := strconv.Atoi(roomIDStr)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()
		if room, ok := rooms[roomID]; ok {
			if room.Started == false {
				room.setup()
				fmt.Println("Started room", roomID)
			}
			t, _ := template.ParseFiles("static/game.html")
			cookie := r.Cookies()[0]
			uuid := cookie.Value
			player, ok := room.playerForUUID(uuid)
			if !ok {
				http.NotFound(w, r)
				return
			}

			data := struct {
				Spy       bool
				Location  int
				Cards     []Card
				Countdown int
			}{
				Spy: player.Spy, Location: room.Location, Cards: cards, Countdown: room.Countdown,
			}

			t.Execute(w, data)
		} else {
			http.NotFound(w, r)
			return
		}
	})

	http.HandleFunc("/players.json", func(w http.ResponseWriter, r *http.Request) {
		roomIDStr := r.URL.Query().Get("id")
		roomID, err := strconv.Atoi(roomIDStr)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()
		if room, ok := rooms[roomID]; ok {
			js, err := json.Marshal(room)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(js)
		} else {
			http.NotFound(w, r)
			return
		}
	})

	http.Handle("/", http.FileServer(http.Dir("./static")))
	fmt.Println("listen on", *httpAddr)
	log.Fatal(http.ListenAndServe(*httpAddr, nil))
}
<commit_msg>set round time to 8 minutes<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"strconv"
	"sync"
	"time"
)
import (
	"github.com/satori/go.uuid"
	"github.com/speps/go-hashids"
)

var rooms = make(map[int]*Room)
var roomsMU sync.Mutex
var counter int = 0

var cards []Card
var HashID *hashids.HashID
var colors = []string{"Magenta", "LightSlateGray", "PaleVioletRed", "Peru", "RebeccaPurple", "LightSeaGreen", "Tomato", "SeaGreen", "Maroon", "GoldenRod", "DarkSlateBlue"}

type Card struct {
	Name string `json:"name"`
	Path string `json:"path"`
}

type Room struct {
	ID        int
	Players   []Player `json:"players"`
	Started   bool     `json:"started"`
	Location  int      `json:"-"`
	Countdown int      `json:"-"`
}

type Player struct {
	Name  string `json:"name"`
	Color string `json:"color"`
	Admin bool   `json:"-"`
	UUID  string `json:"-"`
	Spy   bool   `json:"-"`
}

func (r Room) playerForUUID(uuid string) (p Player, found bool) {
	for _, value := range r.Players {
		if value.UUID == uuid {
			return value, true
		}
	}
	return Player{}, false
}

func (r Room) playerForCookies(cookies []*http.Cookie) (p Player, found bool) {
	if len(cookies) == 0 {
		return Player{}, false
	}

	return r.playerForUUID(cookies[0].Value) // TODO: dont take first cookie, search for spyfall cookie
}

func (r *Room) setup() {
	r.Location = rand.Intn(len(cards))
	spy := rand.Intn(len(r.Players))
	r.Players[spy].Spy = true

	t := int(time.Now().Unix())
	t = t + (60 * 8)
	r.Countdown = t
	r.Started = true
}

func main() {
	var (
		httpAddr = flag.String("http", ":3000", "HTTP service address")
		salt     = flag.String("salt", "super secret salt", "Salt is the secret used to make the generated id harder to guess")
	)
	flag.Parse()

	cardsJSON, _ := ioutil.ReadFile("static/cards/cards.json")
	json.Unmarshal([]byte(cardsJSON), &cards)

	hd := hashids.NewData()
	hd.Salt = *salt
	hd.MinLength = 5
	hd.Alphabet = "abcdefghijklmnopqrstuvwxyz"
	HashID = hashids.NewWithData(hd)

	http.HandleFunc("/room/new", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()

		c, _ := HashID.Encode([]int{counter})

		uuidS := uuid.NewV4().String()
		admin := Player{Name: colors[0], Color: colors[0], Admin: true, UUID: uuidS, Spy: false}
		players := []Player{admin}
		rooms[counter] = &Room{ID: counter, Players: players, Started: false}

		expiration := time.Now().Add(365 * 24 * time.Hour)
		cookie := http.Cookie{Name: "spyfall", Value: uuidS, Path: "/", Expires: expiration}
		http.SetCookie(w, &cookie)
		fmt.Println("created new room", c, counter)

		counter++
		http.Redirect(w, r, "/room?code="+c, 303)
	})

	http.HandleFunc("/room", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()

		c := r.URL.Query().Get("code")

		d := HashID.Decode(c)
		roomID := d[0]
		if room, ok := rooms[roomID]; ok {
			if room.Started {
				http.Redirect(w, r, "/", 303) // TODO: show error message that room already started
				return
			}
			var player Player

			if p, ok := room.playerForCookies(r.Cookies()); ok {
				player = p
			} else {
				uuidS := uuid.NewV4().String()
				color := colors[len(room.Players)]
				player = Player{Name: color, Color: color, Admin: false, UUID: uuidS, Spy: false}

				expiration := time.Now().Add(365 * 24 * time.Hour)
				cookie := http.Cookie{Name: "spyfall", Value: uuidS, Path: "/", Expires: expiration}
				http.SetCookie(w, &cookie)

				room.Players = append(room.Players, player)
			}

			t, _ := template.ParseFiles("static/room.html")
			data := struct {
				ID     int
				Code   string
				Player Player
			}{
				ID: roomID, Code: c, Player: player,
			}
			t.Execute(w, data)
		} else {
			http.Redirect(w, r, "/", 303)
			return
		}
	})

	http.HandleFunc("/game", func(w http.ResponseWriter, r *http.Request) {
		roomIDStr := r.URL.Query().Get("id")
		roomID, err := strconv.Atoi(roomIDStr)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()
		if room, ok := rooms[roomID]; ok {
			if room.Started == false {
				room.setup()
				fmt.Println("Started room", roomID)
			}
			t, _ := template.ParseFiles("static/game.html")
			cookie := r.Cookies()[0]
			uuid := cookie.Value
			player, ok := room.playerForUUID(uuid)
			if !ok {
				http.NotFound(w, r)
				return
			}

			data := struct {
				Spy       bool
				Location  int
				Cards     []Card
				Countdown int
			}{
				Spy: player.Spy, Location: room.Location, Cards: cards, Countdown: room.Countdown,
			}

			t.Execute(w, data)
		} else {
			http.NotFound(w, r)
			return
		}
	})

	http.HandleFunc("/players.json", func(w http.ResponseWriter, r *http.Request) {
		roomIDStr := r.URL.Query().Get("id")
		roomID, err := strconv.Atoi(roomIDStr)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		roomsMU.Lock()
		defer roomsMU.Unlock()
		if room, ok := rooms[roomID]; ok {
			js, err := json.Marshal(room)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(js)
		} else {
			http.NotFound(w, r)
			return
		}
	})

	http.Handle("/", http.FileServer(http.Dir("./static")))
	fmt.Println("listen on", *httpAddr)
	log.Fatal(http.ListenAndServe(*httpAddr, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net/http"
	"net/url"
	"strings"
	"text/template"

	"github.com/rollbrettler/daily-stars/stars"
)

var port string

func init() {
	flag.StringVar(&port, "port", ":8001", "Port to listen on")
}

func main() {
	flag.Parse()

	http.HandleFunc("/", showStar)
	fs := http.FileServer(http.Dir("assets"))
	http.Handle("/assets/", http.StripPrefix("/assets/", fs))
	http.HandleFunc("/favicon.ico", handleFavicon)
	http.ListenAndServe(port, nil)
}

func handleFavicon(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(""))
}

func showStar(w http.ResponseWriter, r *http.Request) {

	username := username(r.URL)
	log.Printf("%v\n", username)
	s := stars.Stars{
		Username: username,
	}

	repos, err := s.Repos()
	if err != nil {
		w.Write([]byte("Wrong username"))
	}

	t, _ := template.ParseFiles("html/index.html")

	t.Execute(w, repos)
}

func username(s *url.URL) string {
	return strings.SplitN(s.Path, "/", 3)[1]
}
<commit_msg>Add posibility to use env variable for the port<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"text/template"

	"github.com/rollbrettler/daily-stars/stars"
)

var port string

func init() {
	flag.StringVar(&port, "port", ":8001", "Port to listen on")
}

func main() {
	flag.Parse()

	envPort := os.Getenv("PORT")

	if envPort != "" {
		port = ":" + envPort
	}

	http.HandleFunc("/", showStar)
	fs := http.FileServer(http.Dir("assets"))
	http.Handle("/assets/", http.StripPrefix("/assets/", fs))
	http.HandleFunc("/favicon.ico", handleFavicon)
	http.ListenAndServe(port, nil)
}

func handleFavicon(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(""))
}

func showStar(w http.ResponseWriter, r *http.Request) {

	username := username(r.URL)
	log.Printf("%v\n", username)
	s := stars.Stars{
		Username: username,
	}

	repos, err := s.Repos()
	if err != nil {
		w.Write([]byte("Wrong username"))
	}

	t, _ := template.ParseFiles("html/index.html")

	t.Execute(w, repos)
}

func username(s *url.URL) string {
	return strings.SplitN(s.Path, "/", 3)[1]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/drone/routes"
	"log"
	"net/http"
	"os"
	"path"
	"strconv"
)

type HttpSettings struct {
	port int
}

type BitTorrentSettings struct {
	port         int
	downloadRate int
	uploadRate   int
	keepFiles    bool
}

type Settings struct {
	http       HttpSettings
	bitTorrent BitTorrentSettings
}

type Server struct {
	settings Settings
	magnets  map[string]*Magnet
}

func NewServer() *Server {
	return &Server{magnets: make(map[string]*Magnet)}
}

var server = NewServer()

func (server *Server) Run() {
	log.Println("[HTTP] Starting on port", server.settings.http.port)

	mux := routes.New()
	mux.Get("/add", add)
	mux.Get("/files/:infohash", files)
	mux.Get("/files/:infohash/:file", files)
	mux.Get("/shutdown", shutdown)

	http.Handle("/", mux)
	http.ListenAndServe(":"+strconv.Itoa(server.settings.http.port), nil)
}

func add(w http.ResponseWriter, r *http.Request) {
	magnetLink := r.URL.Query().Get("magnet")

	downloadDir := r.URL.Query().Get("download_dir")
	if downloadDir == "" {
		downloadDir = "."
	}

	if magnetLink != "" {
		magnet := NewMagnet(magnetLink, downloadDir)
		magnet.Files = append(magnet.Files, NewMagnetFile("Guardians of the Galaxy (2014).mp4"))
		server.magnets[magnetLink] = magnet

		log.Printf("[HTTP] Downloading %s to %s\n", magnetLink, downloadDir)
		fmt.Fprintf(w, "")
	} else {
		http.Error(w, "Missing Magnet link", http.StatusBadRequest)
	}
}

func files(w http.ResponseWriter, r *http.Request) {
	infoHash := r.URL.Query().Get(":infohash")
	file := r.URL.Query().Get(":file")

	if magnet, ok := server.magnets[infoHash]; ok {
		if file != "" {
			r.URL.Path = file
			log.Printf("[HTTP] Serving %s: %s\n", magnet.InfoHash, path.Join(magnet.DownloadDir, file))
			http.FileServer(MagnetFileSystem{magnet}).ServeHTTP(w, r)
		} else {
			log.Println("[HTTP] Listing", magnet.InfoHash)
			routes.ServeJson(w, magnet)
		}
	} else {
		http.Error(w, "Invalid Magnet info hash", http.StatusNotFound)
	}
}

func shutdown(w http.ResponseWriter, r *http.Request) {
	log.Println("[HTTP] Shutting down")
	os.Exit(0)
}
<commit_msg>Add /files endpoint to list all active magnet links<commit_after>package main

import (
	"fmt"
	"github.com/drone/routes"
	"log"
	"net/http"
	"os"
	"path"
	"strconv"
)

type HttpSettings struct {
	port int
}

type BitTorrentSettings struct {
	port         int
	downloadRate int
	uploadRate   int
	keepFiles    bool
}

type Settings struct {
	http       HttpSettings
	bitTorrent BitTorrentSettings
}

type Server struct {
	settings Settings
	magnets  map[string]*Magnet
}

func NewServer() *Server {
	return &Server{magnets: make(map[string]*Magnet)}
}

var server = NewServer()

func (server *Server) Run() {
	log.Println("[HTTP] Starting on port", server.settings.http.port)

	mux := routes.New()
	mux.Get("/add", add)
	mux.Get("/files", files)
	mux.Get("/files/:infohash", files)
	mux.Get("/files/:infohash/:file", files)
	mux.Get("/shutdown", shutdown)

	http.Handle("/", mux)
	http.ListenAndServe(":"+strconv.Itoa(server.settings.http.port), nil)
}

func add(w http.ResponseWriter, r *http.Request) {
	magnetLink := r.URL.Query().Get("magnet")

	downloadDir := r.URL.Query().Get("download_dir")
	if downloadDir == "" {
		downloadDir = "."
	}

	if magnetLink != "" {
		magnet := NewMagnet(magnetLink, downloadDir)
		magnet.Files = append(magnet.Files, NewMagnetFile("Guardians of the Galaxy (2014).mp4"))
		server.magnets[magnetLink] = magnet

		log.Printf("[HTTP] Downloading %s to %s\n", magnetLink, downloadDir)
		fmt.Fprintf(w, "")
	} else {
		http.Error(w, "Missing Magnet link", http.StatusBadRequest)
	}
}

func files(w http.ResponseWriter, r *http.Request) {
	infoHash := r.URL.Query().Get(":infohash")
	file := r.URL.Query().Get(":file")

	if infoHash != "" {
		if magnet, ok := server.magnets[infoHash]; ok {
			if file != "" {
				r.URL.Path = file
				log.Printf("[HTTP] Serving %s: %s\n", magnet.InfoHash, path.Join(magnet.DownloadDir, file))
				http.FileServer(MagnetFileSystem{magnet}).ServeHTTP(w, r)
			} else {
				log.Println("[HTTP] Listing", magnet.InfoHash)
				routes.ServeJson(w, magnet)
			}
		} else {
			http.Error(w, "Invalid Magnet info hash", http.StatusNotFound)
		}
	} else {
		log.Println("[HTTP] Listing all Magnets")
		routes.ServeJson(w, server.magnets)
	}
}

func shutdown(w http.ResponseWriter, r *http.Request) {
	log.Println("[HTTP] Shutting down")
	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"syscall"
	"time"

	yaml "gopkg.in/yaml.v1"

	"github.com/fsnotify/fsnotify"
)

const (
	cfgPath = "/etc/nginx-static/config"
	tplPath = "/etc/nginx/nginx.conf.tpl"
	outPath = "/etc/nginx/nginx.conf"
)

func main() {
	err := do()
	if err != nil {
		log.Fatal(err)
	}
}

func do() error {
	tpl, err := template.ParseFiles(tplPath)
	if err != nil {
		return err
	}

	// Write initial config
	err = writeConfig(tpl)
	if err != nil {
		return err
	}

	// Start nginx
	cmd := exec.Command("/usr/sbin/nginx", "-g", "daemon off;")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		return err
	}

	// Shutdown listener
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGTERM)

	// Config watcher
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return err
	}

	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
				if event.Op&fsnotify.Write == fsnotify.Write {
					log.Println("modified file:", event.Name)
					err := process(tpl, cmd)
					if err != nil {
						log.Printf("Failed to process config: %s", err)
					}
				}
			case err := <-watcher.Errors:
				log.Printf("Config watch error: %s", err)

			case <-stop:
				// Wait for a while
				time.Sleep(30 * time.Second)
				err := cmd.Process.Signal(syscall.SIGINT)
				if err != nil {
					log.Println(err)
				}
				return
			}
		}
	}()

	err = watcher.Add(cfgPath)
	if err != nil {
		return err
	}

	return cmd.Wait()
}

type SiteConfig struct {
	Host     string `yaml:"host"`
	Root     string `yaml:"root"`
	Redirect string `yaml:"redirect"`
}

func writeConfig(tpl *template.Template) error {
	cfg, err := os.Open(cfgPath)
	if err != nil {
		return err
	}
	defer cfg.Close()

	hosts, err := getConfig(cfg)
	if err != nil {
		return err
	}

	fp, err := os.Create(outPath)
	if err != nil {
		return err
	}
	defer fp.Close()

	return tpl.Execute(fp, hosts)
}

func getConfig(in io.Reader) ([]SiteConfig, error) {
	hosts := make([]SiteConfig, 0)

	b, err := ioutil.ReadAll(in)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(b, &hosts)
	if err != nil {
		return nil, err
	}

	return hosts, nil
}

func process(tpl *template.Template, cmd *exec.Cmd) error {
	err := writeConfig(tpl)
	if err != nil {
		return err
	}

	// Trigger reload of config
	return cmd.Process.Signal(syscall.SIGHUP)
}
<commit_msg>Process config on any change<commit_after>package main

import (
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"syscall"
	"time"

	yaml "gopkg.in/yaml.v1"

	"github.com/fsnotify/fsnotify"
)

const (
	cfgPath = "/etc/nginx-static/config"
	tplPath = "/etc/nginx/nginx.conf.tpl"
	outPath = "/etc/nginx/nginx.conf"
)

func main() {
	err := do()
	if err != nil {
		log.Fatal(err)
	}
}

func do() error {
	tpl, err := template.ParseFiles(tplPath)
	if err != nil {
		return err
	}

	// Write initial config
	err = writeConfig(tpl)
	if err != nil {
		return err
	}

	// Start nginx
	cmd := exec.Command("/usr/sbin/nginx", "-g", "daemon off;")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		return err
	}

	// Shutdown listener
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGTERM)

	// Config watcher
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return err
	}

	go func() {
		for {
			select {
			case <-watcher.Events:
				err := process(tpl, cmd)
				if err != nil {
					log.Printf("Failed to process config: %s", err)
				}
			case err := <-watcher.Errors:
				log.Printf("Config watch error: %s", err)
			case <-stop:
				// Wait for a while
				time.Sleep(30 * time.Second)
				err := cmd.Process.Signal(syscall.SIGINT)
				if err != nil {
					log.Println(err)
				}
				return
			}
		}
	}()

	err = watcher.Add(cfgPath)
	if err != nil {
		return err
	}

	return cmd.Wait()
}

type SiteConfig struct {
	Host     string `yaml:"host"`
	Root     string `yaml:"root"`
	Redirect string `yaml:"redirect"`
}

func writeConfig(tpl *template.Template) error {
	cfg, err := os.Open(cfgPath)
	if err != nil {
		return err
	}
	defer cfg.Close()

	hosts, err := getConfig(cfg)
	if err != nil {
		return err
	}

	fp, err := os.Create(outPath)
	if err != nil {
		return err
	}
	defer fp.Close()

	return tpl.Execute(fp, hosts)
}

func getConfig(in io.Reader) ([]SiteConfig, error) {
	hosts := make([]SiteConfig, 0)

	b, err := ioutil.ReadAll(in)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(b, &hosts)
	if err != nil {
		return nil, err
	}

	return hosts, nil
}

func process(tpl *template.Template, cmd *exec.Cmd) error {
	err := writeConfig(tpl)
	if err != nil {
		return err
	}

	// Trigger reload of config
	return cmd.Process.Signal(syscall.SIGHUP)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"os"
	"strings"
	"io/ioutil"
	"log/syslog"

  log "github.com/Sirupsen/logrus"
  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
	"golang.org/x/crypto/ssh"
  "github.com/rifflock/lfshook"
  "github.com/codegangsta/cli"
	// "github.com/davecgh/go-spew/spew"
)

func setupLogging(logToSyslog bool, logFile string) {
  logLevel := log.InfoLevel
  if os.Getenv("DEBUG") == "true" { logLevel = log.DebugLevel }
  log.SetLevel(logLevel)

	log.SetFormatter(&log.TextFormatter{DisableColors: true})

	if (logToSyslog) { setupSyslogLogging() }
	if (len(logFile) > 0) { setupFileLogging(logFile) }
}

func setupSyslogLogging() {
	log.Debugf("Logging to syslog")
	logrusSysLogHook, err := logrus_syslog.NewSyslogHook("", "localhost:514", syslog.LOG_INFO, "sshoney")
	if err != nil { log.Fatalf("Failed to add syslog logrus hook - %s", err) }
	log.AddHook(logrusSysLogHook)
}

func setupFileLogging(logFile string) {
	log.Debugf("Logging to %s", logFile)
	logrusFileHook := lfshook.NewHook(lfshook.PathMap{
	  log.InfoLevel : logFile, log.WarnLevel : logFile, log.ErrorLevel : logFile, log.FatalLevel : logFile, log.PanicLevel : logFile,
  })
	log.AddHook(logrusFileHook)
}

func setupSSHListener(port string, hostKey string) (ssh.ServerConfig, net.Listener) {
	sshConfig := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			remoteAddr := c.RemoteAddr().String()
			ip := remoteAddr[0:strings.Index(remoteAddr, ":")]
			log.Printf("SSH connection from ip=[%s], username=[%s], password=[%s], version=[%s]", ip, c.User(), pass, c.ClientVersion())
			return nil, fmt.Errorf("invalid credentials")
		},
	}

	privateBytes, err := ioutil.ReadFile(hostKey)
	if err != nil { log.Fatalf("Failed to load private key %s.  Run make gen_ssh_key %s", hostKey, hostKey) }

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil { log.Fatal("Failed to parse private key") }
	sshConfig.AddHostKey(private)

  portComplete := fmt.Sprintf(":%s", port)
	listener, err := net.Listen("tcp4", portComplete)
	if err != nil { log.Fatalf("failed to listen on *:%s", port) }

	log.Printf("listening on %s", port)

	return *sshConfig, listener;
}

func processConnections(sshConfig *ssh.ServerConfig, listener net.Listener) {
	for {
		tcpConn, err := listener.Accept()
		if err != nil {
			log.Debugf("failed to accept incoming connection (%s)", err)
			continue
		}
		go handleConnection(sshConfig, tcpConn)
	}
}

func handleConnection(sshConfig *ssh.ServerConfig, tcpConn net.Conn) {
	defer tcpConn.Close()
	log.Debugf("new TCP connection from %s", tcpConn.RemoteAddr())

	sshConn, _, _, err := ssh.NewServerConn(tcpConn, sshConfig)
	if err != nil {
		log.Debugf("failed to handshake (%s)", err)
	} else {
		sshConn.Close()
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "sshoney"
	app.Usage = "SSH honeypot"
	app.Version = "0.1.0"

	app.Flags = []cli.Flag {
		cli.BoolFlag{ Name: "log-to-syslog", Usage: "log to syslog" },
		cli.StringFlag{
	    Name: "port",
	    Usage: "port to listen on",
			Value: "2222",
			EnvVar: "PORT",
	  },
		cli.StringFlag{
	    Name: "host-key",
	    Usage: "SSH private host key",
			Value: "host.key",
			EnvVar: "HOST_KEY",
	  },
	  cli.StringFlag{
	    Name: "log-file",
	    Usage: "path to logfile",
			EnvVar: "LOG_FILE",
	  },
	}

	app.Action = func(c *cli.Context) {
		setupLogging(c.Bool("log-to-syslog"), c.String("log-file"))
		sshConfig, listener := setupSSHListener(c.String("port"), c.String("host-key"))
		processConnections(&sshConfig, listener)
	}

	app.Run(os.Args)
}
<commit_msg>Support the ability to define the syslog addr and program name<commit_after>package main

import (
	"fmt"
	"net"
	"os"
	"strings"
	"io/ioutil"
	"log/syslog"

  log "github.com/Sirupsen/logrus"
  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
	"golang.org/x/crypto/ssh"
  "github.com/rifflock/lfshook"
  "github.com/codegangsta/cli"
	// "github.com/davecgh/go-spew/spew"
)

func setupLogging(logToSyslog bool, syslogAddr string, syslogProgramName string, logFile string) {
  logLevel := log.InfoLevel
  if os.Getenv("DEBUG") == "true" { logLevel = log.DebugLevel }
  log.SetLevel(logLevel)

	log.SetFormatter(&log.TextFormatter{DisableColors: true})

	if (logToSyslog)      { setupSyslogLogging(syslogAddr, syslogProgramName) }
	if (len(logFile) > 0) { setupFileLogging(logFile) }
}

func setupSyslogLogging(syslogAddr string, syslogProgramName string) {
	log.Printf("Logging to syslog addr=[%s], program_name=[%s]", syslogAddr, syslogProgramName)
	logrusSysLogHook, err := logrus_syslog.NewSyslogHook("udp", syslogAddr, syslog.LOG_INFO, syslogProgramName)
	if err != nil { log.Fatalf("Failed to add syslog logrus hook - %s", err) }
	log.AddHook(logrusSysLogHook)
}

func setupFileLogging(logFile string) {
	log.Printf("Logging to file=[%s]", logFile)
	logrusFileHook := lfshook.NewHook(lfshook.PathMap{
	  log.InfoLevel : logFile, log.WarnLevel : logFile, log.ErrorLevel : logFile, log.FatalLevel : logFile, log.PanicLevel : logFile,
  })
	log.AddHook(logrusFileHook)
}

func setupSSHListener(port string, hostKey string) (ssh.ServerConfig, net.Listener) {
	sshConfig := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			remoteAddr := c.RemoteAddr().String()
			ip := remoteAddr[0:strings.Index(remoteAddr, ":")]
			log.Printf("SSH connection from ip=[%s], username=[%s], password=[%s], version=[%s]", ip, c.User(), pass, c.ClientVersion())
			return nil, fmt.Errorf("invalid credentials")
		},
	}

	privateBytes, err := ioutil.ReadFile(hostKey)
	if err != nil { log.Fatalf("Failed to load private key %s.  Run make gen_ssh_key %s", hostKey, hostKey) }

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil { log.Fatal("Failed to parse private key") }
	sshConfig.AddHostKey(private)

  portComplete := fmt.Sprintf(":%s", port)
	listener, err := net.Listen("tcp4", portComplete)
	if err != nil { log.Fatalf("failed to listen on *:%s", port) }

	log.Printf("listening on %s", port)

	return *sshConfig, listener;
}

func processConnections(sshConfig *ssh.ServerConfig, listener net.Listener) {
	for {
		tcpConn, err := listener.Accept()
		if err != nil {
			log.Debugf("failed to accept incoming connection (%s)", err)
			continue
		}
		go handleConnection(sshConfig, tcpConn)
	}
}

func handleConnection(sshConfig *ssh.ServerConfig, tcpConn net.Conn) {
	defer tcpConn.Close()
	log.Debugf("new TCP connection from %s", tcpConn.RemoteAddr())

	sshConn, _, _, err := ssh.NewServerConn(tcpConn, sshConfig)
	if err != nil {
		log.Debugf("failed to handshake (%s)", err)
	} else {
		sshConn.Close()
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "sshoney"
	app.Usage = "SSH honeypot"
	app.Version = "0.1.0"

	app.Flags = []cli.Flag {
		cli.BoolFlag{ Name: "log-to-syslog", Usage: "log to syslog" },
		cli.StringFlag{
	    Name: "port",
	    Usage: "port to listen on",
			Value: "2222",
			EnvVar: "PORT",
	  },
		cli.StringFlag{
	    Name: "syslog-addr",
	    Usage: "host:port of the syslog server",
			Value: "localhost:514",
			EnvVar: "SYSLOG_ADDR",
	  },
		cli.StringFlag{
	    Name: "syslog-program-name",
	    Usage: "syslog program name to use",
			Value: "sshoney",
			EnvVar: "SYSLOG_PROGRAM_NAME",
	  },
		cli.StringFlag{
	    Name: "host-key",
	    Usage: "SSH private host key",
			Value: "host.key",
			EnvVar: "HOST_KEY",
	  },
	  cli.StringFlag{
	    Name: "log-file",
	    Usage: "path to logfile",
			EnvVar: "LOG_FILE",
	  },
	}

	app.Action = func(c *cli.Context) {
		setupLogging(c.Bool("log-to-syslog"), c.String("syslog-addr"), c.String("syslog-program-name"), c.String("log-file"))
		sshConfig, listener := setupSSHListener(c.String("port"), c.String("host-key"))
		processConnections(&sshConfig, listener)
	}

	app.Run(os.Args)
}
<|endoftext|>


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

package main

import (
	"log"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	pzlogger "github.com/venicegeo/pz-logger/logger"
	pzuuidgen "github.com/venicegeo/pz-uuidgen/uuidgen"
	pzworkflow "github.com/venicegeo/pz-workflow/workflow"
)

func main() {
	sys, logger, uuidgen := makeSystem()

	logger.Info("pz-workflow starting...")

	indices := makeIndexes(sys)

	workflowServer := makeWorkflow(sys, indices, logger, uuidgen)

	serverLoop(sys, workflowServer)
}

func makeWorkflow(sys *piazza.SystemConfig,
	indices []*elasticsearch.Index,
	logger *pzlogger.Client,
	uuidgen *pzuuidgen.Client) *pzworkflow.Server {
	workflowService := &pzworkflow.Service{}
	err := workflowService.Init(
		sys,
		logger,
		uuidgen,
		indices[0],
		indices[1],
		indices[2],
		indices[3],
		indices[4],
		indices[5])
	if err != nil {
		log.Fatal(err)
	}

	err = workflowService.InitCron()
	if err != nil {
		log.Fatal(err)
	}

	workflowServer := &pzworkflow.Server{}
	err = workflowServer.Init(workflowService)
	if err != nil {
		log.Fatal(err)
	}

	return workflowServer
}

func makeSystem() (
	*piazza.SystemConfig,
	*pzlogger.Client,
	*pzuuidgen.Client) {

	required := []piazza.ServiceName{
		piazza.PzElasticSearch,
		piazza.PzLogger,
		piazza.PzUuidgen,
		piazza.PzKafka,
		piazza.PzServiceController,
	}

	sys, err := piazza.NewSystemConfig(piazza.PzWorkflow, required)
	if err != nil {
		log.Fatal(err)
	}

	logger, err := pzlogger.NewClient(sys)
	if err != nil {
		log.Fatal(err)
	}

	uuidgen, err := pzuuidgen.NewClient(sys)
	if err != nil {
		log.Fatal(err)
	}

	return sys, logger, uuidgen
}

func serverLoop(sys *piazza.SystemConfig,
	workflowServer *pzworkflow.Server) {
	genericServer := piazza.GenericServer{Sys: sys}

	err := genericServer.Configure(workflowServer.Routes)
	if err != nil {
		log.Fatal(err)
	}

	done, err := genericServer.Start()
	if err != nil {
		log.Fatal(err)
	}

	err = <-done
	if err != nil {
		log.Fatal(err)
	}
}

func makeIndexes(sys *piazza.SystemConfig) []*elasticsearch.Index {
	eventtypesIndex, err := elasticsearch.NewIndex(sys, "eventtypes003", pzworkflow.EventTypeIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	eventsIndex, err := elasticsearch.NewIndex(sys, "events004", pzworkflow.EventIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	triggersIndex, err := elasticsearch.NewIndex(sys, "triggers003", pzworkflow.TriggerIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	alertsIndex, err := elasticsearch.NewIndex(sys, "alerts003", pzworkflow.AlertIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	cronIndex, err := elasticsearch.NewIndex(sys, "crons003", pzworkflow.CronIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	testElasticsearchIndex, err := elasticsearch.NewIndex(sys, "testelasticsearch003", pzworkflow.TestElasticsearchSettings)
	if err != nil {
		log.Fatal(err)
	}

	ret := []*elasticsearch.Index{
		eventtypesIndex, eventsIndex, triggersIndex,
		alertsIndex, cronIndex, testElasticsearchIndex,
	}
	return ret
}
<commit_msg>compile fix<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"log"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	pzlogger "github.com/venicegeo/pz-logger/logger"
	pzuuidgen "github.com/venicegeo/pz-uuidgen/uuidgen"
	pzworkflow "github.com/venicegeo/pz-workflow/workflow"
)

func main() {
	sys, logger, uuidgen := makeSystem()

	log.Printf("pz-workflow starting...")

	indices := makeIndexes(sys)

	workflowServer := makeWorkflow(sys, indices, logger, uuidgen)

	serverLoop(sys, workflowServer)
}

func makeWorkflow(sys *piazza.SystemConfig,
	indices []*elasticsearch.Index,
	logger *pzlogger.Client,
	uuidgen *pzuuidgen.Client) *pzworkflow.Server {
	workflowService := &pzworkflow.Service{}
	err := workflowService.Init(
		sys,
		logger,
		uuidgen,
		indices[0],
		indices[1],
		indices[2],
		indices[3],
		indices[4],
		indices[5])
	if err != nil {
		log.Fatal(err)
	}

	err = workflowService.InitCron()
	if err != nil {
		log.Fatal(err)
	}

	workflowServer := &pzworkflow.Server{}
	err = workflowServer.Init(workflowService)
	if err != nil {
		log.Fatal(err)
	}

	return workflowServer
}

func makeSystem() (
	*piazza.SystemConfig,
	*pzlogger.Client,
	*pzuuidgen.Client) {

	required := []piazza.ServiceName{
		piazza.PzElasticSearch,
		piazza.PzLogger,
		piazza.PzUuidgen,
		piazza.PzKafka,
		piazza.PzServiceController,
	}

	sys, err := piazza.NewSystemConfig(piazza.PzWorkflow, required)
	if err != nil {
		log.Fatal(err)
	}

	logger, err := pzlogger.NewClient(sys)
	if err != nil {
		log.Fatal(err)
	}

	uuidgen, err := pzuuidgen.NewClient(sys)
	if err != nil {
		log.Fatal(err)
	}

	return sys, logger, uuidgen
}

func serverLoop(sys *piazza.SystemConfig,
	workflowServer *pzworkflow.Server) {
	genericServer := piazza.GenericServer{Sys: sys}

	err := genericServer.Configure(workflowServer.Routes)
	if err != nil {
		log.Fatal(err)
	}

	done, err := genericServer.Start()
	if err != nil {
		log.Fatal(err)
	}

	err = <-done
	if err != nil {
		log.Fatal(err)
	}
}

func makeIndexes(sys *piazza.SystemConfig) []*elasticsearch.Index {
	eventtypesIndex, err := elasticsearch.NewIndex(sys, "eventtypes003", pzworkflow.EventTypeIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	eventsIndex, err := elasticsearch.NewIndex(sys, "events004", pzworkflow.EventIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	triggersIndex, err := elasticsearch.NewIndex(sys, "triggers003", pzworkflow.TriggerIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	alertsIndex, err := elasticsearch.NewIndex(sys, "alerts003", pzworkflow.AlertIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	cronIndex, err := elasticsearch.NewIndex(sys, "crons003", pzworkflow.CronIndexSettings)
	if err != nil {
		log.Fatal(err)
	}
	testElasticsearchIndex, err := elasticsearch.NewIndex(sys, "testelasticsearch003", pzworkflow.TestElasticsearchSettings)
	if err != nil {
		log.Fatal(err)
	}

	ret := []*elasticsearch.Index{
		eventtypesIndex, eventsIndex, triggersIndex,
		alertsIndex, cronIndex, testElasticsearchIndex,
	}
	return ret
}
<|endoftext|>


<commit_before>/*
 * Copyright 2018 The original author or authors
 *
 * 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"
	"os"

	"github.com/projectriff/riff/pkg/core"

	"github.com/projectriff/riff/cmd/commands"
)

var (
	builder         = "projectriff/builder"
	defaultRunImage = "packs/run"

	manifests = map[string]*core.Manifest{
		"latest": {
			ManifestVersion: "0.1",
			Istio: []string{
				"https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml",
			},
			Knative: []string{
				"https://storage.googleapis.com/knative-releases/build/latest/release.yaml",
				"https://storage.googleapis.com/knative-releases/serving/latest/serving.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181106-a99376f/release.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181106-a99376f/release-clusterbus-stub.yaml",
			},
			Namespace: []string{
				"https://storage.googleapis.com/projectriff/riff-buildtemplate/riff-cnb-buildtemplate.yaml",
			},
		},
		"stable": {
			ManifestVersion: "0.1",
			Istio: []string{
				"https://storage.googleapis.com/knative-releases/serving/previous/v0.2.2/istio.yaml",
			},
			Knative: []string{
				"https://storage.googleapis.com/knative-releases/build/previous/v0.2.0/release.yaml",
				"https://storage.googleapis.com/knative-releases/serving/previous/v0.2.2/serving.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181031-a2f9417/release.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181031-a2f9417/release-clusterbus-stub.yaml",
			},
			Namespace: []string{
				"https://storage.googleapis.com/projectriff/riff-buildtemplate/riff-cnb-buildtemplate-0.0.1-snapshot-ci-a28efbae0dcb.yaml",
			},
		},
	}
)

func main() {

	root := commands.CreateAndWireRootCommand(manifests, builder, defaultRunImage)

	sub, err := root.ExecuteC()
	if err != nil {
		if !sub.SilenceUsage { // May have been switched to true once we're past PreRunE()
			sub.Help()
		}
		fmt.Fprintf(os.Stderr, "\nError: %v\n", err)
		os.Exit(1)
	}
}
<commit_msg>Use released version v0.1.0 of BuildTemplate<commit_after>/*
 * Copyright 2018 The original author or authors
 *
 * 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"
	"os"

	"github.com/projectriff/riff/pkg/core"

	"github.com/projectriff/riff/cmd/commands"
)

var (
	builder         = "projectriff/builder"
	defaultRunImage = "packs/run"

	manifests = map[string]*core.Manifest{
		"latest": {
			ManifestVersion: "0.1",
			Istio: []string{
				"https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml",
			},
			Knative: []string{
				"https://storage.googleapis.com/knative-releases/build/latest/release.yaml",
				"https://storage.googleapis.com/knative-releases/serving/latest/serving.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181106-a99376f/release.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181106-a99376f/release-clusterbus-stub.yaml",
			},
			Namespace: []string{
				"https://storage.googleapis.com/projectriff/riff-buildtemplate/riff-cnb-buildtemplate.yaml",
			},
		},
		"stable": {
			ManifestVersion: "0.1",
			Istio: []string{
				"https://storage.googleapis.com/knative-releases/serving/previous/v0.2.2/istio.yaml",
			},
			Knative: []string{
				"https://storage.googleapis.com/knative-releases/build/previous/v0.2.0/release.yaml",
				"https://storage.googleapis.com/knative-releases/serving/previous/v0.2.2/serving.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181031-a2f9417/release.yaml",
				"https://storage.googleapis.com/knative-releases/eventing/previous/v20181031-a2f9417/release-clusterbus-stub.yaml",
			},
			Namespace: []string{
				"https://storage.googleapis.com/projectriff/riff-buildtemplate/riff-cnb-buildtemplate-0.1.0.yaml",
			},
		},
	}
)

func main() {

	root := commands.CreateAndWireRootCommand(manifests, builder, defaultRunImage)

	sub, err := root.ExecuteC()
	if err != nil {
		if !sub.SilenceUsage { // May have been switched to true once we're past PreRunE()
			sub.Help()
		}
		fmt.Fprintf(os.Stderr, "\nError: %v\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/VividCortex/pm"
	"flag"
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var statuses = []string{"starting",
	"waiting for requests",
	"accepting request",
	"receiving data",
	"querying database",
	"sending data",
	"sending response",
}

var pid = 0
var mutex sync.Mutex

var wg sync.WaitGroup
var mapPack map[string]interface{}

//attributes *map[string]interface{}
func SomeProcess() {
	wg.Add(1)
	go func() {
		mutex.Lock()
		pid++
		id := fmt.Sprint(pid)
		fmt.Println("ID: " + id)
		mutex.Unlock()

		defer func() {
			if r := recover(); r != nil {
				fmt.Printf("pid [%s] cancelled\n", id)
			}
			wg.Done()
		}()

		// --- Generate a new, random Map ---
		attributes:=packValues();

		// --- Pass the map ---
		pm.Start(id, nil, &attributes)
		defer pm.Done(id)

		for _, status := range statuses {
			time.Sleep(time.Duration((rand.Int()) % 7000 * int(time.Millisecond)))
			pm.Status(id, status)
		}

		SomeProcess()
	}()

}

// --- Not Inclusive of Maximum ---
func randInt(min int , max int) int {
        rand.Seed( time.Now().UTC().UnixNano())
        return min + rand.Intn(max-min)
}

func packValues() map[string]interface{} {

	// --- Initialization ---
	theMap:=make(map[string]interface{})

	// --- The 'bank' of values to pull from ---
	taste := [] string{
		"salty",
		"sweet",
		"sour",
	}
	color := [] string{
		"red",
		"green",
		"blue",
	}
	temperature := [] string{
		"hot",
		"medium",
		"cold",
	}

	// --- Randomize the Attributes ---
	numAttrs := randInt(1, 4)
	for i:=0; i<numAttrs; i++ {
		d1 := randInt(1,4)
		d2 := randInt(0,3)
		switch d1 {
			case 1: theMap["Taste"]=taste[d2]
			case 2: theMap["Color"]=color[d2]
			case 3: theMap["Temperature"]=temperature[d2]
		}
	}
	return theMap
}

func main() {

	// --- Command Line Parsing ---
	port := flag.String("port", ":8081", "port string (ex. :8081)")
	flag.Parse()

	go pm.ListenAndServe(*port)

	// --- Command Line Checking ---
	fmt.Printf("Listening on localhost%s\n", *port)

	// --- Creating a ProcList of size 'i' ---
	for i := 0; i < 10; i++ {
		SomeProcess()
	}

	wg.Wait()
}
<commit_msg>Removed superfluous output and comments<commit_after>package main

import (
	"github.com/VividCortex/pm"
	"flag"
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var statuses = []string{"starting",
	"waiting for requests",
	"accepting request",
	"receiving data",
	"querying database",
	"sending data",
	"sending response",
}

var pid = 0
var mutex sync.Mutex

var wg sync.WaitGroup
var mapPack map[string]interface{}

func SomeProcess() {
	wg.Add(1)
	go func() {
		mutex.Lock()
		pid++
		id := fmt.Sprint(pid)
		mutex.Unlock()

		defer func() {
			if r := recover(); r != nil {
				fmt.Printf("pid [%s] cancelled\n", id)
			}
			wg.Done()
		}()

		// --- Generate a new, random Map ---
		attributes:=packValues();

		// --- Pass the map ---
		pm.Start(id, nil, &attributes)
		defer pm.Done(id)

		for _, status := range statuses {
			time.Sleep(time.Duration((rand.Int()) % 7000 * int(time.Millisecond)))
			pm.Status(id, status)
		}

		SomeProcess()
	}()

}

// --- Not Inclusive of Maximum ---
func randInt(min int , max int) int {
        rand.Seed( time.Now().UTC().UnixNano())
        return min + rand.Intn(max-min)
}

func packValues() map[string]interface{} {

	// --- Initialization ---
	theMap:=make(map[string]interface{})

	// --- The 'bank' of values to pull from ---
	taste := [] string{
		"salty",
		"sweet",
		"sour",
	}
	color := [] string{
		"red",
		"green",
		"blue",
	}
	temperature := [] string{
		"hot",
		"medium",
		"cold",
	}

	// --- Randomize the Attributes ---
	numAttrs := randInt(1, 4)
	for i:=0; i<numAttrs; i++ {
		d1 := randInt(1,4)
		d2 := randInt(0,3)
		switch d1 {
			case 1: theMap["Taste"]=taste[d2]
			case 2: theMap["Color"]=color[d2]
			case 3: theMap["Temperature"]=temperature[d2]
		}
	}
	return theMap
}

func main() {

	// --- Command Line Parsing ---
	port := flag.String("port", ":8081", "port string (ex. :8081)")
	flag.Parse()

	go pm.ListenAndServe(*port)

	// --- Command Line Checking ---
	fmt.Printf("Listening on localhost%s\n", *port)

	// --- Creating a ProcList of size 'i' ---
	for i := 0; i < 10; i++ {
		SomeProcess()
	}

	wg.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/pkg/profile"
	"github.com/verath/archipelago/lib"
	"net/http"
	"os"
	"os/signal"
	"path"
	"time"
)

const (
	httpReadTimeout  = 10 * time.Second
	httpWriteTimeout = 10 * time.Second
)

func main() {
	var (
		debug       bool
		serveStatic bool
		serverAddr  string
		profileMode string
	)
	flag.BoolVar(&debug, "debug", false, "Set to true to log debug messages.")
	flag.BoolVar(&serveStatic, "servestatic", false, "Enable serving of static assets.")
	flag.StringVar(&serverAddr, "addr", ":8080", "TCP address for the http server to listen on.")
	flag.StringVar(&profileMode, "profile", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
	flag.Parse()

	logger := logrus.New()
	logger.Formatter = &logrus.TextFormatter{}
	if debug {
		logger.Level = logrus.DebugLevel
	}
	// Setup profiling, if profile flag was set
	switch profileMode {
	case "cpu":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.BlockProfile).Stop()
	default:
	}

	archipelagoServer, err := archipelago.New(logger)
	if err != nil {
		logger.Fatalf("Error creating game: %+v", err)
	}

	http.Handle("/ws", archipelagoServer.WebsocketHandler())
	if serveStatic {
		staticPath := "./web/dist"
		// Explicitly set a max-age of 0 for service worker script.
		http.HandleFunc("/sw.js", func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Cache-Control", "max-age=0")
			http.ServeFile(w, r, path.Join(staticPath, "sw.js"))
		})
		http.Handle("/", http.FileServer(http.Dir(staticPath)))
	}
	httpServer := &http.Server{
		Addr:         serverAddr,
		ReadTimeout:  httpReadTimeout,
		WriteTimeout: httpWriteTimeout,
	}

	ctx, cancel := context.WithCancel(lifetimeContext(logger))
	errCh := make(chan error)
	go func() { errCh <- archipelagoServer.Run(ctx) }()
	go func() { errCh <- runHTTPServer(ctx, httpServer) }()
	err = <-errCh
	cancel()
	<-errCh
	if errors.Cause(err) == context.Canceled {
		logger.Debugf("Error caught in main: %+v", err)
	} else {
		logger.Fatalf("Error caught in main: %+v", err)
	}
}

// lifetimeContext returns a context that is cancelled on the first SIGINT or
// SIGKILL signal received. The application is force closed if more than
// one signal is received.
func lifetimeContext(logger *logrus.Logger) context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	stopSigs := make(chan os.Signal, 2)
	signal.Notify(stopSigs, os.Interrupt, os.Kill)
	go func() {
		<-stopSigs
		logger.Info("Caught interrupt, shutting down")
		cancel()
		<-stopSigs
		logger.Fatal("Caught second interrupt, force closing")
	}()
	return ctx
}

// runHTTPServer starts and runs the given HTTP server until either an error
// occurs or the context is cancelled.
func runHTTPServer(ctx context.Context, server *http.Server) error {
	errCh := make(chan error)
	go func() { errCh <- server.ListenAndServe() }()
	select {
	case err := <-errCh:
		return err
	case <-ctx.Done():
		server.Close()
		return ctx.Err()
	}
}
<commit_msg>Adds an http /healthcheck endpoint<commit_after>package main

import (
	"context"
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/pkg/profile"
	"github.com/verath/archipelago/lib"
	"net/http"
	"os"
	"os/signal"
	"path"
	"time"
)

const (
	httpReadTimeout  = 10 * time.Second
	httpWriteTimeout = 10 * time.Second
)

func main() {
	var (
		debug       bool
		serveStatic bool
		serverAddr  string
		profileMode string
	)
	flag.BoolVar(&debug, "debug", false, "Set to true to log debug messages.")
	flag.BoolVar(&serveStatic, "servestatic", false, "Enable serving of static assets.")
	flag.StringVar(&serverAddr, "addr", ":8080", "TCP address for the http server to listen on.")
	flag.StringVar(&profileMode, "profile", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
	flag.Parse()

	logger := logrus.New()
	logger.Formatter = &logrus.TextFormatter{}
	if debug {
		logger.Level = logrus.DebugLevel
	}
	// Setup profiling, if profile flag was set
	switch profileMode {
	case "cpu":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.BlockProfile).Stop()
	default:
	}

	archipelagoServer, err := archipelago.New(logger)
	if err != nil {
		logger.Fatalf("Error creating game: %+v", err)
	}

	http.Handle("/ws", archipelagoServer.WebsocketHandler())
	if serveStatic {
		staticPath := "./web/dist"
		// Explicitly set a max-age of 0 for service worker script.
		http.HandleFunc("/sw.js", func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Cache-Control", "max-age=0")
			http.ServeFile(w, r, path.Join(staticPath, "sw.js"))
		})
		http.Handle("/", http.FileServer(http.Dir(staticPath)))
	}
	http.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})
	httpServer := &http.Server{
		Addr:         serverAddr,
		ReadTimeout:  httpReadTimeout,
		WriteTimeout: httpWriteTimeout,
	}

	ctx, cancel := context.WithCancel(lifetimeContext(logger))
	errCh := make(chan error)
	go func() { errCh <- archipelagoServer.Run(ctx) }()
	go func() { errCh <- runHTTPServer(ctx, httpServer) }()
	err = <-errCh
	cancel()
	<-errCh
	if errors.Cause(err) == context.Canceled {
		logger.Debugf("Error caught in main: %+v", err)
	} else {
		logger.Fatalf("Error caught in main: %+v", err)
	}
}

// lifetimeContext returns a context that is cancelled on the first SIGINT or
// SIGKILL signal received. The application is force closed if more than
// one signal is received.
func lifetimeContext(logger *logrus.Logger) context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	stopSigs := make(chan os.Signal, 2)
	signal.Notify(stopSigs, os.Interrupt, os.Kill)
	go func() {
		<-stopSigs
		logger.Info("Caught interrupt, shutting down")
		cancel()
		<-stopSigs
		logger.Fatal("Caught second interrupt, force closing")
	}()
	return ctx
}

// runHTTPServer starts and runs the given HTTP server until either an error
// occurs or the context is cancelled.
func runHTTPServer(ctx context.Context, server *http.Server) error {
	errCh := make(chan error)
	go func() { errCh <- server.ListenAndServe() }()
	select {
	case err := <-errCh:
		return err
	case <-ctx.Done():
		server.Close()
		return ctx.Err()
	}
}
<|endoftext|>