<commit_before>// Sample datastore-quickstart fetches an entity from Google Cloud Datastore.
package main

import (
        "fmt"
        "log"
        "bufio"
        "os"

        // Imports the Google Cloud Datastore client package.
        "cloud.google.com/go/datastore"
        "golang.org/x/net/context"
)

type database struct {
    projectID string
    ctx context.Context
    client *datastore.Client
}

func (db *database) Init(projectID string) {
    db.projectID = projectID
    db.ctx = context.Background()
    var err error
    db.client, err = datastore.NewClient(db.ctx, db.projectID)
    if err != nil {
            log.Fatalf("Failed to create client: %v", err)
    }
}

type Task struct {
    Description string
}

func (db *database) StoreTask(kind, name string, task Task) *datastore.Key {
    key := datastore.NameKey(kind, name, nil)
    if _, err := db.client.Put(db.ctx, key, &task); err != nil {
        log.Fatalf("Failed to save task: %v", err)
    }
    return key
}

func main() {
    var db database
    db.Init("alert-height-150418")
    scanner := bufio.NewScanner(os.Stdin)
    kind := "Task"
    taskCounter := 0
    fmt.Print("q to quit; enter first task: ")
    for scanner.Scan() {
        if scanner.Text() == "quit" {
            break
        }
        description := scanner.Text()
        taskCounter++
        name := "task" + toString(taskCounter)
        task := Task{
            Description: description,
        }
        fmt.Printf("Saved %v\n", db.StoreTask(kind, name, task))
        fmt.Print("enter next task: ")
    }
}<commit_msg>use strconv to convert taskCounter to string<commit_after>// Sample datastore-quickstart fetches an entity from Google Cloud Datastore.
package main

import (
        "fmt"
        "log"
        "bufio"
        "os"
        "strconv"

        // Imports the Google Cloud Datastore client package.
        "cloud.google.com/go/datastore"
        "golang.org/x/net/context"
)

type database struct {
    projectID string
    ctx context.Context
    client *datastore.Client
}

func (db *database) Init(projectID string) {
    db.projectID = projectID
    db.ctx = context.Background()
    var err error
    db.client, err = datastore.NewClient(db.ctx, db.projectID)
    if err != nil {
            log.Fatalf("Failed to create client: %v", err)
    }
}

type Task struct {
    Description string
}

func (db *database) StoreTask(kind, name string, task Task) *datastore.Key {
    key := datastore.NameKey(kind, name, nil)
    if _, err := db.client.Put(db.ctx, key, &task); err != nil {
        log.Fatalf("Failed to save task: %v", err)
    }
    return key
}

func main() {
    var db database
    db.Init("alert-height-150418")
    scanner := bufio.NewScanner(os.Stdin)
    kind := "Task"
    taskCounter := 0
    fmt.Print("q to quit; enter first task: ")
    for scanner.Scan() {
        if scanner.Text() == "quit" {
            break
        }
        description := scanner.Text()
        taskCounter++
        name := "task" + strconv.Itoa(taskCounter)
        task := Task{
            Description: description,
        }
        fmt.Printf("Saved %v\n", db.StoreTask(kind, name, task))
        fmt.Print("enter next task: ")
    }
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")

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

func main() {
	fmt.Printf("%v\n", RandStringRunes(6))
}
<commit_msg>Initial support for sqlite3 + create db schema<commit_after>package main

import (
	"database/sql"
	"log"
	"math/rand"
	"os"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")

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

func main() {
	os.Remove("./confirmation-list.db")

	db, err := sql.Open("sqlite3", "./confirmation-list.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sqlStmt := `
create table guests (id integer not null primary key, name text, email text, confirmation_code text);
`
	_, err = db.Exec(sqlStmt)
	if err != nil {
		log.Printf("%q: %s\n", err, sqlStmt)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"

	"github.com/afex/hystrix-go/hystrix"
	"github.com/twitchscience/aws_utils/environment"
	"github.com/twitchscience/aws_utils/notifier"
	"github.com/twitchscience/aws_utils/uploader"

	"github.com/twitchscience/gologging/gologging"
	gen "github.com/twitchscience/gologging/key_name_generator"
	"github.com/twitchscience/spade_edge/kafka_logger"
	"github.com/twitchscience/spade_edge/request_handler"

	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/cactus/go-statsd-client/statsd"
	"github.com/crowdmob/goamz/aws"
	"github.com/crowdmob/goamz/s3"
)

const (
	auditBucketName = "spade-audits"
	eventBucketName = "spade-edge"
)

var (
	CLOUD_ENV    = environment.GetCloudEnv()
	stats_prefix = flag.String("stat_prefix", "edge", "statsd prefix")
	logging_dir  = flag.String("log_dir", ".", "The directory to log these files to")
	listen_port  = flag.String(
		"port",
		":8888",
		"Which port are we listenting on form: ':<port>' e.g. :8888",
	)
	cors_origins = flag.String("cors_origins", "",
		`Which origins should we advertise accepting POST and GET from.
Example: http://www.twitch.tv https://www.twitch.tv
Empty ignores CORS.`)
	brokers = flag.String("kafka_brokers", "",
		`<host>:<port>,<host>:<port>,... of kafka brokers.
		Can leave empty if not using`)
	clientId   = flag.String("client_id", "", "id of this client.")
	VERSION, _ = strconv.Atoi(os.Getenv("EDGE_VERSION"))

	maxLogLines = int(getInt64FromEnv("MAX_LOG_LINES", 1000000))                          // default 1 million
	maxLogAge   = time.Duration(getInt64FromEnv("MAX_LOG_AGE_SECS", 10*60)) * time.Second // default 10 mins

	auditMaxLogLines = int(getInt64FromEnv("MAX_AUDIT_LOG_LINES", 1000000))                          // default 1 million
	auditMaxLogAge   = time.Duration(getInt64FromEnv("MAX_AUDIT_LOG_AGE_SECS", 10*60)) * time.Second // default 10 mins

)

func getInt64FromEnv(target string, def int64) int64 {
	env := os.Getenv(target)
	if env == "" {
		return def
	}
	i, err := strconv.ParseInt(env, 10, 64)
	if err != nil {
		return def
	}
	return i
}

func ParseBrokerList(csv string) []string {
	return strings.Split(csv, ",")
}

type DummyNotifierHarness struct {
}
type SQSNotifierHarness struct {
	qName    string
	version  int
	notifier *notifier.SQSClient
}
type SQSErrorHarness struct {
	qName    string
	notifier *notifier.SQSClient
}

func (d *DummyNotifierHarness) SendMessage(r *uploader.UploadReceipt) error {
	return nil
}

func BuildSQSNotifierHarness() *SQSNotifierHarness {
	client := notifier.DefaultClient
	client.Signer.RegisterMessageType("edge", func(args ...interface{}) (string, error) {
		if len(args) < 2 {
			return "", errors.New("Missing correct number of args ")
		}
		return fmt.Sprintf("{\"version\":%d,\"keyname\":%q}", args...), nil
	})
	return &SQSNotifierHarness{
		qName:    fmt.Sprintf("spade-edge-%s", CLOUD_ENV),
		version:  VERSION,
		notifier: client,
	}
}

func BuildSQSErrorHarness() *SQSErrorHarness {
	return &SQSErrorHarness{
		qName:    fmt.Sprintf("uploader-error-spade-edge-%s", CLOUD_ENV),
		notifier: notifier.DefaultClient,
	}
}

func (s *SQSErrorHarness) SendError(er error) {
	err := s.notifier.SendMessage("error", s.qName, er)
	if err != nil {
		log.Println(err)
	}
}

func (s *SQSNotifierHarness) SendMessage(message *uploader.UploadReceipt) error {
	return s.notifier.SendMessage("edge", s.qName, s.version, message.KeyName)
}

func initStatsd(statsPrefix, statsdHostport string) (stats statsd.Statter, err error) {
	if statsdHostport == "" {
		stats, _ = statsd.NewNoop()
	} else {
		if stats, err = statsd.New(statsdHostport, *stats_prefix); err != nil {
			log.Fatalf("Statsd configuration error: %v", err)
		}
	}
	return
}

func main() {
	flag.Parse()

	stats, err := initStatsd(*stats_prefix, os.Getenv("STATSD_HOSTPORT"))
	if err != nil {
		log.Fatalf("Statsd configuration error: %v", err)
	}

	auth, err := aws.GetAuth("", "", "", time.Now())
	if err != nil {
		log.Fatalln("Failed to recieve auth from env")
	}
	awsConnection := s3.New(
		auth,
		aws.USWest2,
	)

	auditBucket := awsConnection.Bucket(auditBucketName + "-" + CLOUD_ENV)
	auditBucket.PutBucket(s3.BucketOwnerFull)
	eventBucket := awsConnection.Bucket(eventBucketName + "-" + CLOUD_ENV)
	eventBucket.PutBucket(s3.BucketOwnerFull)

	auditInfo := gen.BuildInstanceInfo(&gen.EnvInstanceFetcher{}, "spade_edge_audit", *logging_dir)
	loggingInfo := gen.BuildInstanceInfo(&gen.EnvInstanceFetcher{}, "spade_edge", *logging_dir)

	auditRotateCoordinator := gologging.NewRotateCoordinator(auditMaxLogLines, auditMaxLogAge)
	loggingRotateCoordinator := gologging.NewRotateCoordinator(maxLogLines, maxLogAge)

	auditLogger, err := gologging.StartS3Logger(
		auditRotateCoordinator,
		auditInfo,
		&DummyNotifierHarness{},
		&uploader.S3UploaderBuilder{
			Bucket:           auditBucket,
			KeyNameGenerator: &gen.EdgeKeyNameGenerator{Info: auditInfo},
		},
		BuildSQSErrorHarness(),
		2,
	)
	if err != nil {
		log.Fatalf("Got Error while building audit: %s\n", err)
	}

	spadeEventLogger, err := gologging.StartS3Logger(
		loggingRotateCoordinator,
		loggingInfo,
		BuildSQSNotifierHarness(),
		&uploader.S3UploaderBuilder{
			Bucket:           eventBucket,
			KeyNameGenerator: &gen.EdgeKeyNameGenerator{Info: loggingInfo},
		},
		BuildSQSErrorHarness(),
		2,
	)
	if err != nil {
		log.Fatalf("Got Error while building logger: %s\n", err)
	}

	// Initialize Loggers.
	// AuditLogger writes to the audit log, for analysis of system success rate.
	// SpadeLogger writes requests to a file for processing by the spade processor.
	// K(afka)Logger writes produces messages for kafka, currently in dark launch.
	// We allow the klogger to be null incase we boot up with an unresponsive kafka cluster.
	var logger *request_handler.EventLoggers
	brokerList := ParseBrokerList(*brokers)
	klogger, err := kafka_logger.NewKafkaLogger(*clientId, brokerList)
	if err == nil {
		klogger.(*kafka_logger.KafkaLogger).Init()
		logger = &request_handler.EventLoggers{
			AuditLogger: auditLogger,
			SpadeLogger: spadeEventLogger,
			KLogger:     klogger,
		}
	} else {
		log.Printf("Got Error while building logger: %s + %v\nUsing Nop Logger\n", err, brokerList)
		logger = &request_handler.EventLoggers{
			AuditLogger: auditLogger,
			SpadeLogger: spadeEventLogger,
			KLogger:     &request_handler.NoopLogger{},
		}
	}

	// Trigger close on receipt of SIGINT
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc,
		syscall.SIGINT)
	go func() {
		<-sigc
		// Cause flush
		logger.Close()
		os.Exit(0)
	}()

	hystrixStreamHandler := hystrix.NewStreamHandler()
	hystrixStreamHandler.Start()
	go http.ListenAndServe(net.JoinHostPort("", "81"), hystrixStreamHandler)

	// setup server and listen
	server := &http.Server{
		Addr:           *listen_port,
		Handler:        request_handler.NewSpadeHandler(stats, logger, request_handler.Assigner, *cors_origins),
		ReadTimeout:    5 * time.Second,
		WriteTimeout:   5 * time.Second,
		MaxHeaderBytes: 1 << 20, // 0.5MB
	}
	if err := server.ListenAndServe(); err != nil {
		log.Fatalln(err)
	}
}
<commit_msg>Enable pprof on 8082<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"

	"github.com/afex/hystrix-go/hystrix"
	"github.com/twitchscience/aws_utils/environment"
	"github.com/twitchscience/aws_utils/notifier"
	"github.com/twitchscience/aws_utils/uploader"

	"github.com/twitchscience/gologging/gologging"
	gen "github.com/twitchscience/gologging/key_name_generator"
	"github.com/twitchscience/spade_edge/kafka_logger"
	"github.com/twitchscience/spade_edge/request_handler"

	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/cactus/go-statsd-client/statsd"
	"github.com/crowdmob/goamz/aws"
	"github.com/crowdmob/goamz/s3"
)

const (
	auditBucketName = "spade-audits"
	eventBucketName = "spade-edge"
)

var (
	CLOUD_ENV    = environment.GetCloudEnv()
	stats_prefix = flag.String("stat_prefix", "edge", "statsd prefix")
	logging_dir  = flag.String("log_dir", ".", "The directory to log these files to")
	listen_port  = flag.String(
		"port",
		":8888",
		"Which port are we listenting on form: ':<port>' e.g. :8888",
	)
	cors_origins = flag.String("cors_origins", "",
		`Which origins should we advertise accepting POST and GET from.
Example: http://www.twitch.tv https://www.twitch.tv
Empty ignores CORS.`)
	brokers = flag.String("kafka_brokers", "",
		`<host>:<port>,<host>:<port>,... of kafka brokers.
		Can leave empty if not using`)
	clientId   = flag.String("client_id", "", "id of this client.")
	VERSION, _ = strconv.Atoi(os.Getenv("EDGE_VERSION"))

	maxLogLines = int(getInt64FromEnv("MAX_LOG_LINES", 1000000))                          // default 1 million
	maxLogAge   = time.Duration(getInt64FromEnv("MAX_LOG_AGE_SECS", 10*60)) * time.Second // default 10 mins

	auditMaxLogLines = int(getInt64FromEnv("MAX_AUDIT_LOG_LINES", 1000000))                          // default 1 million
	auditMaxLogAge   = time.Duration(getInt64FromEnv("MAX_AUDIT_LOG_AGE_SECS", 10*60)) * time.Second // default 10 mins

)

func getInt64FromEnv(target string, def int64) int64 {
	env := os.Getenv(target)
	if env == "" {
		return def
	}
	i, err := strconv.ParseInt(env, 10, 64)
	if err != nil {
		return def
	}
	return i
}

func ParseBrokerList(csv string) []string {
	return strings.Split(csv, ",")
}

type DummyNotifierHarness struct {
}
type SQSNotifierHarness struct {
	qName    string
	version  int
	notifier *notifier.SQSClient
}
type SQSErrorHarness struct {
	qName    string
	notifier *notifier.SQSClient
}

func (d *DummyNotifierHarness) SendMessage(r *uploader.UploadReceipt) error {
	return nil
}

func BuildSQSNotifierHarness() *SQSNotifierHarness {
	client := notifier.DefaultClient
	client.Signer.RegisterMessageType("edge", func(args ...interface{}) (string, error) {
		if len(args) < 2 {
			return "", errors.New("Missing correct number of args ")
		}
		return fmt.Sprintf("{\"version\":%d,\"keyname\":%q}", args...), nil
	})
	return &SQSNotifierHarness{
		qName:    fmt.Sprintf("spade-edge-%s", CLOUD_ENV),
		version:  VERSION,
		notifier: client,
	}
}

func BuildSQSErrorHarness() *SQSErrorHarness {
	return &SQSErrorHarness{
		qName:    fmt.Sprintf("uploader-error-spade-edge-%s", CLOUD_ENV),
		notifier: notifier.DefaultClient,
	}
}

func (s *SQSErrorHarness) SendError(er error) {
	err := s.notifier.SendMessage("error", s.qName, er)
	if err != nil {
		log.Println(err)
	}
}

func (s *SQSNotifierHarness) SendMessage(message *uploader.UploadReceipt) error {
	return s.notifier.SendMessage("edge", s.qName, s.version, message.KeyName)
}

func initStatsd(statsPrefix, statsdHostport string) (stats statsd.Statter, err error) {
	if statsdHostport == "" {
		stats, _ = statsd.NewNoop()
	} else {
		if stats, err = statsd.New(statsdHostport, *stats_prefix); err != nil {
			log.Fatalf("Statsd configuration error: %v", err)
		}
	}
	return
}

func main() {
	flag.Parse()

	stats, err := initStatsd(*stats_prefix, os.Getenv("STATSD_HOSTPORT"))
	if err != nil {
		log.Fatalf("Statsd configuration error: %v", err)
	}

	auth, err := aws.GetAuth("", "", "", time.Now())
	if err != nil {
		log.Fatalln("Failed to recieve auth from env")
	}
	awsConnection := s3.New(
		auth,
		aws.USWest2,
	)

	auditBucket := awsConnection.Bucket(auditBucketName + "-" + CLOUD_ENV)
	auditBucket.PutBucket(s3.BucketOwnerFull)
	eventBucket := awsConnection.Bucket(eventBucketName + "-" + CLOUD_ENV)
	eventBucket.PutBucket(s3.BucketOwnerFull)

	auditInfo := gen.BuildInstanceInfo(&gen.EnvInstanceFetcher{}, "spade_edge_audit", *logging_dir)
	loggingInfo := gen.BuildInstanceInfo(&gen.EnvInstanceFetcher{}, "spade_edge", *logging_dir)

	auditRotateCoordinator := gologging.NewRotateCoordinator(auditMaxLogLines, auditMaxLogAge)
	loggingRotateCoordinator := gologging.NewRotateCoordinator(maxLogLines, maxLogAge)

	auditLogger, err := gologging.StartS3Logger(
		auditRotateCoordinator,
		auditInfo,
		&DummyNotifierHarness{},
		&uploader.S3UploaderBuilder{
			Bucket:           auditBucket,
			KeyNameGenerator: &gen.EdgeKeyNameGenerator{Info: auditInfo},
		},
		BuildSQSErrorHarness(),
		2,
	)
	if err != nil {
		log.Fatalf("Got Error while building audit: %s\n", err)
	}

	spadeEventLogger, err := gologging.StartS3Logger(
		loggingRotateCoordinator,
		loggingInfo,
		BuildSQSNotifierHarness(),
		&uploader.S3UploaderBuilder{
			Bucket:           eventBucket,
			KeyNameGenerator: &gen.EdgeKeyNameGenerator{Info: loggingInfo},
		},
		BuildSQSErrorHarness(),
		2,
	)
	if err != nil {
		log.Fatalf("Got Error while building logger: %s\n", err)
	}

	// Initialize Loggers.
	// AuditLogger writes to the audit log, for analysis of system success rate.
	// SpadeLogger writes requests to a file for processing by the spade processor.
	// K(afka)Logger writes produces messages for kafka, currently in dark launch.
	// We allow the klogger to be null incase we boot up with an unresponsive kafka cluster.
	var logger *request_handler.EventLoggers
	brokerList := ParseBrokerList(*brokers)
	klogger, err := kafka_logger.NewKafkaLogger(*clientId, brokerList)
	if err == nil {
		klogger.(*kafka_logger.KafkaLogger).Init()
		logger = &request_handler.EventLoggers{
			AuditLogger: auditLogger,
			SpadeLogger: spadeEventLogger,
			KLogger:     klogger,
		}
	} else {
		log.Printf("Got Error while building logger: %s + %v\nUsing Nop Logger\n", err, brokerList)
		logger = &request_handler.EventLoggers{
			AuditLogger: auditLogger,
			SpadeLogger: spadeEventLogger,
			KLogger:     &request_handler.NoopLogger{},
		}
	}

	// Trigger close on receipt of SIGINT
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc,
		syscall.SIGINT)
	go func() {
		<-sigc
		// Cause flush
		logger.Close()
		os.Exit(0)
	}()

	hystrixStreamHandler := hystrix.NewStreamHandler()
	hystrixStreamHandler.Start()
	go http.ListenAndServe(net.JoinHostPort("", "81"), hystrixStreamHandler)

	go http.ListenAndServe(net.JoinHostPort("", "8082"), http.DefaultServeMux)

	// setup server and listen
	server := &http.Server{
		Addr:           *listen_port,
		Handler:        request_handler.NewSpadeHandler(stats, logger, request_handler.Assigner, *cors_origins),
		ReadTimeout:    5 * time.Second,
		WriteTimeout:   5 * time.Second,
		MaxHeaderBytes: 1 << 20, // 0.5MB
	}
	if err := server.ListenAndServe(); err != nil {
		log.Fatalln(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"
	"encoding/json"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"log"
	"os"
	//"io"
	"fmt"
	"database/sql"
	_ "github.com/lib/pq"
	"gopkg.in/antage/eventsource.v1"
)

var conn *sql.DB

func SetHeaders(w *http.ResponseWriter) {
	(*w).Header().Set("Access-Control-Allow-Origin", "*")
	(*w).Header().Set("Content-Type", "application/json")
}

func GetBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog")
	data := []BlogPost{}
	for rows.Next() {
		post := BlogPost{}
		rows.Scan(&post.Id, &post.Titel, &post.Text, &post.Auteur, &post.Img_url, &post.Ctime, &post.Image)
		data = append(data, post)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetPost(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog WHERE id = $1 LIMIT 1", ps.ByName("id"))
	data := BlogPost{}
	rows.Next()
	rows.Scan(&data.Id, &data.Titel, &data.Text, &data.Auteur, &data.Img_url, &data.Ctime, &data.Image)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM spindata ORDER BY tijd DESC LIMIT 1")
	spin := SpinData{}
	rows.Next()
	rows.Scan(&spin.Id, &spin.Tijd, &spin.Mode, &spin.Hellingsgraad, &spin.Snelheid, &spin.Batterij, &spin.BallonCount)
	buf,_ := json.Marshal(spin)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinBatterij(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT batterij FROM spindata ORDER BY tijd DESC LIMIT 1")
	var data int
	rows.Next()
	rows.Scan(&data)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinMode(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT mode FROM spindata ORDER BY tijd DESC LIMIT 1")
	var data string
	rows.Next()
	rows.Scan(&data)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM spindata")
	data := []SpinData{}
	for rows.Next() {
		spin := SpinData{}
		rows.Scan(&spin.Id, &spin.Tijd, &spin.Mode, &spin.Hellingsgraad, &spin.Snelheid, &spin.Batterij, &spin.BallonCount)
		data = append(data, spin)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinBatterij(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT batterij FROM spindata")
	data := make([]int, 0)
	var scanInt int
	for rows.Next() {
		rows.Scan(&scanInt)
		data = append(data, scanInt)
	}
	buf,_ := json.Marshal(data)
	fmt.Printf(string(buf))
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinMode(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT mode FROM spindata")
	data := make([]string, 0)
	var scanStr string
	for rows.Next() {
		rows.Scan(&scanStr)
		data = append(data, scanStr)
	}
	buf,_ := json.Marshal(data)
	fmt.Printf(string(buf))
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM servodata ORDER BY tijd DESC LIMIT 1")
	servo := ServoData{}
	rows.Next()
	rows.Scan(&servo.Id, &servo.ServoId, &servo.Tijd, &servo.Voltage, &servo.Positie, &servo.Load, &servo.Temperatuur)
	buf,_ := json.Marshal(servo)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM servodata")
	data := []ServoData{}
	for rows.Next() {
		servo := ServoData{}
		rows.Scan(&servo.Id, &servo.ServoId, &servo.Tijd, &servo.Voltage, &servo.Positie, &servo.Load, &servo.Temperatuur)
		data = append(data, servo)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func Test(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	buf,_ := json.Marshal("test")
	SetHeaders(&w)
	w.Write(buf)
}

func PostBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	//r.ParseMultipartForm(32 << 20)
	/*file, handler, err := r.FormFile("uploadfile")
	defer file.Close()
	if err == nil {
		fmt.Fprintf(w, "%v", handler.Header)
		f, err := os.OpenFile("./img/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			w.WriteHeader(500)
			return
		}
		defer f.Close()
		io.Copy(f, file)
	}

	err = nil*/

	//_,err := conn.Query("INSERT INTO blog (titel, text, auteur, ctime, image) VALUES ($1, $2, $3, $4, $5)", r.FormValue("titel"), r.FormValue("text"), r.FormValue("auteur"), time.Now(), "http://idp-api.herokuapp.com/img/"+handler.Filename)
	_,err := conn.Query("INSERT INTO blog (titel, text, auteur, ctime) VALUES ($1, $2, $3, $4)", r.FormValue("onderwerp"), r.FormValue("bericht"), r.FormValue("naam"), time.Now())
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.Header().Set("Content-Type", "text/html")
	w.WriteHeader(201)
	w.Write([]byte("<meta http-equiv=\"refresh\" content=\"5; url=http://knightspider.herokuapp.com/#/blog\">successful"))
}

func PostSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	_,err := conn.Query("INSERT INTO spindata (tijd, mode, hellingsgraad, snelheid, batterij, balloncount) VALUES ($1, $2, $3, $4, $5, $6)", time.Now(),
		r.FormValue("mode"), r.FormValue("hellingsgraad"), r.FormValue("snelheid"), r.FormValue("batterij"), r.FormValue("ballonCount"))
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.WriteHeader(201)
	w.Write([]byte("successful"))
}

func PostServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	_,err := conn.Query("INSERT INTO servodata (servo_id, tijd, voltage, positie, load, temperatuur) VALUES ($1, $2, $3, $4, $5, $6)",
		r.FormValue("servo_id"), time.Now(), r.FormValue("voltage"), r.FormValue("positie"), r.FormValue("load"), r.FormValue("Temperatuur"))
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.WriteHeader(201)
	w.Write([]byte("successful"))
}

/*func GetDoc(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	http.ServeFile(w,r,"./static/doc.html")
}*/

func Static(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	http.ServeFile(w,r,"./static/"+ps.ByName("file"))
}

func main() {
	conn,_ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
	defer conn.Close()

	es := eventsource.New(
		&eventsource.Settings{
            Timeout: 5 * time.Second,
            CloseOnTimeout: false,
            IdleTimeout: 30 * time.Minute,
        },
		func(req *http.Request) [][]byte {
			return [][]byte{
				[]byte("X-Accel-Buffering: no"),
				[]byte("Access-Control-Allow-Origin: *"),
			}
		},
	)
	defer es.Close()

	router := httprouter.New()
	//router.GET("/", GetDoc)
	router.GET("/test", Test)
	router.GET("/blog", GetBlog)
	router.GET("/blog/:id", GetPost)
	router.GET("/spin/latest", GetLatestSpinData)
	router.GET("/spin/latest/batterij", GetLatestSpinBatterij)
	router.GET("/spin/latest/mode", GetLatestSpinMode)
	router.GET("/spin/archive", GetArchivedSpinData)
	router.GET("/spin/archive/batterij", GetArchivedSpinBatterij)
	router.GET("/spin/archive/mode", GetArchivedSpinMode)
	router.GET("/servo/latest", GetLatestServoData)
	router.GET("/servo/archive", GetArchivedServoData)
	http.Handle("/subscribe", es)
	router.POST("/blog", PostBlog)
	router.POST("/spin", PostSpinData)
	router.POST("/servo", PostServoData)
	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	fmt.Printf("Starting server at localhost:%s...", port)
	log.Fatal(http.ListenAndServe(":"+port, router))
}<commit_msg>Testable EventSource<commit_after>package main

import (
	"time"
	"encoding/json"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"log"
	"os"
	//"io"
	"fmt"
	"database/sql"
	_ "github.com/lib/pq"
	"gopkg.in/antage/eventsource.v1"
	"strconv"
)

var conn *sql.DB
var es eventsource.EventSource
var id int

func SetHeaders(w *http.ResponseWriter) {
	(*w).Header().Set("Access-Control-Allow-Origin", "*")
	(*w).Header().Set("Content-Type", "application/json")
}

func GetBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog")
	data := []BlogPost{}
	for rows.Next() {
		post := BlogPost{}
		rows.Scan(&post.Id, &post.Titel, &post.Text, &post.Auteur, &post.Img_url, &post.Ctime, &post.Image)
		data = append(data, post)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetPost(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog WHERE id = $1 LIMIT 1", ps.ByName("id"))
	data := BlogPost{}
	rows.Next()
	rows.Scan(&data.Id, &data.Titel, &data.Text, &data.Auteur, &data.Img_url, &data.Ctime, &data.Image)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM spindata ORDER BY tijd DESC LIMIT 1")
	spin := SpinData{}
	rows.Next()
	rows.Scan(&spin.Id, &spin.Tijd, &spin.Mode, &spin.Hellingsgraad, &spin.Snelheid, &spin.Batterij, &spin.BallonCount)
	buf,_ := json.Marshal(spin)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinBatterij(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT batterij FROM spindata ORDER BY tijd DESC LIMIT 1")
	var data int
	rows.Next()
	rows.Scan(&data)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestSpinMode(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT mode FROM spindata ORDER BY tijd DESC LIMIT 1")
	var data string
	rows.Next()
	rows.Scan(&data)
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM spindata")
	data := []SpinData{}
	for rows.Next() {
		spin := SpinData{}
		rows.Scan(&spin.Id, &spin.Tijd, &spin.Mode, &spin.Hellingsgraad, &spin.Snelheid, &spin.Batterij, &spin.BallonCount)
		data = append(data, spin)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinBatterij(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT batterij FROM spindata")
	data := make([]int, 0)
	var scanInt int
	for rows.Next() {
		rows.Scan(&scanInt)
		data = append(data, scanInt)
	}
	buf,_ := json.Marshal(data)
	fmt.Printf(string(buf))
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedSpinMode(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT mode FROM spindata")
	data := make([]string, 0)
	var scanStr string
	for rows.Next() {
		rows.Scan(&scanStr)
		data = append(data, scanStr)
	}
	buf,_ := json.Marshal(data)
	fmt.Printf(string(buf))
	SetHeaders(&w)
	w.Write(buf)
}

func GetLatestServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM servodata ORDER BY tijd DESC LIMIT 1")
	servo := ServoData{}
	rows.Next()
	rows.Scan(&servo.Id, &servo.ServoId, &servo.Tijd, &servo.Voltage, &servo.Positie, &servo.Load, &servo.Temperatuur)
	buf,_ := json.Marshal(servo)
	SetHeaders(&w)
	w.Write(buf)
}

func GetArchivedServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM servodata")
	data := []ServoData{}
	for rows.Next() {
		servo := ServoData{}
		rows.Scan(&servo.Id, &servo.ServoId, &servo.Tijd, &servo.Voltage, &servo.Positie, &servo.Load, &servo.Temperatuur)
		data = append(data, servo)
	}
	buf,_ := json.Marshal(data)
	SetHeaders(&w)
	w.Write(buf)
}

func Test(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	buf,_ := json.Marshal("test")
	SetHeaders(&w)
	w.Write(buf)
}

func PostBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	//r.ParseMultipartForm(32 << 20)
	/*file, handler, err := r.FormFile("uploadfile")
	defer file.Close()
	if err == nil {
		fmt.Fprintf(w, "%v", handler.Header)
		f, err := os.OpenFile("./img/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			w.WriteHeader(500)
			return
		}
		defer f.Close()
		io.Copy(f, file)
	}

	err = nil*/

	//_,err := conn.Query("INSERT INTO blog (titel, text, auteur, ctime, image) VALUES ($1, $2, $3, $4, $5)", r.FormValue("titel"), r.FormValue("text"), r.FormValue("auteur"), time.Now(), "http://idp-api.herokuapp.com/img/"+handler.Filename)
	_,err := conn.Query("INSERT INTO blog (titel, text, auteur, ctime) VALUES ($1, $2, $3, $4)", r.FormValue("onderwerp"), r.FormValue("bericht"), r.FormValue("naam"), time.Now())
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.Header().Set("Content-Type", "text/html")
	w.WriteHeader(201)
	w.Write([]byte("<meta http-equiv=\"refresh\" content=\"5; url=http://knightspider.herokuapp.com/#/blog\">successful"))
}

func PostSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	_,err := conn.Query("INSERT INTO spindata (tijd, mode, hellingsgraad, snelheid, batterij, balloncount) VALUES ($1, $2, $3, $4, $5, $6)", time.Now(),
		r.FormValue("mode"), r.FormValue("hellingsgraad"), r.FormValue("snelheid"), r.FormValue("batterij"), r.FormValue("ballonCount"))
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.WriteHeader(201)
	w.Write([]byte("successful"))
}

func PostServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	_,err := conn.Query("INSERT INTO servodata (servo_id, tijd, voltage, positie, load, temperatuur) VALUES ($1, $2, $3, $4, $5, $6)",
		r.FormValue("servo_id"), time.Now(), r.FormValue("voltage"), r.FormValue("positie"), r.FormValue("load"), r.FormValue("Temperatuur"))
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}
	w.WriteHeader(201)
	w.Write([]byte("successful"))
}

func PostLog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	es.SendEventMessage(r.FormValue("log"), "log", strconv.Itoa(id))
	w.WriteHeader(201)
	w.Write([]byte("successful"))
}

/*func GetDoc(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	http.ServeFile(w,r,"./static/doc.html")
}*/

func Static(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	http.ServeFile(w,r,"./static/"+ps.ByName("file"))
}

func main() {
	conn,_ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
	defer conn.Close()

	es = eventsource.New(
		&eventsource.Settings{
            Timeout: 5 * time.Second,
            CloseOnTimeout: false,
            IdleTimeout: 30 * time.Minute,
        },
		func(req *http.Request) [][]byte {
			return [][]byte{
				[]byte("X-Accel-Buffering: no"),
				[]byte("Access-Control-Allow-Origin: *"),
			}
		},
	)
	defer es.Close()

	id = 0

	router := httprouter.New()
	//router.GET("/", GetDoc)
	router.GET("/test", Test)
	router.GET("/blog", GetBlog)
	router.GET("/blog/:id", GetPost)
	router.GET("/spin/latest", GetLatestSpinData)
	router.GET("/spin/latest/batterij", GetLatestSpinBatterij)
	router.GET("/spin/latest/mode", GetLatestSpinMode)
	router.GET("/spin/archive", GetArchivedSpinData)
	router.GET("/spin/archive/batterij", GetArchivedSpinBatterij)
	router.GET("/spin/archive/mode", GetArchivedSpinMode)
	router.GET("/servo/latest", GetLatestServoData)
	router.GET("/servo/archive", GetArchivedServoData)
	http.Handle("/subscribe", es)
	router.POST("/blog", PostBlog)
	router.POST("/spin", PostSpinData)
	router.POST("/servo", PostServoData)
	router.POST("/log", PostLog)
	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	fmt.Printf("Starting server at localhost:%s...", port)
	log.Fatal(http.ListenAndServe(":"+port, router))
}<|endoftext|>


<commit_before>// Written by Nathan Sullivan <nathan@nightsys.net>

package main

import (
	"encoding/json"
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

type EcsAgentMetadata struct {
	Cluster              string `json:"Cluster"`
	ContainerInstanceArn string `json:"ContainerInstanceArn"`
	Version              string `json:"Version"`
}

// TODO: deal with docker custom networks. for now this just hits the default bridge network IP.
func getEcsAgentMetadata() EcsAgentMetadata {
	resp, err := http.Get("http://172.17.0.1:51678/v1/metadata")
	if err != nil {
		fmt.Println("Error retrieving metadata from ECS agent on local Docker host (via 172.17.0.1:51678):")
		fmt.Println(err)
		os.Exit(1)
	}

	defer resp.Body.Close()
	body, read_err := ioutil.ReadAll(resp.Body)
	if read_err != nil {
		fmt.Println("Error reading the metadata response from ECS agent on local Docker host:")
		fmt.Println(read_err)
		os.Exit(1)
	}

	var json_data EcsAgentMetadata
	json_data_err := json.Unmarshal(body, &json_data)
	if json_data_err != nil {
		fmt.Println("Error parsing JSON response from ECS agent on local Docker host:")
		fmt.Println(json_data_err)
		os.Exit(1)
	}

	return json_data
}

// Save some repetition, formatting the output of these.
func formatAwsError(err error) {
	if awsErr, ok := err.(awserr.Error); ok {
		// Generic AWS Error with Code, Message, and original error (if any)
		fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
		if reqErr, ok := err.(awserr.RequestFailure); ok {
			// A service error occurred
			fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
		}
	} else {
		fmt.Println(err.Error())
	}
}

// Verify that the ECS service exists.
func verifyServiceExists(ecs_obj *ecs.ECS, cluster string, service string) {
	params := &ecs.DescribeServicesInput{
		Cluster: &cluster,
		Services: []*string{ // Required
			aws.String(service), // Required
		},
	}
	_, err := ecs_obj.DescribeServices(params)

	if err != nil {
		fmt.Println("Cannot verify if ECS service exists:")
		formatAwsError(err)
		os.Exit(1)
	}
}

func getContainerInstanceArnsForService(ecs_obj *ecs.ECS, cluster string, service string, local_container_instance_arn string) []string {
	// Fetch a task list based on the service name.
	list_tasks_params := &ecs.ListTasksInput{
		Cluster:     &cluster,
		ServiceName: &service,
	}
	list_tasks_resp, list_tasks_err := ecs_obj.ListTasks(list_tasks_params)

	if list_tasks_err != nil {
		fmt.Println("Cannot retrieve ECS task list:")
		formatAwsError(list_tasks_err)
		os.Exit(1)
	}

	if len(list_tasks_resp.TaskArns) <= 0 {
		fmt.Println("No ECS tasks found with specified filter - cluster:", cluster, ",service:", service)
		os.Exit(1)
	}

	// Describe the tasks retrieved above.
	describe_tasks_params := &ecs.DescribeTasksInput{
		Cluster: &cluster,
		Tasks:   list_tasks_resp.TaskArns,
	}
	describe_tasks_resp, describe_tasks_err := ecs_obj.DescribeTasks(describe_tasks_params)

	if describe_tasks_err != nil {
		fmt.Println("Cannot retrieve ECS task details:")
		formatAwsError(describe_tasks_err)
		os.Exit(1)
	}

	if len(describe_tasks_resp.Tasks) <= 0 {
		fmt.Println("No ECS task details found with specified filter - tasks:", strings.Join(aws.StringValueSlice(list_tasks_resp.TaskArns), ", "))
		os.Exit(1)
	}

	var result []string
	for _, value := range describe_tasks_resp.Tasks {
		if *value.LastStatus == "RUNNING" && *value.ContainerInstanceArn != local_container_instance_arn {
			result = append(result, *value.ContainerInstanceArn)
		} else {
			if debug == true {
				fmt.Println(*value.ContainerInstanceArn, "is not in a RUNNING state, or is this instance (we dont return ourself). Excluded from results.")
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No ECS task results found in RUNNING state, no ECS container instances to return.")
		os.Exit(1)
	}
	return result
}

func getEc2InstanceIdsFromContainerInstances(ecs_obj *ecs.ECS, cluster string, container_instances []string) []string {
	params := &ecs.DescribeContainerInstancesInput{
		Cluster:            aws.String(cluster),
		ContainerInstances: aws.StringSlice(container_instances),
	}
	resp, err := ecs_obj.DescribeContainerInstances(params)

	if err != nil {
		fmt.Println("Cannot retrieve ECS container instance information:")
		formatAwsError(err)
		os.Exit(1)
	}

	if len(resp.ContainerInstances) <= 0 {
		fmt.Println("No ECS container instances found with specified filter - cluster:", cluster, "- instances:", strings.Join(container_instances, ", "))
		os.Exit(1)
	}

	var result []string
	for _, value := range resp.ContainerInstances {
		if *value.Status == "ACTIVE" {
			result = append(result, *value.Ec2InstanceId)
		} else {
			if debug == true {
				fmt.Println(*value.Ec2InstanceId, "is not in an ACTIVE state, excluded from results.")
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No running ECS container instances found in result set, cannot proceed.")
		os.Exit(1)
	}
	return result
}

func getEc2PrivateIpsFromInstanceIds(ec2_obj *ec2.EC2, instance_ids []string) []string {
	params := &ec2.DescribeInstancesInput{
		InstanceIds: aws.StringSlice(instance_ids),
	}
	resp, err := ec2_obj.DescribeInstances(params)

	if err != nil {
		fmt.Println("Cannot retrieve EC2 instance information:")
		formatAwsError(err)
		os.Exit(1)
	}

	if len(resp.Reservations) <= 0 {
		fmt.Println("No EC2 instances found (Reservations.*) with specified Instance IDs filter: ", strings.Join(instance_ids, ", "))
		os.Exit(1)
	}
	if len(resp.Reservations[0].Instances) <= 0 {
		fmt.Println("No EC2 instances found (Reservations[0].* with specified Instance IDs filter: ", strings.Join(instance_ids, ", "))
		os.Exit(1)
	}

	var result []string
	for idx, _ := range resp.Reservations {
		for _, value := range resp.Reservations[idx].Instances {
			if *value.State.Name == "running" {
				result = append(result, *value.PrivateIpAddress)
			} else {
				if debug == true {
					fmt.Println(*value.InstanceId, "is not in a running state, excluded from results.")
				}
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No running EC2 instances found in result set, cannot proceed.")
		os.Exit(1)
	}
	return result
}

var debug bool

func main() {
	// Check that the ECS service name is passed in as an argument.
	if len(os.Args) != 2 && len(os.Args) != 3 {
		fmt.Println("Usage:", os.Args[0], "ecs_service_name [debug]")
		os.Exit(1)
	}
	ecs_service := os.Args[1]
	if len(os.Args) == 3 && os.Args[2] == "debug" {
		fmt.Println("Debug Mode Enabled")
		debug = true
	} else {
		debug = false
	}

	// Get the metadata from the ECS agent on the local Docker host.
	local_ecs_agent_metadata := getEcsAgentMetadata()

	// Discover the region which this instance resides.
	metadata := ec2metadata.New(&ec2metadata.Config{})
	region, err := metadata.Region()
	if err != nil {
		fmt.Println("Cannot retrieve AWS region from EC2 Metadata Service:")
		formatAwsError(err)
		os.Exit(1)
	}

	// Discover the ECS cluster this EC2 instance belongs to, via local ECS agent.
	ecs_cluster := local_ecs_agent_metadata.Cluster

	// Reusable config object for AWS services with current region attached.
	aws_config := &aws.Config{Region: aws.String(region)}

	// Create an ECS service object.
	ecs_obj := ecs.New(aws_config)
	// Create an EC2 service object.
	ec2_obj := ec2.New(aws_config)

	// Check that the service exists.
	verifyServiceExists(ecs_obj, ecs_cluster, ecs_service)

	// TODOLATER - do we want to get the listen ports for each task? or just assume a port...?
	// readme states ports are outside the scope for now.

	// Get all tasks for the given service, in this ECS cluster. We exclude the current container instance in the result,
	// as we only need to know about all other instances.
	container_instances := getContainerInstanceArnsForService(ecs_obj, ecs_cluster, ecs_service, local_ecs_agent_metadata.ContainerInstanceArn)
	if debug == true {
		fmt.Println("container_instances:", strings.Join(container_instances, ","))
	}

	// Get EC2 instance IDs for all container instances returned.
	instance_ids := getEc2InstanceIdsFromContainerInstances(ecs_obj, ecs_cluster, container_instances)
	if debug == true {
		fmt.Println("instance_ids:", strings.Join(instance_ids, ","))
	}

	// Get the private IP of the EC2 (container) instance running the ECS agent.
	instance_private_ips := getEc2PrivateIpsFromInstanceIds(ec2_obj, instance_ids)
	if debug == true {
		fmt.Println("instance_private_ips:", strings.Join(instance_private_ips, ","))
	}

	fmt.Println(strings.Join(instance_private_ips, ","))
}
<commit_msg>fix breaking aws-sdk-go changes - https://github.com/aws/aws-sdk-go/issues/421<commit_after>// Written by Nathan Sullivan <nathan@nightsys.net>

package main

import (
	"encoding/json"
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

type EcsAgentMetadata struct {
	Cluster              string `json:"Cluster"`
	ContainerInstanceArn string `json:"ContainerInstanceArn"`
	Version              string `json:"Version"`
}

// TODO: deal with docker custom networks. for now this just hits the default bridge network IP.
func getEcsAgentMetadata() EcsAgentMetadata {
	resp, err := http.Get("http://172.17.0.1:51678/v1/metadata")
	if err != nil {
		fmt.Println("Error retrieving metadata from ECS agent on local Docker host (via 172.17.0.1:51678):")
		fmt.Println(err)
		os.Exit(1)
	}

	defer resp.Body.Close()
	body, read_err := ioutil.ReadAll(resp.Body)
	if read_err != nil {
		fmt.Println("Error reading the metadata response from ECS agent on local Docker host:")
		fmt.Println(read_err)
		os.Exit(1)
	}

	var json_data EcsAgentMetadata
	json_data_err := json.Unmarshal(body, &json_data)
	if json_data_err != nil {
		fmt.Println("Error parsing JSON response from ECS agent on local Docker host:")
		fmt.Println(json_data_err)
		os.Exit(1)
	}

	return json_data
}

// Save some repetition, formatting the output of these.
func formatAwsError(err error) {
	if awsErr, ok := err.(awserr.Error); ok {
		// Generic AWS Error with Code, Message, and original error (if any)
		fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
		if reqErr, ok := err.(awserr.RequestFailure); ok {
			// A service error occurred
			fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
		}
	} else {
		fmt.Println(err.Error())
	}
}

// Verify that the ECS service exists.
func verifyServiceExists(ecs_obj *ecs.ECS, cluster string, service string) {
	params := &ecs.DescribeServicesInput{
		Cluster: &cluster,
		Services: []*string{ // Required
			aws.String(service), // Required
		},
	}
	_, err := ecs_obj.DescribeServices(params)

	if err != nil {
		fmt.Println("Cannot verify if ECS service exists:")
		formatAwsError(err)
		os.Exit(1)
	}
}

func getContainerInstanceArnsForService(ecs_obj *ecs.ECS, cluster string, service string, local_container_instance_arn string) []string {
	// Fetch a task list based on the service name.
	list_tasks_params := &ecs.ListTasksInput{
		Cluster:     &cluster,
		ServiceName: &service,
	}
	list_tasks_resp, list_tasks_err := ecs_obj.ListTasks(list_tasks_params)

	if list_tasks_err != nil {
		fmt.Println("Cannot retrieve ECS task list:")
		formatAwsError(list_tasks_err)
		os.Exit(1)
	}

	if len(list_tasks_resp.TaskArns) <= 0 {
		fmt.Println("No ECS tasks found with specified filter - cluster:", cluster, ",service:", service)
		os.Exit(1)
	}

	// Describe the tasks retrieved above.
	describe_tasks_params := &ecs.DescribeTasksInput{
		Cluster: &cluster,
		Tasks:   list_tasks_resp.TaskArns,
	}
	describe_tasks_resp, describe_tasks_err := ecs_obj.DescribeTasks(describe_tasks_params)

	if describe_tasks_err != nil {
		fmt.Println("Cannot retrieve ECS task details:")
		formatAwsError(describe_tasks_err)
		os.Exit(1)
	}

	if len(describe_tasks_resp.Tasks) <= 0 {
		fmt.Println("No ECS task details found with specified filter - tasks:", strings.Join(aws.StringValueSlice(list_tasks_resp.TaskArns), ", "))
		os.Exit(1)
	}

	var result []string
	for _, value := range describe_tasks_resp.Tasks {
		if *value.LastStatus == "RUNNING" && *value.ContainerInstanceArn != local_container_instance_arn {
			result = append(result, *value.ContainerInstanceArn)
		} else {
			if debug == true {
				fmt.Println(*value.ContainerInstanceArn, "is not in a RUNNING state, or is this instance (we dont return ourself). Excluded from results.")
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No ECS task results found in RUNNING state, no ECS container instances to return.")
		os.Exit(1)
	}
	return result
}

func getEc2InstanceIdsFromContainerInstances(ecs_obj *ecs.ECS, cluster string, container_instances []string) []string {
	params := &ecs.DescribeContainerInstancesInput{
		Cluster:            aws.String(cluster),
		ContainerInstances: aws.StringSlice(container_instances),
	}
	resp, err := ecs_obj.DescribeContainerInstances(params)

	if err != nil {
		fmt.Println("Cannot retrieve ECS container instance information:")
		formatAwsError(err)
		os.Exit(1)
	}

	if len(resp.ContainerInstances) <= 0 {
		fmt.Println("No ECS container instances found with specified filter - cluster:", cluster, "- instances:", strings.Join(container_instances, ", "))
		os.Exit(1)
	}

	var result []string
	for _, value := range resp.ContainerInstances {
		if *value.Status == "ACTIVE" {
			result = append(result, *value.Ec2InstanceId)
		} else {
			if debug == true {
				fmt.Println(*value.Ec2InstanceId, "is not in an ACTIVE state, excluded from results.")
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No running ECS container instances found in result set, cannot proceed.")
		os.Exit(1)
	}
	return result
}

func getEc2PrivateIpsFromInstanceIds(ec2_obj *ec2.EC2, instance_ids []string) []string {
	params := &ec2.DescribeInstancesInput{
		InstanceIds: aws.StringSlice(instance_ids),
	}
	resp, err := ec2_obj.DescribeInstances(params)

	if err != nil {
		fmt.Println("Cannot retrieve EC2 instance information:")
		formatAwsError(err)
		os.Exit(1)
	}

	if len(resp.Reservations) <= 0 {
		fmt.Println("No EC2 instances found (Reservations.*) with specified Instance IDs filter: ", strings.Join(instance_ids, ", "))
		os.Exit(1)
	}
	if len(resp.Reservations[0].Instances) <= 0 {
		fmt.Println("No EC2 instances found (Reservations[0].* with specified Instance IDs filter: ", strings.Join(instance_ids, ", "))
		os.Exit(1)
	}

	var result []string
	for idx, _ := range resp.Reservations {
		for _, value := range resp.Reservations[idx].Instances {
			if *value.State.Name == "running" {
				result = append(result, *value.PrivateIpAddress)
			} else {
				if debug == true {
					fmt.Println(*value.InstanceId, "is not in a running state, excluded from results.")
				}
			}
		}
	}

	if len(result) == 0 {
		fmt.Println("No running EC2 instances found in result set, cannot proceed.")
		os.Exit(1)
	}
	return result
}

var debug bool

func main() {
	// Check that the ECS service name is passed in as an argument.
	if len(os.Args) != 2 && len(os.Args) != 3 {
		fmt.Println("Usage:", os.Args[0], "ecs_service_name [debug]")
		os.Exit(1)
	}
	ecs_service := os.Args[1]
	if len(os.Args) == 3 && os.Args[2] == "debug" {
		fmt.Println("Debug Mode Enabled")
		debug = true
	} else {
		debug = false
	}

	// Get the metadata from the ECS agent on the local Docker host.
	local_ecs_agent_metadata := getEcsAgentMetadata()

	// Discover the region which this instance resides.
	metadata := ec2metadata.New(session.New())
	region, err := metadata.Region()
	if err != nil {
		fmt.Println("Cannot retrieve AWS region from EC2 Metadata Service:")
		formatAwsError(err)
		os.Exit(1)
	}

	// Discover the ECS cluster this EC2 instance belongs to, via local ECS agent.
	ecs_cluster := local_ecs_agent_metadata.Cluster

	// Reusable config session object for AWS services with current region attached.
	aws_config_session := session.New(&aws.Config{Region: aws.String(region)})

	// Create an ECS service object.
	ecs_obj := ecs.New(aws_config_session)
	// Create an EC2 service object.
	ec2_obj := ec2.New(aws_config_session)

	// Check that the service exists.
	verifyServiceExists(ecs_obj, ecs_cluster, ecs_service)

	// TODOLATER - do we want to get the listen ports for each task? or just assume a port...?
	// readme states ports are outside the scope for now.

	// Get all tasks for the given service, in this ECS cluster. We exclude the current container instance in the result,
	// as we only need to know about all other instances.
	container_instances := getContainerInstanceArnsForService(ecs_obj, ecs_cluster, ecs_service, local_ecs_agent_metadata.ContainerInstanceArn)
	if debug == true {
		fmt.Println("container_instances:", strings.Join(container_instances, ","))
	}

	// Get EC2 instance IDs for all container instances returned.
	instance_ids := getEc2InstanceIdsFromContainerInstances(ecs_obj, ecs_cluster, container_instances)
	if debug == true {
		fmt.Println("instance_ids:", strings.Join(instance_ids, ","))
	}

	// Get the private IP of the EC2 (container) instance running the ECS agent.
	instance_private_ips := getEc2PrivateIpsFromInstanceIds(ec2_obj, instance_ids)
	if debug == true {
		fmt.Println("instance_private_ips:", strings.Join(instance_private_ips, ","))
	}

	fmt.Println(strings.Join(instance_private_ips, ","))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

func analyzeBytes(data string) {
	// TODO : Fix shift when battery MSB=0
	// TODO : Handle modes 2, 3, 4 & 5
	byte1 := data[0:8]
	byte2 := data[8:16]
	byte3 := data[16:24]
	byte4 := data[24:32]

	//Byte 1
	mode, _ := strconv.ParseInt(data[5:8], 2, 8)
	timeframe, _ := strconv.ParseInt(data[3:5], 2, 8)
	eventType, _ := strconv.ParseInt(data[1:3], 2, 8)
	batteryMsb := data[0:1]

	//Byte 2
	temperatureMsb := data[8:12]
	batteryLsb := data[12:16]
	battData := []string{batteryMsb, batteryLsb}
	battery, _ := strconv.ParseInt(strings.Join(battData, ""), 2, 8)
	batVal := float32(battery) * 0.05 * 2.7

	//Byte 3
	temperature := int64(0)
	tempVal := float32(0)

	reedSwitch := false
	if mode == 0 || mode == 1 {
		temperatureLsb := data[18:24]
		tempData := []string{temperatureMsb, temperatureLsb}
		temperature, _ := strconv.ParseInt(strings.Join(tempData, ""), 2, 16)
		tempVal = (float32(temperature) - 200) / 8
		if data[17] == 1 {
			reedSwitch = true
		}
	} else {
		temperature, _ = strconv.ParseInt(temperatureMsb, 2, 16)
		tempVal = (float32(temperature) - 200) / 8
	}

	modeStr := ""
	swRev := ""
	humidity := 0.0
	light := float32(0.0)
	switch mode {
	case 0:
		modeStr = "Button"
		majorSwRev, _ := strconv.ParseInt(data[24:28], 2, 8)
		minorSwRev, _ := strconv.ParseInt(data[28:32], 2, 8)
		swRev = fmt.Sprintf("%d.%d", majorSwRev, minorSwRev)
	case 1:
		modeStr = "Temperature + Humidity"
		humi, _ := strconv.ParseInt(data[24:32], 2, 16)
		humidity = float64(humi) * 0.5
	case 2:
		modeStr = "Light"
		lightVal, _ := strconv.ParseInt(data[18:24], 2, 8)
		lightMulti, _ := strconv.ParseInt(data[17:18], 2, 8)
		light = float32(lightVal) * 0.01
		if lightMulti == 1 {
			light = light * 8
			}
	case 3:
		modeStr = "Door"
	case 4:
		modeStr = "Move"
	case 5:
		modeStr = "Reed switch"
	default:
		modeStr = ""
	}

	timeStr := ""
	switch timeframe {
	case 0:
		timeStr = "10 mins"
	case 1:
		timeStr = "1 hour"
	case 2:
		timeStr = "6 hours"
	case 3:
		timeStr = "24 hours"
	default:
		timeStr = ""
	}

	typeStr := ""
	switch eventType {
	case 0:
		typeStr = "Regular, no alert"
	case 1:
		typeStr = "Button call"
	case 2:
		typeStr = "Alert"
	case 3:
		typeStr = "New mode"
	default:
		timeStr = ""
	}

	//fmt.Println(data)
	fmt.Println("Raw data :", byte1, byte2, byte3, byte4)
	fmt.Println("Mode", mode, ":", modeStr, "\t\t", "Event type", eventType, ":", typeStr, "\t\t", "Timeframe", timeframe, ":", timeStr)
	fmt.Println("Battery :", batVal, "V\t\t")
	switch mode {
	case 0:
		fmt.Println("v" + swRev)
		fmt.Println("Temperature :", tempVal, "°C")
	case 1:
		fmt.Println(humidity, "% RH")
		fmt.Println("Temperature :", tempVal, "°C")
	case 2:
		fmt.Println(light, "lux")
	case 3,4,5:
		alerts, _ := strconv.ParseInt(data[24:32], 2, 16)
		fmt.Println("Number of alerts :", alerts)
	}
	if reedSwitch {
		fmt.Println("Reed switch on")
	}
}

func formatData(data string) {
	//decoded, err := hex.DecodeString(data)
	parsed, err := strconv.ParseUint(data, 16, 32)
	if err != nil {
		log.Fatal(err)
	}
	pars := fmt.Sprintf("%08b", parsed)
	analyzeBytes(pars)
}

func main() {
	frameBits := "ec6e1700"
	formatData(frameBits)
}
<commit_msg>Added examples<commit_after>package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

func analyzeBytes(data string) {
	// TODO : Fix shift when battery MSB=0
	// TODO : Handle modes 2, 3, 4 & 5
	byte1 := data[0:8]
	byte2 := data[8:16]
	byte3 := data[16:24]
	byte4 := data[24:32]

	//Byte 1
	mode, _ := strconv.ParseInt(data[5:8], 2, 8)
	timeframe, _ := strconv.ParseInt(data[3:5], 2, 8)
	eventType, _ := strconv.ParseInt(data[1:3], 2, 8)
	batteryMsb := data[0:1]

	//Byte 2
	temperatureMsb := data[8:12]
	batteryLsb := data[12:16]
	battData := []string{batteryMsb, batteryLsb}
	battery, _ := strconv.ParseInt(strings.Join(battData, ""), 2, 8)
	batVal := float32(battery) * 0.05 * 2.7

	//Byte 3
	temperature := int64(0)
	tempVal := float32(0)

	reedSwitch := false
	if mode == 0 || mode == 1 {
		temperatureLsb := data[18:24]
		tempData := []string{temperatureMsb, temperatureLsb}
		temperature, _ := strconv.ParseInt(strings.Join(tempData, ""), 2, 16)
		tempVal = (float32(temperature) - 200) / 8
		if data[17] == 1 {
			reedSwitch = true
		}
	} else {
		temperature, _ = strconv.ParseInt(temperatureMsb, 2, 16)
		tempVal = (float32(temperature) - 200) / 8
	}

	modeStr := ""
	swRev := ""
	humidity := 0.0
	light := float32(0.0)
	switch mode {
	case 0:
		modeStr = "Button"
		majorSwRev, _ := strconv.ParseInt(data[24:28], 2, 8)
		minorSwRev, _ := strconv.ParseInt(data[28:32], 2, 8)
		swRev = fmt.Sprintf("%d.%d", majorSwRev, minorSwRev)
	case 1:
		modeStr = "Temperature + Humidity"
		humi, _ := strconv.ParseInt(data[24:32], 2, 16)
		humidity = float64(humi) * 0.5
	case 2:
		modeStr = "Light"
		lightVal, _ := strconv.ParseInt(data[18:24], 2, 8)
		lightMulti, _ := strconv.ParseInt(data[17:18], 2, 8)
		light = float32(lightVal) * 0.01
		if lightMulti == 1 {
			light = light * 8
		}
	case 3:
		modeStr = "Door"
	case 4:
		modeStr = "Move"
	case 5:
		modeStr = "Reed switch"
	default:
		modeStr = ""
	}

	timeStr := ""
	switch timeframe {
	case 0:
		timeStr = "10 mins"
	case 1:
		timeStr = "1 hour"
	case 2:
		timeStr = "6 hours"
	case 3:
		timeStr = "24 hours"
	default:
		timeStr = ""
	}

	typeStr := ""
	switch eventType {
	case 0:
		typeStr = "Regular, no alert"
	case 1:
		typeStr = "Button call"
	case 2:
		typeStr = "Alert"
	case 3:
		typeStr = "New mode"
	default:
		timeStr = ""
	}

	//fmt.Println(data)
	fmt.Println("________________________________________________________________________________________")
	fmt.Println("Raw data :", byte1, byte2, byte3, byte4)
	fmt.Println("Mode", mode, ":", modeStr, "\t\t", "Event type", eventType, ":", typeStr, "\t\t", "Timeframe", timeframe, ":", timeStr)
	fmt.Println("Battery :", batVal, "V\t\t")
	switch mode {
	case 0:
		fmt.Println("v" + swRev)
		fmt.Println("Temperature :", tempVal, "°C")
	case 1:
		fmt.Println(humidity, "% RH")
		fmt.Println("Temperature :", tempVal, "°C")
	case 2:
		fmt.Println(light, "lux")
		alerts, _ := strconv.ParseInt(data[24:32], 2, 16)
		fmt.Println("Number of alerts :", alerts)
	case 3, 4, 5:
		alerts, _ := strconv.ParseInt(data[24:32], 2, 16)
		fmt.Println("Number of alerts :", alerts)
	}
	if reedSwitch {
		fmt.Println("Reed switch on")
	}
}

func formatData(data string) {
	//decoded, err := hex.DecodeString(data)
	parsed, err := strconv.ParseUint(data, 16, 32)
	if err != nil {
		log.Fatal(err)
	}
	pars := fmt.Sprintf("%08b", parsed)
	analyzeBytes(pars)
}

func main() {
	frameBits := "e86e1a21"
	formatData(frameBits)
	formatData("896e1293")
	formatData("ca6ec401")
	formatData("eb6e0000")
	formatData("ec6e1700")
	formatData("ed6e1900")
}
<|endoftext|>


<commit_before>// Package c2go contains the main function for running the executable.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/Konstantin8105/c2go/util"
	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "0.13.3"

// ProgramArgs - arguments of program
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFile   string
	outputFile  string
	packageName string
}

func readAST(data []byte) []string {
	uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{})
	return strings.Split(string(uncolored), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := []treeNode{}
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)

		indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line)
		if len(indentAndType) == 0 {
			panic(fmt.Sprintf("Cannot understand line '%s'", line))
		}

		offset := len(indentAndType[1])
		node := ast.Parse(line[offset:])

		indentLevel := len(indentAndType[1]) / 2
		nodes = append(nodes, treeNode{indentLevel, node})
	}

	return nodes
}

// buildTree convert an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a a tree with its own root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

/* Dead code
// ToJSON - tree convert to JSON
func ToJSON(tree []interface{}) []map[string]interface{} {
	r := make([]map[string]interface{}, len(tree))

	for j, n := range tree {
		rn := reflect.ValueOf(n).Elem()
		r[j] = make(map[string]interface{})
		r[j]["node"] = rn.Type().Name()

		for i := 0; i < rn.NumField(); i++ {
			name := strings.ToLower(rn.Type().Field(i).Name)
			value := rn.Field(i).Interface()

			if name == "children" {
				v := value.([]interface{})

				if len(v) == 0 {
					continue
				}

				value = ToJSON(v)
			}

			r[j][name] = value
		}
	}

	return r
}
*/

type headerTypes bool

const (
	systemHeader   headerTypes = true
	internalHeader headerTypes = false
)

type include struct {
	headerName string
	typeHeader headerTypes
}

func (inc include) String() (s string) {
	s += fmt.Sprintf("\tHeader name : %v\n", inc.headerName)
	s += fmt.Sprintf("\tType : ")
	switch inc.typeHeader {
	case systemHeader:
		s += fmt.Sprintf("System header\n")
	case internalHeader:
		s += fmt.Sprintf("Internal header\n")
	}
	return
}

// parseForFoundLostIncluse - parsing string to
// found lost includes in c code after clang
//
// Example of input:
// E:\Temp\c2go001preprocess.c:1:10: fatal error: 'AbsoluteWrongInclude.h' file not found
// #include <AbsoluteWrongInclude.h>
//          ^~~~~~~~~~~~~~~~~~~~~~~~
// tests\struct.c:3:10: fatal error: 'stdio.h' file not found
//                #include <stdio.h>
//                         ^~~~~~~~~
//                1 error generated.
func parseForFoundLostIncluse(s string) (includes []include, err error) {
	lines, err := util.StringToLines(s)
	if err != nil {
		return includes, err
	}
	includeName := "#include"
	regSystem := regexp.MustCompile("<(.*?)>")
	regInternal := regexp.MustCompile("\"(.*?)\"")
	for _, line := range lines {
		if !strings.Contains(line, includeName) {
			continue
		}
		// Now, we know - the string line have "#include"
		// Find the name of header file
		var inc include
		if strings.ContainsAny(line, "<>") {
			// system header
			inc.headerName = regSystem.FindString(line)
			inc.typeHeader = systemHeader
		} else {
			// internal header
			inc.headerName = regInternal.FindString(line)
			inc.typeHeader = internalHeader
		}
		inc.headerName = inc.headerName[1 : len(inc.headerName)-1]
		includes = append(includes, inc)
	}
	return includes, nil
}

// Start - base function
func Start(args ProgramArgs) error {
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	_, err := os.Stat(args.inputFile)
	if err != nil {
		return fmt.Errorf("Input file is not found")
	}

	// 2. Preprocess
	var pp []byte
	{
		cmd := exec.Command("clang", "-E", args.inputFile)
		var out bytes.Buffer
		var stderr bytes.Buffer
		cmd.Stdout = &out
		cmd.Stderr = &stderr
		err = cmd.Run()
		if err != nil {
			var errorResult string
			// add error message from stdErr
			errorResult += fmt.Sprintf("preprocess failed: %v\nStdErr = %v\n", err, stderr.String())
			// parse error output for found lost includes
			lostIncludes, err := parseForFoundLostIncluse(stderr.String())
			if err != nil {
				errorResult += fmt.Sprintf("Cannot parse for found lost includes: %v", err)
			} else {
				// NEED TO APPROVE
				// Theoretically: system headers is not need for transpiling,
				// and system header need only for clang correct working,
				// but internal header is important
				var haveLostInternalHeader bool
				for _, lostInclude := range lostIncludes {
					if lostInclude.typeHeader == internalHeader {
						haveLostInternalHeader = true
						break
					}
				}
				if !haveLostInternalHeader {
					// now, we found lost system header file
					// so, we can try remove lost system header file and try again
					panic(fmt.Errorf("Present state of error = %v", errorResult))
				}
				for _, lostInclude := range lostIncludes {
					errorResult += fmt.Sprintf("Lost header file #include:\n %v\n", lostInclude)
				}
			}
			return fmt.Errorf(errorResult)
		}
		pp = []byte(out.String())
	}

	ppFilePath := path.Join(os.TempDir(), "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to /tmp/pp.c failed: %v", err)
	}

	// 3. Generate JSON from AST
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()
	}

	nodes := convertLinesToNodes(lines)
	tree := buildTree(nodes, 0)

	p := program.NewProgram()
	p.Verbose = args.verbose

	err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		panic(err)
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		cleanFileName := filepath.Clean(filepath.Base(args.inputFile))
		extension := filepath.Ext(args.inputFile)

		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755)
	if err != nil {
		return fmt.Errorf("writing C output file failed: %v", err)
	}

	return nil
}

// newTempFile - returns temp file
func newTempFile(dir, prefix, suffix string) (*os.File, error) {
	for index := 1; index < 10000; index++ {
		path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix))
		if _, err := os.Stat(path); err != nil {
			return os.Create(path)
		}
	}
	return nil, fmt.Errorf("could not create file: %s%03d%s", prefix, 1, suffix)
}

func main() {
	var (
		versionFlag       = flag.Bool("v", false, "print the version and exit")
		transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
		verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
		outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
		packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
		transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
		astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
		astHelpFlag       = astCommand.Bool("h", false, "print help information")
	)

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file.c\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()

		// print flags of transpile command
		fmt.Println("\nFlags of transpile command:")
		transpileCommand.PrintDefaults()

		// print flags of ast command
		fmt.Println("\nFlags of ast command:")
		astCommand.PrintDefaults()

		// examples
		fmt.Println("\nExamples of flag using:")
		fmt.Println("\nc2go -h\n\treturn the help", "")
		fmt.Println("\nc2go transpile -o source.go source.c\n\ttranspiling file source.c to Go file with name source.go")
	}

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return
	}

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(1)
	}

	args := ProgramArgs{verbose: *verboseFlag, ast: false}

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			os.Exit(1)
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(os.Stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			os.Exit(1)
		}

		args.ast = true
		args.inputFile = astCommand.Arg(0)
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			os.Exit(1)
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(os.Stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0])
			transpileCommand.PrintDefaults()
			os.Exit(1)
		}

		args.inputFile = transpileCommand.Arg(0)
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
	default:
		flag.Usage()
		os.Exit(1)
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v", err)
		os.Exit(1)
	}
}
<commit_msg>add weblink<commit_after>// Package c2go contains the main function for running the executable.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/Konstantin8105/c2go/util"
	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "0.13.3"

// ProgramArgs - arguments of program
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFile   string
	outputFile  string
	packageName string
}

func readAST(data []byte) []string {
	uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{})
	return strings.Split(string(uncolored), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := []treeNode{}
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)

		indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line)
		if len(indentAndType) == 0 {
			panic(fmt.Sprintf("Cannot understand line '%s'", line))
		}

		offset := len(indentAndType[1])
		node := ast.Parse(line[offset:])

		indentLevel := len(indentAndType[1]) / 2
		nodes = append(nodes, treeNode{indentLevel, node})
	}

	return nodes
}

// buildTree convert an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a a tree with its own root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

/* Dead code
// ToJSON - tree convert to JSON
func ToJSON(tree []interface{}) []map[string]interface{} {
	r := make([]map[string]interface{}, len(tree))

	for j, n := range tree {
		rn := reflect.ValueOf(n).Elem()
		r[j] = make(map[string]interface{})
		r[j]["node"] = rn.Type().Name()

		for i := 0; i < rn.NumField(); i++ {
			name := strings.ToLower(rn.Type().Field(i).Name)
			value := rn.Field(i).Interface()

			if name == "children" {
				v := value.([]interface{})

				if len(v) == 0 {
					continue
				}

				value = ToJSON(v)
			}

			r[j][name] = value
		}
	}

	return r
}
*/

type headerTypes bool

const (
	systemHeader   headerTypes = true
	internalHeader headerTypes = false
)

type include struct {
	headerName string
	typeHeader headerTypes
}

func (inc include) String() (s string) {
	s += fmt.Sprintf("\tHeader name : %v\n", inc.headerName)
	s += fmt.Sprintf("\tType : ")
	switch inc.typeHeader {
	case systemHeader:
		s += fmt.Sprintf("System header\n")
	case internalHeader:
		s += fmt.Sprintf("Internal header\n")
	}
	return
}

// parseForFoundLostIncluse - parsing string to
// found lost includes in c code after clang
//
// Example of input:
// E:\Temp\c2go001preprocess.c:1:10: fatal error: 'AbsoluteWrongInclude.h' file not found
// #include <AbsoluteWrongInclude.h>
//          ^~~~~~~~~~~~~~~~~~~~~~~~
// tests\struct.c:3:10: fatal error: 'stdio.h' file not found
//                #include <stdio.h>
//                         ^~~~~~~~~
//                1 error generated.
func parseForFoundLostIncluse(s string) (includes []include, err error) {
	lines, err := util.StringToLines(s)
	if err != nil {
		return includes, err
	}
	includeName := "#include"
	regSystem := regexp.MustCompile("<(.*?)>")
	regInternal := regexp.MustCompile("\"(.*?)\"")
	for _, line := range lines {
		if !strings.Contains(line, includeName) {
			continue
		}
		// Now, we know - the string line have "#include"
		// Find the name of header file
		var inc include
		if strings.ContainsAny(line, "<>") {
			// system header
			inc.headerName = regSystem.FindString(line)
			inc.typeHeader = systemHeader
		} else {
			// internal header
			inc.headerName = regInternal.FindString(line)
			inc.typeHeader = internalHeader
		}
		inc.headerName = inc.headerName[1 : len(inc.headerName)-1]
		includes = append(includes, inc)
	}
	return includes, nil
}

// Start - base function
func Start(args ProgramArgs) error {
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	_, err := os.Stat(args.inputFile)
	if err != nil {
		return fmt.Errorf("Input file is not found")
	}

	// 2. Preprocess
	var pp []byte
	{
		// See : https://clang.llvm.org/docs/CommandGuide/clang.html
		// clang -E <file>    Run the preprocessor stage.
		cmd := exec.Command("clang", "-E", args.inputFile)
		var out bytes.Buffer
		var stderr bytes.Buffer
		cmd.Stdout = &out
		cmd.Stderr = &stderr
		err = cmd.Run()
		if err != nil {
			var errorResult string
			// add error message from stdErr
			errorResult += fmt.Sprintf("preprocess failed: %v\nStdErr = %v\n", err, stderr.String())
			// parse error output for found lost includes
			lostIncludes, err := parseForFoundLostIncluse(stderr.String())
			if err != nil {
				errorResult += fmt.Sprintf("Cannot parse for found lost includes: %v", err)
			} else {
				// NEED TO APPROVE
				// Theoretically: system headers is not need for transpiling,
				// and system header need only for clang correct working,
				// but internal header is important
				var haveLostInternalHeader bool
				for _, lostInclude := range lostIncludes {
					if lostInclude.typeHeader == internalHeader {
						haveLostInternalHeader = true
						break
					}
				}
				if !haveLostInternalHeader {
					// now, we found lost system header file
					// so, we can try remove lost system header file and try again
					panic(fmt.Errorf("Present state of error = %v", errorResult))
				}
				for _, lostInclude := range lostIncludes {
					errorResult += fmt.Sprintf("Lost header file #include:\n %v\n", lostInclude)
				}
			}
			return fmt.Errorf(errorResult)
		}
		pp = []byte(out.String())
	}

	ppFilePath := path.Join(os.TempDir(), "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to /tmp/pp.c failed: %v", err)
	}

	// 3. Generate JSON from AST
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()
	}

	nodes := convertLinesToNodes(lines)
	tree := buildTree(nodes, 0)

	p := program.NewProgram()
	p.Verbose = args.verbose

	err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		panic(err)
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		cleanFileName := filepath.Clean(filepath.Base(args.inputFile))
		extension := filepath.Ext(args.inputFile)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755)
	if err != nil {
		return fmt.Errorf("writing C output file failed: %v", err)
	}

	return nil
}

// newTempFile - returns temp file
func newTempFile(dir, prefix, suffix string) (*os.File, error) {
	for index := 1; index < 10000; index++ {
		path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix))
		if _, err := os.Stat(path); err != nil {
			return os.Create(path)
		}
	}
	return nil, fmt.Errorf("could not create file: %s%03d%s", prefix, 1, suffix)
}

func main() {
	var (
		versionFlag       = flag.Bool("v", false, "print the version and exit")
		transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
		verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
		outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
		packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
		transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
		astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
		astHelpFlag       = astCommand.Bool("h", false, "print help information")
	)

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file.c\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()

		// print flags of transpile command
		fmt.Println("\nFlags of transpile command:")
		transpileCommand.PrintDefaults()

		// print flags of ast command
		fmt.Println("\nFlags of ast command:")
		astCommand.PrintDefaults()

		// examples
		fmt.Println("\nExamples of flag using:")
		fmt.Println("\nc2go -h\n\treturn the help", "")
		fmt.Println("\nc2go transpile -o source.go source.c\n\ttranspiling file source.c to Go file with name source.go")
	}

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return
	}

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(1)
	}

	args := ProgramArgs{verbose: *verboseFlag, ast: false}

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			os.Exit(1)
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(os.Stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			os.Exit(1)
		}

		args.ast = true
		args.inputFile = astCommand.Arg(0)
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			os.Exit(1)
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(os.Stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0])
			transpileCommand.PrintDefaults()
			os.Exit(1)
		}

		args.inputFile = transpileCommand.Arg(0)
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
	default:
		flag.Usage()
		os.Exit(1)
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	gorillasession "github.com/gorilla/sessions"
	"github.com/ory-am/common/env"
	"github.com/ory-am/common/mgopath"
	"github.com/ory-am/event"
	"github.com/ory-am/gitdeploy/eco"
	"github.com/ory-am/gitdeploy/ip"
	"github.com/ory-am/gitdeploy/job"
	"github.com/ory-am/gitdeploy/job/deploy"
	gdLog "github.com/ory-am/gitdeploy/log"
	"github.com/ory-am/gitdeploy/public"
	"github.com/ory-am/gitdeploy/sse"
	"github.com/ory-am/gitdeploy/storage"
	"github.com/ory-am/gitdeploy/storage/mongo"
	"github.com/ory-am/gitdeploy/task"
	"github.com/ory-am/gitdeploy/task/flynn"
	"github.com/ory-am/google-json-style-response/responder"
	"gopkg.in/mgo.v2"
	"gopkg.in/validator.v2"
	"log"
	"net/http"
	"time"
)

const (
	sessionCurrentDeployment = "cdid"
	sessionName              = "gdp"
)

var (
	ApiVersion      = "1.0"
	host            = env.Getenv("HOST", "")
	port            = env.Getenv("PORT", "7654")
	envAppTtl       = env.Getenv("APP_TTL", "30m")
	envClusterConf  = env.Getenv("FLYNN_CLUSTER_CONFIG", "")
	corsAllowOrigin = env.Getenv("CORS_ALLOW_ORIGIN", "http://localhost:9000")
	sessionStore    = gorillasession.NewCookieStore([]byte(env.Getenv("SESSION_SECRET", "changme")))
	envMongoPath    = env.Getenv("MONGODB", "mongodb://localhost:27017/gitdeploy")
)

type deployRequest struct {
	Repository string `json:"repository",validate:"regex=^(https|http):\\/\\/github\\.com\\/[a-zA-Z0-9\\-\\_\\.]+/[a-zA-Z0-9\\-\\_\\.]+$"`
	Ref        string `json:"ref",validate:"regex=^(origin\\/.*|tags\\/.*|[a-z0-9]+)$"`
}

type appResponse struct {
	App string `json:"app"`
}

func main() {
	eco.IsGitAvailable()
	eco.IsFlynnAvailable()
	init := flag.Bool("init", false, "Initialize flynn")
	flag.Parse()
	if *init {
		eco.InitFlynn(envClusterConf)
		eco.InitGit()
	}

	db, dbName, err := mgopath.Connect(envMongoPath)
	if err != nil {
		log.Fatal(err)
	}
	eventManager := event.New()
	storage := mongo.New(db, dbName)
	sseBroker := sse.New(storage)
	eventManager.AttachListenerAggregate(storage)
	eventManager.AttachListenerAggregate(new(gdLog.Listener))

	// Mux router
	r := mux.NewRouter()
	r.HandleFunc("/config", configHandler).Methods("GET")
	r.HandleFunc("/deployments", deployWrapperAction(sseBroker, eventManager, storage)).Methods("POST")
	r.HandleFunc("/deployments", setCORSHeaders).Methods("OPTIONS")
	r.HandleFunc("/deployments/{app:.+}/events", eventWrapperAction(sseBroker)).Methods("GET")
	r.HandleFunc("/apps/{app:.+}", getAppHandler(storage)).Methods("GET")
	r.PathPrefix("/").HandlerFunc(public.HTML5ModeHandler("./app/dist", "index.html"))
	http.Handle("/", r)

	go job.KillAppsOnHitList(storage)

	listen := fmt.Sprintf("%s:%s", host, port)
	log.Printf("Listening on %s", listen)
	log.Fatal(http.ListenAndServe(listen, nil))
}

func eventWrapperAction(sseBroker *sse.Broker) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		sseBroker.EventHandler(w, r)
	}
}

func deployWrapperAction(sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		deployAction(w, r, sseBroker, em, store)
	}
}

func configHandler(w http.ResponseWriter, r *http.Request) {
	setCORSHeaders(w, r)
	responseSuccess(w, struct {
		Now time.Time `json:"now"`
	}{time.Now()})
}

func getAppHandler(store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if cleanUpSession(w, r) != nil {
			return
		}
		setCORSHeaders(w, r)
		vars := mux.Vars(r)
		id := vars["app"]
		app, err := store.GetApp(id)
		if err == mgo.ErrNotFound {
			responseError(w, http.StatusNotFound, fmt.Sprintf("App %s does not exist.", id))
			return
		} else if app.Killed {
			responseError(w, http.StatusNotFound, "App timed out and is no longer available.")
			return
		} else if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		logs, err := flynn.GetLogs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		ps, err := flynn.GetProcs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		deployLogs, err := store.FindDeployLogsForApp(id)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		responseSuccess(w, struct {
			*storage.App
			Logs       string                 `json:"logs"`
			DeployLogs []*storage.DeployEvent `json:"deployLogs,inline"`
			PS         string                 `json:"ps"`
		}{app, logs, deployLogs, ps})
	}
}

func deployAction(w http.ResponseWriter, r *http.Request, sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return
	}

	// Check if the user is currently deploying an application and switch to that one.
	if v, ok := session.Values[sessionCurrentDeployment].(string); ok && len(v) > 0 {
		app, err := store.GetApp(v)
		if err != nil {
			cleanUpSession(w, r)
			log.Printf("Could not fetch app from cookie: %s", err.Error())
		} else if !sseBroker.IsChannelOpen(app.ID) {
			cleanUpSession(w, r)
			log.Printf("Channel %s does not exist any more", app.ID)
		} else {
			responseSuccess(w, app)
			return
		}
	}

	dr := new(deployRequest)
	app := uuid.NewRandom().String()
	ttl, err := time.ParseDuration(envAppTtl)
	if err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else if err := json.NewDecoder(r.Body).Decode(dr); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else if err := validator.Validate(dr); err != nil {
		responseError(w, http.StatusBadRequest, fmt.Sprintf("Validation failed: %s", err))
		return
	}

	if dr.Repository[len(dr.Repository)-4:] != ".git" {
		dr.Repository = dr.Repository + ".git"
	}
	if len(dr.Ref) == 0 {
		dr.Ref = "master"
	}
	appEntity, err := store.AddApp(app, time.Now().Add(ttl), dr.Repository, ip.GetRemoteAddr(r), dr.Ref)
	if err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	}

	session.Values[sessionCurrentDeployment] = appEntity.ID
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	}

	responseSuccess(w, appEntity)
	go func() {
		sseBroker.OpenChannel(app)
		sseBroker.Start(app)
		defer func() {
			// Give the client the chance to read the output...
			time.Sleep(15 * time.Second)
			sseBroker.CloseChannel(app)
		}()
		tasks := deploy.CreateJob(store, appEntity)
		err := task.RunJob(app, em, tasks)
		if err != nil {
			log.Printf("Error in task.RunJob: %s", err)
		}
	}()
}

func cleanUpSession(w http.ResponseWriter, r *http.Request) error {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return err
	}
	delete(session.Values, sessionCurrentDeployment)
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return err
	}
	return nil
}

// Set the different CORS headers required for CORS request
func setCORSHeaders(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
	w.Header().Set("Access-Control-Allow-Origin", corsAllowOrigin)
	w.Header().Set("Access-Control-Allow-Credentials", "true")
	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
}

func responseError(w http.ResponseWriter, code int, message string) {
	log.Printf("Error %d: %s", code, message)
	response := responder.New(ApiVersion)
	response.Write(w, response.Error(code, message))
}

func responseSuccess(w http.ResponseWriter, data interface{}) {
	response := responder.New(ApiVersion)
	response.Write(w, response.Success(data))
}
<commit_msg>main: more logging<commit_after>package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	gorillasession "github.com/gorilla/sessions"
	"github.com/ory-am/common/env"
	"github.com/ory-am/common/mgopath"
	"github.com/ory-am/event"
	"github.com/ory-am/gitdeploy/eco"
	"github.com/ory-am/gitdeploy/ip"
	"github.com/ory-am/gitdeploy/job"
	"github.com/ory-am/gitdeploy/job/deploy"
	gdLog "github.com/ory-am/gitdeploy/log"
	"github.com/ory-am/gitdeploy/public"
	"github.com/ory-am/gitdeploy/sse"
	"github.com/ory-am/gitdeploy/storage"
	"github.com/ory-am/gitdeploy/storage/mongo"
	"github.com/ory-am/gitdeploy/task"
	"github.com/ory-am/gitdeploy/task/flynn"
	"github.com/ory-am/google-json-style-response/responder"
	"gopkg.in/mgo.v2"
	"gopkg.in/validator.v2"
	"log"
	"net/http"
	"time"
)

const (
	sessionCurrentDeployment = "cdid"
	sessionName              = "gdp"
)

var (
	ApiVersion      = "1.0"
	host            = env.Getenv("HOST", "")
	port            = env.Getenv("PORT", "7654")
	envAppTtl       = env.Getenv("APP_TTL", "30m")
	envClusterConf  = env.Getenv("FLYNN_CLUSTER_CONFIG", "")
	corsAllowOrigin = env.Getenv("CORS_ALLOW_ORIGIN", "http://localhost:9000")
	sessionStore    = gorillasession.NewCookieStore([]byte(env.Getenv("SESSION_SECRET", "changme")))
	envMongoPath    = env.Getenv("MONGODB", "mongodb://localhost:27017/gitdeploy")
)

type deployRequest struct {
	Repository string `json:"repository",validate:"regex=^(https|http):\\/\\/github\\.com\\/[a-zA-Z0-9\\-\\_\\.]+/[a-zA-Z0-9\\-\\_\\.]+$"`
	Ref        string `json:"ref",validate:"regex=^(origin\\/.*|tags\\/.*|[a-z0-9]+)$"`
}

type appResponse struct {
	App string `json:"app"`
}

func main() {
	eco.IsGitAvailable()
	eco.IsFlynnAvailable()
	init := flag.Bool("init", false, "Initialize flynn")
	flag.Parse()
	if *init {
		eco.InitFlynn(envClusterConf)
		eco.InitGit()
	}

	db, dbName, err := mgopath.Connect(envMongoPath)
	if err != nil {
		log.Fatal(err)
	}
	eventManager := event.New()
	storage := mongo.New(db, dbName)
	sseBroker := sse.New(storage)
	eventManager.AttachListenerAggregate(storage)
	eventManager.AttachListenerAggregate(new(gdLog.Listener))

	// Mux router
	r := mux.NewRouter()
	r.HandleFunc("/config", configHandler).Methods("GET")
	r.HandleFunc("/deployments", deployWrapperAction(sseBroker, eventManager, storage)).Methods("POST")
	r.HandleFunc("/deployments", setCORSHeaders).Methods("OPTIONS")
	r.HandleFunc("/deployments/{app:.+}/events", eventWrapperAction(sseBroker)).Methods("GET")
	r.HandleFunc("/apps/{app:.+}", getAppHandler(storage)).Methods("GET")
	r.PathPrefix("/").HandlerFunc(public.HTML5ModeHandler("./app/dist", "index.html"))
	http.Handle("/", r)

	go job.KillAppsOnHitList(storage)

	listen := fmt.Sprintf("%s:%s", host, port)
	log.Printf("Listening on %s", listen)
	log.Fatal(http.ListenAndServe(listen, nil))
}

func eventWrapperAction(sseBroker *sse.Broker) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		sseBroker.EventHandler(w, r)
	}
}

func deployWrapperAction(sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		deployAction(w, r, sseBroker, em, store)
	}
}

func configHandler(w http.ResponseWriter, r *http.Request) {
	setCORSHeaders(w, r)
	responseSuccess(w, struct {
		Now time.Time `json:"now"`
	}{time.Now()})
}

func getAppHandler(store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if cleanUpSession(w, r) != nil {
			return
		}
		setCORSHeaders(w, r)
		vars := mux.Vars(r)
		id := vars["app"]
		app, err := store.GetApp(id)
		if err == mgo.ErrNotFound {
			responseError(w, http.StatusNotFound, fmt.Sprintf("App %s does not exist.", id))
			return
		} else if app.Killed {
			responseError(w, http.StatusNotFound, "App timed out and is no longer available.")
			return
		} else if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		logs, err := flynn.GetLogs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		ps, err := flynn.GetProcs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		deployLogs, err := store.FindDeployLogsForApp(id)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		responseSuccess(w, struct {
			*storage.App
			Logs       string                 `json:"logs"`
			DeployLogs []*storage.DeployEvent `json:"deployLogs,inline"`
			PS         string                 `json:"ps"`
		}{app, logs, deployLogs, ps})
	}
}

func deployAction(w http.ResponseWriter, r *http.Request, sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) {
	app := uuid.NewRandom().String()
	log.Printf("Trying to fetch session: %s", app)
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return
	}

	// Check if the user is currently deploying an application and switch to that one.
	if v, ok := session.Values[sessionCurrentDeployment].(string); ok && len(v) > 0 {
		a, err := store.GetApp(v)
		if err != nil {
			cleanUpSession(w, r)
			log.Printf("Could not fetch app from cookie: %s", err.Error())
		} else if !sseBroker.IsChannelOpen(a.ID) {
			cleanUpSession(w, r)
			log.Printf("Channel %s does not exist any more", a.ID)
		} else {
			responseSuccess(w, a)
			return
		}
	}

	log.Printf("No deployment active for this session, starting new one: %s", app)
	dr := new(deployRequest)
	ttl, err := time.ParseDuration(envAppTtl)
	if err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else if err := json.NewDecoder(r.Body).Decode(dr); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else if err := validator.Validate(dr); err != nil {
		responseError(w, http.StatusBadRequest, fmt.Sprintf("Validation failed: %s", err))
		return
	}

	log.Printf("Validation passed: %s", app)
	if dr.Repository[len(dr.Repository)-4:] != ".git" {
		dr.Repository = dr.Repository + ".git"
	}
	if len(dr.Ref) == 0 {
		dr.Ref = "master"
	}

	log.Printf("Storing app information: %s", app)
	appEntity, err := store.AddApp(app, time.Now().Add(ttl), dr.Repository, ip.GetRemoteAddr(r), dr.Ref)
	if err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	}

	session.Values[sessionCurrentDeployment] = appEntity.ID
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	}

	log.Printf("Storing app information: %s", app)
	responseSuccess(w, appEntity)
	go func() {
		sseBroker.OpenChannel(app)
		sseBroker.Start(app)
		defer func() {
			log.Printf("Waiting for slow clients: %s", app)
			// Give the client the chance to read the output...
			time.Sleep(5 * time.Second)
			log.Printf("Timeout for slow clients: %s", app)
			sseBroker.CloseChannel(app)
		}()
		log.Printf("Creating job: %s", app)
		tasks := deploy.CreateJob(store, appEntity)
		log.Printf("Run job: %s", app)
		err := task.RunJob(app, em, tasks)
		if err != nil {
			log.Printf("Error in task.RunJob: %s", err)
		}
	}()
}

func cleanUpSession(w http.ResponseWriter, r *http.Request) error {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return err
	}
	delete(session.Values, sessionCurrentDeployment)
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return err
	}
	return nil
}

// Set the different CORS headers required for CORS request
func setCORSHeaders(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
	w.Header().Set("Access-Control-Allow-Origin", corsAllowOrigin)
	w.Header().Set("Access-Control-Allow-Credentials", "true")
	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
}

func responseError(w http.ResponseWriter, code int, message string) {
	log.Printf("Error %d: %s", code, message)
	response := responder.New(ApiVersion)
	response.Write(w, response.Error(code, message))
}

func responseSuccess(w http.ResponseWriter, data interface{}) {
	response := responder.New(ApiVersion)
	response.Write(w, response.Success(data))
}
<|endoftext|>


<commit_before>package main

import (
	"runtime"

	"github.com/filebrowser/filebrowser/v2/cmd"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	cmd.Execute()
}
<commit_msg>chore: remove GOMAXPROCS setting (#1803)<commit_after>package main

import (
	"github.com/filebrowser/filebrowser/v2/cmd"
)

func main() {
	cmd.Execute()
}
<|endoftext|>