<commit_before>package main

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

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 = " + ps.ByName("id"))
	data := BlogPost{}
	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.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 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.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 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()
	router := httprouter.New()
	//router.GET("/", GetDoc)
	router.GET("/blog", GetBlog)
	router.GET("/blog/:id", GetPost)
	router.GET("/spin/latest", GetLatestSpinData)
	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)
	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>route for specific posts<commit_after>package main

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

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", 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.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 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.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 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()
	router := httprouter.New()
	//router.GET("/", GetDoc)
	router.GET("/blog", GetBlog)
	router.GET("/blog/:id", GetPost)
	router.GET("/spin/latest", GetLatestSpinData)
	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)
	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))
}<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/gogo/protobuf/proto"
	log "github.com/golang/glog"
	"github.com/mesos/mesos-go/auth"
	"github.com/mesos/mesos-go/auth/sasl"
	"github.com/mesos/mesos-go/auth/sasl/mech"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	sched "github.com/mesos/mesos-go/scheduler"
	mlog "github.com/yp-engineering/mesos-runonce/mesosutil"
	"golang.org/x/net/context"
)

var eventCh = make(chan *mesos.TaskStatus)
var _frameworkId string

var (
	address      = flag.String("address", "127.0.0.1", "Address for mesos to callback on.")
	bindingPort  = flag.Uint("port", 0, "Port for address to use for mesos to callback.")
	authProvider = flag.String("authentication-provider", sasl.ProviderName,
		fmt.Sprintf("Authentication provider to use, default is SASL that supports mechanisms: %+v", mech.ListSupported()))
	master               = flag.String("master", "127.0.0.1:5050", "Master address <ip:port>")
	taskCount            = flag.Int("task-count", 1, "Total task count to run.")
	mesosTaskID          = flag.String("task-id", "", "Mesos task id to identify the task.")
	mesosTaskName        = flag.String("task-name", "", "Mesos task name to label the task.")
	mesosAuthPrincipal   = flag.String("principal", "", "Mesos authentication principal.")
	mesosAuthSecretFile  = flag.String("secret-file", "", "Mesos authentication secret file.")
	mesosRunasUser       = flag.String("user", "root", "Mesos user to run tasks as.")
	dockerImage          = flag.String("docker-image", "", "Docker image to run.")
	dockerCmd            = flag.String("docker-cmd", "", "Docker command to run.")
	dockerForcePullImage = flag.Bool("force-pull", false, "Boolean for forcing pull of image before run.")
	dockerEnvVars        = flag.String("env-vars", "", "Docker env vars for the container. E.g. -env-vars='{\"env\":{\"FOO\":\"bar\"}}'")
	dCpus                = flag.Float64("cpus", 1.0, "How many CPUs to use.")
	dMem                 = flag.Float64("mem", 10, "How much memory to use.")
)

type ExampleScheduler struct {
	executor      *mesos.ExecutorInfo
	tasksLaunched int
	tasksFinished int
	totalTasks    int
}

type DockerEnvVars struct {
	Env map[string]string `json:"env"`
}

func newExampleScheduler(exec *mesos.ExecutorInfo) *ExampleScheduler {
	return &ExampleScheduler{
		executor:      exec,
		tasksLaunched: 0,
		tasksFinished: 0,
		totalTasks:    *taskCount,
	}
}

func (sched *ExampleScheduler) Registered(driver sched.SchedulerDriver, frameworkId *mesos.FrameworkID, masterInfo *mesos.MasterInfo) {
	log.V(1).Infoln("Framework Registered with Master ", masterInfo)
	_frameworkId = frameworkId.GetValue()
	fmt.Println("Registered with master and given framework ID:", _frameworkId)
}
func (sched *ExampleScheduler) Reregistered(driver sched.SchedulerDriver, masterInfo *mesos.MasterInfo) {
	log.V(1).Infoln("Framework Re-Registered with Master ", masterInfo)
}
func (sched *ExampleScheduler) Disconnected(sched.SchedulerDriver) {
	log.Exitf("disconnected from master, aborting")
}
func (sched *ExampleScheduler) OfferRescinded(_ sched.SchedulerDriver, oid *mesos.OfferID) {
	log.Errorf("offer rescinded: %v", oid)
}
func (sched *ExampleScheduler) FrameworkMessage(_ sched.SchedulerDriver, eid *mesos.ExecutorID, sid *mesos.SlaveID, msg string) {
	log.Errorf("framework message from executor %q slave %q: %q", eid, sid, msg)
}
func (sched *ExampleScheduler) SlaveLost(_ sched.SchedulerDriver, sid *mesos.SlaveID) {
	log.Errorf("slave lost: %v", sid)
}
func (sched *ExampleScheduler) ExecutorLost(_ sched.SchedulerDriver, eid *mesos.ExecutorID, sid *mesos.SlaveID, code int) {
	log.Errorf("executor %q lost on slave %q code %d", eid, sid, code)
}
func (sched *ExampleScheduler) Error(_ sched.SchedulerDriver, err string) {
	log.Exitf("Scheduler received error: %v", err)
}

func (sched *ExampleScheduler) ResourceOffers(driver sched.SchedulerDriver, offers []*mesos.Offer) {

	if sched.tasksLaunched >= sched.totalTasks {
		log.V(1).Info("decline all of the offers since all of our tasks are already launched")
		ids := make([]*mesos.OfferID, len(offers))
		for i, offer := range offers {
			ids[i] = offer.Id
		}
		driver.LaunchTasks(ids, []*mesos.TaskInfo{}, &mesos.Filters{RefuseSeconds: proto.Float64(120)})
		return
	}
	for _, offer := range offers {
		cpuResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "cpus"
		})
		cpus := 0.0
		for _, res := range cpuResources {
			cpus += res.GetScalar().GetValue()
		}

		memResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "mem"
		})
		mems := 0.0
		for _, res := range memResources {
			mems += res.GetScalar().GetValue()
		}

		log.V(1).Infoln("Received Offer <", offer.Id.GetValue(), "> on host ", *offer.Hostname, "with cpus=", cpus, " mem=", mems)

		remainingCpus := cpus
		remainingMems := mems

		var tasks []*mesos.TaskInfo
		for sched.tasksLaunched < sched.totalTasks &&
			*dCpus <= remainingCpus &&
			*dMem <= remainingMems {

			sched.tasksLaunched++

			tID := strconv.Itoa(sched.tasksLaunched)
			if *mesosTaskID != "" {
				tID = *mesosTaskID
			}

			tName := "mesos-runonce-" + tID
			if *mesosTaskName != "" {
				tName = *mesosTaskName
			}

			taskId := &mesos.TaskID{
				Value: proto.String(tID),
			}

			containerType := mesos.ContainerInfo_DOCKER
			task := &mesos.TaskInfo{
				Name:    proto.String(tName),
				TaskId:  taskId,
				SlaveId: offer.SlaveId,
				Resources: []*mesos.Resource{
					util.NewScalarResource("cpus", *dCpus),
					util.NewScalarResource("mem", *dMem),
				},
				Command: &mesos.CommandInfo{
					Shell: proto.Bool(false),
				},
				Container: &mesos.ContainerInfo{
					Type: &containerType,
					Docker: &mesos.ContainerInfo_DockerInfo{
						Image:          proto.String(*dockerImage),
						ForcePullImage: proto.Bool(*dockerForcePullImage),
					},
				},
			}
			log.V(1).Infof("Prepared task: %s with offer %s for launch\n", task.GetName(), offer.Id.GetValue())

			if *dockerEnvVars != "" {
				task.Command.Environment = envVars()
			}

			// Allow arbitrary commands, else just use whatever the image defines in CMD
			if *dockerCmd != "" {
				task.Command.Value = proto.String(*dockerCmd)
				task.Command.Shell = proto.Bool(true)
			}

			tasks = append(tasks, task)
			remainingCpus -= *dCpus
			remainingMems -= *dMem
		}
		log.V(1).Infoln("Launching ", len(tasks), "tasks for offer", offer.Id.GetValue())
		driver.LaunchTasks([]*mesos.OfferID{offer.Id}, tasks, &mesos.Filters{RefuseSeconds: proto.Float64(5)})
	}
}

func (sched *ExampleScheduler) StatusUpdate(driver sched.SchedulerDriver, status *mesos.TaskStatus) {
	log.V(1).Infoln("Status update: task", status.TaskId.GetValue(), " is in state ", status.State.Enum().String())
	eventCh <- status

	if status.GetState() == mesos.TaskState_TASK_FINISHED {
		sched.tasksFinished++
	}

	if sched.tasksFinished >= sched.totalTasks {
		log.V(1).Infoln("Total tasks completed, stopping framework.")
		driver.Stop(false)
	}

	if status.GetState() == mesos.TaskState_TASK_LOST ||
		status.GetState() == mesos.TaskState_TASK_KILLED ||
		status.GetState() == mesos.TaskState_TASK_FAILED ||
		status.GetState() == mesos.TaskState_TASK_ERROR {
		log.Warningf("mesos TaskStatus: %v", status)
		driver.Abort()
		log.Errorln(
			"Aborting because task", status.TaskId.GetValue(),
			"is in unexpected state", status.State.String(),
			"with message.", status.GetMessage(),
		)
	}
}

// ----------------------- func init() ------------------------- //

func init() {
	flag.Parse()
	log.V(1).Infoln("Initializing the Example Scheduler...")
}

func printLogs() {
	timer := time.Tick(500 * time.Millisecond)
	var (
		readableStatus *mesos.TaskStatus
		finished       bool
		oout, oerr     int
	)
	for {
		select {
		case status := <-eventCh:
			switch status.GetState() {
			case mesos.TaskState_TASK_RUNNING,
				mesos.TaskState_TASK_STARTING:
				readableStatus = status
			case mesos.TaskState_TASK_FAILED,
				mesos.TaskState_TASK_KILLED:
				readableStatus = status
				finished = true
			case mesos.TaskState_TASK_FINISHED:
				finished = true
			}
		case <-timer:
			if readableStatus != nil {
				if finished {
					time.Sleep(3 * time.Second)
				}
				x := printLog(readableStatus, oout, os.Stdout)
				y := printLog(readableStatus, oerr, os.Stderr)
				if finished && x == 0 && y == 0 {
					return
				}
				oout += x
				oerr += y
			}
		}
	}
}

func printLog(status *mesos.TaskStatus, offset int, w io.Writer) int {
	file := "stdout"
	if w == os.Stderr {
		file = "stderr"
	}
	data, err := mlog.FetchLogs(status, offset, file, _frameworkId)
	if err != nil {
		log.V(1).Infof("fetch logs err: %s\n", err)
		return 0
	}
	if len(data) > 0 {
		fmt.Fprint(w, string(data))
	}
	return len(data)
}

func prepareExecutorInfo() *mesos.ExecutorInfo {
	// Create mesos scheduler driver.
	containerType := mesos.ContainerInfo_DOCKER
	return &mesos.ExecutorInfo{
		ExecutorId: util.NewExecutorID("default"),
		Name:       proto.String("mesos-runonce-executor"),
		Source:     proto.String("mesos-runonce-executor"),
		Container: &mesos.ContainerInfo{
			Type: &containerType,
		},
	}
}

func parseIP(address string) net.IP {
	addr, err := net.LookupIP(address)
	if err != nil {
		log.Exit(err)
	}
	if len(addr) < 1 {
		log.Exitf("failed to parse IP from address '%v'", address)
	}
	return addr[0]
}

func envVars() *mesos.Environment {
	var dEnvVars DockerEnvVars
	err := json.Unmarshal([]byte(*dockerEnvVars), &dEnvVars)
	if err != nil {
		log.Exitf("JSON error: %#v with unparsable env vars: %+v", err, *dockerEnvVars)
	}

	var variables []*mesos.Environment_Variable
	for key, value := range dEnvVars.Env {
		variables = append(variables, &mesos.Environment_Variable{Name: proto.String(key), Value: proto.String(value)})
	}

	return &mesos.Environment{Variables: variables}
}

// ----------------------- func main() ------------------------- //

func main() {

	// build command executor
	exec := prepareExecutorInfo()

	// the framework
	fwinfo := &mesos.FrameworkInfo{
		User: proto.String(*mesosRunasUser),
		Name: proto.String("mesos-runonce"),
	}

	cred := (*mesos.Credential)(nil)
	if *mesosAuthPrincipal != "" {
		fwinfo.Principal = proto.String(*mesosAuthPrincipal)
		cred = &mesos.Credential{
			Principal: proto.String(*mesosAuthPrincipal),
		}
		if *mesosAuthSecretFile != "" {
			_, err := os.Stat(*mesosAuthSecretFile)
			if err != nil {
				log.Exit("missing secret file: ", err.Error())
			}
			secret, err := ioutil.ReadFile(*mesosAuthSecretFile)
			if err != nil {
				log.Exit("failed to read secret file: ", err.Error())
			}
			cred.Secret = proto.String(string(secret))
		}
	}

	publishedAddress := parseIP(*address)
	config := sched.DriverConfig{
		Scheduler:        newExampleScheduler(exec),
		Framework:        fwinfo,
		Master:           *master,
		Credential:       cred,
		PublishedAddress: publishedAddress,
		WithAuthContext: func(ctx context.Context) context.Context {
			ctx = auth.WithLoginProvider(ctx, *authProvider)
			ctx = sasl.WithBindingAddress(ctx, publishedAddress)
			return ctx
		},
	}

	// Allow listening port to be configurable so we can run this inside of
	// mesos if desired.
	if *bindingPort != 0 {
		config.BindingPort = uint16(*bindingPort)
	}

	driver, err := sched.NewMesosSchedulerDriver(config)

	if err != nil {
		log.Errorln("Unable to create a SchedulerDriver ", err.Error())
	}

	go func() {
		if stat, err := driver.Run(); err != nil {
			log.V(1).Infof("Framework stopped with status %s and error: %s\n", stat.String(), err.Error())
		}
	}()

	printLogs()
	log.V(1).Infof("framework terminating")
}
<commit_msg>Setting up basic exit status.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/gogo/protobuf/proto"
	log "github.com/golang/glog"
	"github.com/mesos/mesos-go/auth"
	"github.com/mesos/mesos-go/auth/sasl"
	"github.com/mesos/mesos-go/auth/sasl/mech"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	sched "github.com/mesos/mesos-go/scheduler"
	mlog "github.com/yp-engineering/mesos-runonce/mesosutil"
	"golang.org/x/net/context"
)

var eventCh = make(chan *mesos.TaskStatus)
var _frameworkId string
var exitStatus = 0

var (
	address      = flag.String("address", "127.0.0.1", "Address for mesos to callback on.")
	bindingPort  = flag.Uint("port", 0, "Port for address to use for mesos to callback.")
	authProvider = flag.String("authentication-provider", sasl.ProviderName,
		fmt.Sprintf("Authentication provider to use, default is SASL that supports mechanisms: %+v", mech.ListSupported()))
	master               = flag.String("master", "127.0.0.1:5050", "Master address <ip:port>")
	taskCount            = flag.Int("task-count", 1, "Total task count to run.")
	mesosTaskID          = flag.String("task-id", "", "Mesos task id to identify the task.")
	mesosTaskName        = flag.String("task-name", "", "Mesos task name to label the task.")
	mesosAuthPrincipal   = flag.String("principal", "", "Mesos authentication principal.")
	mesosAuthSecretFile  = flag.String("secret-file", "", "Mesos authentication secret file.")
	mesosRunasUser       = flag.String("user", "root", "Mesos user to run tasks as.")
	dockerImage          = flag.String("docker-image", "", "Docker image to run.")
	dockerCmd            = flag.String("docker-cmd", "", "Docker command to run.")
	dockerForcePullImage = flag.Bool("force-pull", false, "Boolean for forcing pull of image before run.")
	dockerEnvVars        = flag.String("env-vars", "", "Docker env vars for the container. E.g. -env-vars='{\"env\":{\"FOO\":\"bar\"}}'")
	dCpus                = flag.Float64("cpus", 1.0, "How many CPUs to use.")
	dMem                 = flag.Float64("mem", 10, "How much memory to use.")
)

type ExampleScheduler struct {
	executor      *mesos.ExecutorInfo
	tasksLaunched int
	tasksFinished int
	totalTasks    int
}

type DockerEnvVars struct {
	Env map[string]string `json:"env"`
}

func newExampleScheduler(exec *mesos.ExecutorInfo) *ExampleScheduler {
	return &ExampleScheduler{
		executor:      exec,
		tasksLaunched: 0,
		tasksFinished: 0,
		totalTasks:    *taskCount,
	}
}

func (sched *ExampleScheduler) Registered(driver sched.SchedulerDriver, frameworkId *mesos.FrameworkID, masterInfo *mesos.MasterInfo) {
	log.V(1).Infoln("Framework Registered with Master ", masterInfo)
	_frameworkId = frameworkId.GetValue()
	fmt.Println("Registered with master and given framework ID:", _frameworkId)
}
func (sched *ExampleScheduler) Reregistered(driver sched.SchedulerDriver, masterInfo *mesos.MasterInfo) {
	log.V(1).Infoln("Framework Re-Registered with Master ", masterInfo)
}
func (sched *ExampleScheduler) Disconnected(sched.SchedulerDriver) {
	log.Exitf("disconnected from master, aborting")
}
func (sched *ExampleScheduler) OfferRescinded(_ sched.SchedulerDriver, oid *mesos.OfferID) {
	log.Errorf("offer rescinded: %v", oid)
}
func (sched *ExampleScheduler) FrameworkMessage(_ sched.SchedulerDriver, eid *mesos.ExecutorID, sid *mesos.SlaveID, msg string) {
	log.Errorf("framework message from executor %q slave %q: %q", eid, sid, msg)
}
func (sched *ExampleScheduler) SlaveLost(_ sched.SchedulerDriver, sid *mesos.SlaveID) {
	log.Errorf("slave lost: %v", sid)
}
func (sched *ExampleScheduler) ExecutorLost(_ sched.SchedulerDriver, eid *mesos.ExecutorID, sid *mesos.SlaveID, code int) {
	log.Errorf("executor %q lost on slave %q code %d", eid, sid, code)
}
func (sched *ExampleScheduler) Error(_ sched.SchedulerDriver, err string) {
	log.Exitf("Scheduler received error: %v", err)
}

func (sched *ExampleScheduler) ResourceOffers(driver sched.SchedulerDriver, offers []*mesos.Offer) {

	if sched.tasksLaunched >= sched.totalTasks {
		log.V(1).Info("decline all of the offers since all of our tasks are already launched")
		ids := make([]*mesos.OfferID, len(offers))
		for i, offer := range offers {
			ids[i] = offer.Id
		}
		driver.LaunchTasks(ids, []*mesos.TaskInfo{}, &mesos.Filters{RefuseSeconds: proto.Float64(120)})
		return
	}
	for _, offer := range offers {
		cpuResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "cpus"
		})
		cpus := 0.0
		for _, res := range cpuResources {
			cpus += res.GetScalar().GetValue()
		}

		memResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "mem"
		})
		mems := 0.0
		for _, res := range memResources {
			mems += res.GetScalar().GetValue()
		}

		log.V(1).Infoln("Received Offer <", offer.Id.GetValue(), "> on host ", *offer.Hostname, "with cpus=", cpus, " mem=", mems)

		remainingCpus := cpus
		remainingMems := mems

		var tasks []*mesos.TaskInfo
		for sched.tasksLaunched < sched.totalTasks &&
			*dCpus <= remainingCpus &&
			*dMem <= remainingMems {

			sched.tasksLaunched++

			tID := strconv.Itoa(sched.tasksLaunched)
			if *mesosTaskID != "" {
				tID = *mesosTaskID
			}

			tName := "mesos-runonce-" + tID
			if *mesosTaskName != "" {
				tName = *mesosTaskName
			}

			taskId := &mesos.TaskID{
				Value: proto.String(tID),
			}

			containerType := mesos.ContainerInfo_DOCKER
			task := &mesos.TaskInfo{
				Name:    proto.String(tName),
				TaskId:  taskId,
				SlaveId: offer.SlaveId,
				Resources: []*mesos.Resource{
					util.NewScalarResource("cpus", *dCpus),
					util.NewScalarResource("mem", *dMem),
				},
				Command: &mesos.CommandInfo{
					Shell: proto.Bool(false),
				},
				Container: &mesos.ContainerInfo{
					Type: &containerType,
					Docker: &mesos.ContainerInfo_DockerInfo{
						Image:          proto.String(*dockerImage),
						ForcePullImage: proto.Bool(*dockerForcePullImage),
					},
				},
			}
			log.V(1).Infof("Prepared task: %s with offer %s for launch\n", task.GetName(), offer.Id.GetValue())

			if *dockerEnvVars != "" {
				task.Command.Environment = envVars()
			}

			// Allow arbitrary commands, else just use whatever the image defines in CMD
			if *dockerCmd != "" {
				task.Command.Value = proto.String(*dockerCmd)
				task.Command.Shell = proto.Bool(true)
			}

			tasks = append(tasks, task)
			remainingCpus -= *dCpus
			remainingMems -= *dMem
		}
		log.V(1).Infoln("Launching ", len(tasks), "tasks for offer", offer.Id.GetValue())
		driver.LaunchTasks([]*mesos.OfferID{offer.Id}, tasks, &mesos.Filters{RefuseSeconds: proto.Float64(5)})
	}
}

func (sched *ExampleScheduler) StatusUpdate(driver sched.SchedulerDriver, status *mesos.TaskStatus) {
	log.V(1).Infoln("Status update: task", status.TaskId.GetValue(), " is in state ", status.State.Enum().String())
	eventCh <- status

	if status.GetState() == mesos.TaskState_TASK_FINISHED {
		sched.tasksFinished++
	}

	if sched.tasksFinished >= sched.totalTasks {
		log.V(1).Infoln("Total tasks completed, stopping framework.")
		driver.Stop(false)
	}

	if status.GetState() == mesos.TaskState_TASK_LOST ||
		status.GetState() == mesos.TaskState_TASK_KILLED ||
		status.GetState() == mesos.TaskState_TASK_FAILED ||
		status.GetState() == mesos.TaskState_TASK_ERROR {
		exitStatus = 1
		log.Warningf("mesos TaskStatus: %v", status)
		driver.Abort()
		log.Errorln(
			"Aborting because task", status.TaskId.GetValue(),
			"is in unexpected state", status.State.String(),
			"with message.", status.GetMessage(),
		)
	}
}

// ----------------------- func init() ------------------------- //

func init() {
	flag.Parse()
	log.V(1).Infoln("Initializing the Example Scheduler...")
}

func printLogs() {
	timer := time.Tick(500 * time.Millisecond)
	var (
		readableStatus *mesos.TaskStatus
		finished       bool
		oout, oerr     int
	)
	for {
		select {
		case status := <-eventCh:
			switch status.GetState() {
			case mesos.TaskState_TASK_RUNNING,
				mesos.TaskState_TASK_STARTING:
				readableStatus = status
			case mesos.TaskState_TASK_FAILED,
				mesos.TaskState_TASK_KILLED:
				readableStatus = status
				finished = true
			case mesos.TaskState_TASK_FINISHED:
				finished = true
			}
		case <-timer:
			if readableStatus != nil {
				if finished {
					time.Sleep(3 * time.Second)
				}
				x := printLog(readableStatus, oout, os.Stdout)
				y := printLog(readableStatus, oerr, os.Stderr)
				if finished && x == 0 && y == 0 {
					return
				}
				oout += x
				oerr += y
			}
		}
	}
}

func printLog(status *mesos.TaskStatus, offset int, w io.Writer) int {
	file := "stdout"
	if w == os.Stderr {
		file = "stderr"
	}
	data, err := mlog.FetchLogs(status, offset, file, _frameworkId)
	if err != nil {
		log.V(1).Infof("fetch logs err: %s\n", err)
		return 0
	}
	if len(data) > 0 {
		fmt.Fprint(w, string(data))
	}
	return len(data)
}

func prepareExecutorInfo() *mesos.ExecutorInfo {
	// Create mesos scheduler driver.
	containerType := mesos.ContainerInfo_DOCKER
	return &mesos.ExecutorInfo{
		ExecutorId: util.NewExecutorID("default"),
		Name:       proto.String("mesos-runonce-executor"),
		Source:     proto.String("mesos-runonce-executor"),
		Container: &mesos.ContainerInfo{
			Type: &containerType,
		},
	}
}

func parseIP(address string) net.IP {
	addr, err := net.LookupIP(address)
	if err != nil {
		log.Exit(err)
	}
	if len(addr) < 1 {
		log.Exitf("failed to parse IP from address '%v'", address)
	}
	return addr[0]
}

func envVars() *mesos.Environment {
	var dEnvVars DockerEnvVars
	err := json.Unmarshal([]byte(*dockerEnvVars), &dEnvVars)
	if err != nil {
		log.Exitf("JSON error: %#v with unparsable env vars: %+v", err, *dockerEnvVars)
	}

	var variables []*mesos.Environment_Variable
	for key, value := range dEnvVars.Env {
		variables = append(variables, &mesos.Environment_Variable{Name: proto.String(key), Value: proto.String(value)})
	}

	return &mesos.Environment{Variables: variables}
}

// ----------------------- func main() ------------------------- //

func main() {

	// build command executor
	exec := prepareExecutorInfo()

	// the framework
	fwinfo := &mesos.FrameworkInfo{
		User: proto.String(*mesosRunasUser),
		Name: proto.String("mesos-runonce"),
	}

	cred := (*mesos.Credential)(nil)
	if *mesosAuthPrincipal != "" {
		fwinfo.Principal = proto.String(*mesosAuthPrincipal)
		cred = &mesos.Credential{
			Principal: proto.String(*mesosAuthPrincipal),
		}
		if *mesosAuthSecretFile != "" {
			_, err := os.Stat(*mesosAuthSecretFile)
			if err != nil {
				log.Exit("missing secret file: ", err.Error())
			}
			secret, err := ioutil.ReadFile(*mesosAuthSecretFile)
			if err != nil {
				log.Exit("failed to read secret file: ", err.Error())
			}
			cred.Secret = proto.String(string(secret))
		}
	}

	publishedAddress := parseIP(*address)
	config := sched.DriverConfig{
		Scheduler:        newExampleScheduler(exec),
		Framework:        fwinfo,
		Master:           *master,
		Credential:       cred,
		PublishedAddress: publishedAddress,
		WithAuthContext: func(ctx context.Context) context.Context {
			ctx = auth.WithLoginProvider(ctx, *authProvider)
			ctx = sasl.WithBindingAddress(ctx, publishedAddress)
			return ctx
		},
	}

	// Allow listening port to be configurable so we can run this inside of
	// mesos if desired.
	if *bindingPort != 0 {
		config.BindingPort = uint16(*bindingPort)
	}

	driver, err := sched.NewMesosSchedulerDriver(config)

	if err != nil {
		log.Errorln("Unable to create a SchedulerDriver ", err.Error())
	}

	go func() {
		if stat, err := driver.Run(); err != nil {
			log.V(1).Infof("Framework stopped with status %s and error: %s\n", stat.String(), err.Error())
		}
	}()

	printLogs()
	log.V(1).Infof("framework terminating")
	os.Exit(exitStatus)
}
<|endoftext|>


<commit_before>package main

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

const Version = "2.0.0"

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

var sharedSecret = os.Getenv("GARAGE_SECRET")

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

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

func toggleSwitch(pinNumber int) (err error) {
	err = rpio.Open()
	if err != nil {
		return
	}
	pin := rpio.Pin(pinNumber)
	pin.Output()
	pin.Low()
	time.Sleep(500 * time.Millisecond)
	pin.High()
	return nil
}

type AppRequest struct {
	Timestamp int    `json:"timestamp"`
	Signature []byte `json:"signature"`
}

func Relay(w http.ResponseWriter, r *http.Request) {
	var jsonResp struct {
		Text string `json:"status"`
	}
	jsonResp.Text = "signal received"

	decoder := json.NewDecoder(r.Body)
	var appRequest AppRequest
	err := decoder.Decode(&appRequest)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	verified := verifySignature(appRequest.Timestamp, appRequest.Signature)
	if verified {
		fmt.Println("Signature verified")
		_, err := verifyTime(appRequest.Timestamp)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		fmt.Println("Time verified")
		err = toggleSwitch(options.pinNumber)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			w.WriteHeader(422)
			jsonResp.Text = fmt.Sprintf("%s", err)
		}
	} else {
		w.WriteHeader(401)
		jsonResp.Text = fmt.Sprintf("%s", "Invalid signature")
	}

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

	w.Write(message)
}

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

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

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

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

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

	http.HandleFunc("/", Relay)

	fmt.Fprintln(os.Stderr, "=> Booting Garage Server ", Version)
	fmt.Fprintln(os.Stderr, "=> Run `garage-server -h` for more startup options")
	fmt.Fprintln(os.Stderr, "=> Ctrl-C to shutdown server")
	var err error
	if options.key != "" && options.cert != "" {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on https://%s", serveAddress))
		err = http.ListenAndServeTLS(serveAddress, options.cert, options.key, nil)
	} else {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on http://%s", serveAddress))
		err = http.ListenAndServe(serveAddress, nil)
	}

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

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

const Version = "2.0.0"

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

var sharedSecret = os.Getenv("GARAGE_SECRET")

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

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

func toggleSwitch(pinNumber int) (err error) {
	err = rpio.Open()
	if err != nil {
		return
	}
	pin := rpio.Pin(pinNumber)
	pin.Output()
	pin.Low()
	time.Sleep(500 * time.Millisecond)
	pin.High()
	return nil
}

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

func Relay(w http.ResponseWriter, r *http.Request) {
	var jsonResp struct {
		Text string `json:"status"`
	}
	jsonResp.Text = "signal received"

	decoder := json.NewDecoder(r.Body)
	var clientRequest ClientRequest
	err := decoder.Decode(&clientRequest)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	verified := verifySignature(clientRequest.Timestamp, clientRequest.Signature)
	if verified {
		fmt.Println("Signature verified")
		_, err := verifyTime(clientRequest.Timestamp)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		fmt.Println("Time verified")
		err = toggleSwitch(options.pinNumber)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			w.WriteHeader(422)
			jsonResp.Text = fmt.Sprintf("%s", err)
		}
	} else {
		w.WriteHeader(401)
		jsonResp.Text = fmt.Sprintf("%s", "Invalid signature")
	}

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

	w.Write(message)
}

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

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

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

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

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

	http.HandleFunc("/", Relay)

	fmt.Fprintln(os.Stderr, "=> Booting Garage Server ", Version)
	fmt.Fprintln(os.Stderr, "=> Run `garage-server -h` for more startup options")
	fmt.Fprintln(os.Stderr, "=> Ctrl-C to shutdown server")
	var err error
	if options.key != "" && options.cert != "" {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on https://%s", serveAddress))
		err = http.ListenAndServeTLS(serveAddress, options.cert, options.key, nil)
	} else {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("* Listening on http://%s", serveAddress))
		err = http.ListenAndServe(serveAddress, nil)
	}

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


<commit_before>package main

import (
	"log"
	"net/http"
	"os"

	"github.com/chrisledet/rebasebot/config"
	"github.com/chrisledet/rebasebot/git"
	"github.com/chrisledet/rebasebot/github"
	_http "github.com/chrisledet/rebasebot/http"
)

const (
	Version = "0.1"
)

var (
	botConfig *config.Config
)

func init() {
	var conf *config.Config
	var err error

	switch os.Getenv("DEV") {
	case "true":
		conf, err = config.NewDevConfig()
	default:
		conf, err = config.NewConfig()
	}

	if err != nil {
		log.Fatalf("server.down err: %s\n", err.Error())
	}

	botConfig = conf
}

func main() {
	setup()

	http.HandleFunc("/rebase", _http.Rebase)
	http.HandleFunc("/status", _http.Status)

	log.Printf("server.up: 0.0.0.0:%s version: %s\n", botConfig.Port, Version)

	err := http.ListenAndServe(":"+botConfig.Port, nil)
	if err != nil {
		log.Fatalf("server.down: %s\n", err)
	}
}

func setup() {
	if len(botConfig.TmpDir) > 0 {
		git.SetParentDir(botConfig.TmpDir)
	}

	github.SetSignature(botConfig.Secret)
	github.SetAuth(botConfig.Username, botConfig.Password)
	git.SetAuth(botConfig.Username, botConfig.Password)
}
<commit_msg>Bump version<commit_after>package main

import (
	"log"
	"net/http"
	"os"

	"github.com/chrisledet/rebasebot/config"
	"github.com/chrisledet/rebasebot/git"
	"github.com/chrisledet/rebasebot/github"
	_http "github.com/chrisledet/rebasebot/http"
)

const (
	Version = "0.1.1"
)

var (
	botConfig *config.Config
)

func init() {
	var conf *config.Config
	var err error

	switch os.Getenv("DEV") {
	case "true":
		conf, err = config.NewDevConfig()
	default:
		conf, err = config.NewConfig()
	}

	if err != nil {
		log.Fatalf("server.down err: %s\n", err.Error())
	}

	botConfig = conf
}

func main() {
	setup()

	http.HandleFunc("/rebase", _http.Rebase)
	http.HandleFunc("/status", _http.Status)

	log.Printf("server.up: 0.0.0.0:%s version: %s\n", botConfig.Port, Version)

	err := http.ListenAndServe(":"+botConfig.Port, nil)
	if err != nil {
		log.Fatalf("server.down: %s\n", err)
	}
}

func setup() {
	if len(botConfig.TmpDir) > 0 {
		git.SetParentDir(botConfig.TmpDir)
	}

	github.SetSignature(botConfig.Secret)
	github.SetAuth(botConfig.Username, botConfig.Password)
	git.SetAuth(botConfig.Username, botConfig.Password)
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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

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

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

package main

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

	"github.com/golang/glog"
	"github.com/openshift/origin/pkg/util/proc"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/spf13/pflag"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	"net/http/pprof"

	"k8s.io/kube-state-metrics/collectors"
)

const (
	metricsPath = "/metrics"
	healthzPath = "/healthz"
)

var (
	defaultCollectors = collectorSet{
		"daemonsets":             struct{}{},
		"deployments":            struct{}{},
		"limitranges":            struct{}{},
		"nodes":                  struct{}{},
		"pods":                   struct{}{},
		"replicasets":            struct{}{},
		"replicationcontrollers": struct{}{},
		"resourcequotas":         struct{}{},
		"services":               struct{}{},
		"jobs":                   struct{}{},
		"cronjobs":               struct{}{},
		"statefulsets":           struct{}{},
		"persistentvolumeclaims": struct{}{},
		"namespaces":             struct{}{},
	}
	availableCollectors = map[string]func(registry prometheus.Registerer, kubeClient clientset.Interface, namespace string){
		"cronjobs":               collectors.RegisterCronJobCollector,
		"daemonsets":             collectors.RegisterDaemonSetCollector,
		"deployments":            collectors.RegisterDeploymentCollector,
		"jobs":                   collectors.RegisterJobCollector,
		"limitranges":            collectors.RegisterLimitRangeCollector,
		"nodes":                  collectors.RegisterNodeCollector,
		"pods":                   collectors.RegisterPodCollector,
		"replicasets":            collectors.RegisterReplicaSetCollector,
		"replicationcontrollers": collectors.RegisterReplicationControllerCollector,
		"resourcequotas":         collectors.RegisterResourceQuotaCollector,
		"services":               collectors.RegisterServiceCollector,
		"statefulsets":           collectors.RegisterStatefulSetCollector,
		"persistentvolumeclaims": collectors.RegisterPersistentVolumeClaimCollector,
		"namespaces":             collectors.RegisterNamespaceCollector,
	}
)

type collectorSet map[string]struct{}

func (c *collectorSet) String() string {
	s := *c
	return strings.Join(s.asSlice(), ",")
}

func (c *collectorSet) Set(value string) error {
	s := *c
	cols := strings.Split(value, ",")
	for _, col := range cols {
		_, ok := availableCollectors[col]
		if !ok {
			glog.Fatalf("Collector \"%s\" does not exist", col)
		}
		s[col] = struct{}{}
	}
	return nil
}

func (c collectorSet) asSlice() []string {
	cols := []string{}
	for col, _ := range c {
		cols = append(cols, col)
	}
	return cols
}

func (c collectorSet) isEmpty() bool {
	return len(c.asSlice()) == 0
}

func (c *collectorSet) Type() string {
	return "map[string]struct{}"
}

type options struct {
	inCluster  bool
	apiserver  string
	kubeconfig string
	help       bool
	port       int
	collectors collectorSet
	namespace  string
}

func main() {
	options := &options{collectors: make(collectorSet)}
	flags := pflag.NewFlagSet("", pflag.ExitOnError)
	// add glog flags
	flags.AddGoFlagSet(flag.CommandLine)
	flags.Lookup("logtostderr").Value.Set("true")
	flags.BoolVar(&options.inCluster, "in-cluster", true, `If true, use the built in kubernetes cluster for creating the client`)
	flags.StringVar(&options.apiserver, "apiserver", "", `The URL of the apiserver to use as a master`)
	flags.StringVar(&options.kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig file")
	flags.BoolVarP(&options.help, "help", "h", false, "Print help text")
	flags.IntVar(&options.port, "port", 80, `Port to expose metrics on.`)
	flags.Var(&options.collectors, "collectors", "Collectors to be enabled")
	flags.StringVar(&options.namespace, "namespace", api.NamespaceAll, "namespace to be enabled for collecting resources")

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

	err := flags.Parse(os.Args)
	if err != nil {
		glog.Fatalf("Error: %s", err)
	}

	if options.help {
		flags.Usage()
		os.Exit(0)
	}

	var collectors collectorSet
	if len(options.collectors) == 0 {
		glog.Info("Using default collectors")
		collectors = defaultCollectors
	} else {
		collectors = options.collectors
	}

	if options.namespace == api.NamespaceAll {
		glog.Info("Using all namespace")
	} else {
		glog.Infof("Using %s namespace", options.namespace)
	}

	if isNotExists(options.kubeconfig) && !(options.inCluster) {
		glog.Fatalf("kubeconfig invalid and --in-cluster is false; kubeconfig must be set to a valid file(kubeconfig default file name: $HOME/.kube/config)")
	}
	if options.apiserver != "" {
		glog.Infof("apiserver set to: %v", options.apiserver)
	}

	proc.StartReaper()

	kubeClient, err := createKubeClient(options.inCluster, options.apiserver, options.kubeconfig)
	if err != nil {
		glog.Fatalf("Failed to create client: %v", err)
	}

	registry := prometheus.NewRegistry()
	registerCollectors(registry, kubeClient, collectors, options.namespace)
	metricsServer(registry, options.port)
}

func isNotExists(file string) bool {
	if file == "" {
		file = clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename()
	}
	_, err := os.Stat(file)
	return os.IsNotExist(err)
}

func createKubeClient(inCluster bool, apiserver string, kubeconfig string) (kubeClient clientset.Interface, err error) {
	if inCluster {
		config, err := rest.InClusterConfig()
		if err != nil {
			return nil, err
		}
		// Allow overriding of apiserver even if using inClusterConfig
		// (necessary if kube-proxy isn't properly set up).
		if apiserver != "" {
			config.Host = apiserver
		}
		tokenPresent := false
		if len(config.BearerToken) > 0 {
			tokenPresent = true
		}
		glog.Infof("service account token present: %v", tokenPresent)
		glog.Infof("service host: %s", config.Host)
		if kubeClient, err = clientset.NewForConfig(config); err != nil {
			return nil, err
		}
	} else {
		loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
		// if you want to change the loading rules (which files in which order), you can do so here
		loadingRules.ExplicitPath = kubeconfig
		configOverrides := &clientcmd.ConfigOverrides{}
		// if you want to change override values or bind them to flags, there are methods to help you
		kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
		config, err := kubeConfig.ClientConfig()
		//config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
		//config, err := clientcmd.DefaultClientConfig.ClientConfig()
		if err != nil {
			return nil, err
		}
		kubeClient, err = clientset.NewForConfig(config)
		if err != nil {
			return nil, err
		}
	}

	// Informers don't seem to do a good job logging error messages when it
	// can't reach the server, making debugging hard. This makes it easier to
	// figure out if apiserver is configured incorrectly.
	glog.Infof("Testing communication with server")
	_, err = kubeClient.Discovery().ServerVersion()
	if err != nil {
		return nil, fmt.Errorf("ERROR communicating with apiserver: %v", err)
	}
	glog.Infof("Communication with server successful")

	return kubeClient, nil
}

func metricsServer(registry prometheus.Gatherer, port int) {
	// Address to listen on for web interface and telemetry
	listenAddress := fmt.Sprintf(":%d", port)

	glog.Infof("Starting metrics server: %s", listenAddress)

	mux := http.NewServeMux()

	mux.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
	mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
	mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
	mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
	mux.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))

	// Add metricsPath
	mux.Handle(metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
	// Add healthzPath
	mux.HandleFunc(healthzPath, func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("ok"))
	})
	// Add index
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
             <title>Kube Metrics Server</title>

Kube Metrics

<a href='` + metricsPath + `'>metrics

<a href='` + healthzPath + `'>healthz

             `))
	})
	log.Fatal(http.ListenAndServe(listenAddress, mux))
}

// registerCollectors creates and starts informers and initializes and
// registers metrics for collection.
func registerCollectors(registry prometheus.Registerer, kubeClient clientset.Interface, enabledCollectors collectorSet, namespace string) {
	activeCollectors := []string{}
	for c, _ := range enabledCollectors {
		f, ok := availableCollectors[c]
		if ok {
			f(registry, kubeClient, namespace)
			activeCollectors = append(activeCollectors, c)
		}
	}

	glog.Infof("Active collectors: %s", strings.Join(activeCollectors, ","))
}
<commit_msg>display default logtostderr in help output<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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

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

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

package main

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

	"github.com/golang/glog"
	"github.com/openshift/origin/pkg/util/proc"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/spf13/pflag"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	"net/http/pprof"

	"k8s.io/kube-state-metrics/collectors"
)

const (
	metricsPath = "/metrics"
	healthzPath = "/healthz"
)

var (
	defaultCollectors = collectorSet{
		"daemonsets":             struct{}{},
		"deployments":            struct{}{},
		"limitranges":            struct{}{},
		"nodes":                  struct{}{},
		"pods":                   struct{}{},
		"replicasets":            struct{}{},
		"replicationcontrollers": struct{}{},
		"resourcequotas":         struct{}{},
		"services":               struct{}{},
		"jobs":                   struct{}{},
		"cronjobs":               struct{}{},
		"statefulsets":           struct{}{},
		"persistentvolumeclaims": struct{}{},
		"namespaces":             struct{}{},
	}
	availableCollectors = map[string]func(registry prometheus.Registerer, kubeClient clientset.Interface, namespace string){
		"cronjobs":               collectors.RegisterCronJobCollector,
		"daemonsets":             collectors.RegisterDaemonSetCollector,
		"deployments":            collectors.RegisterDeploymentCollector,
		"jobs":                   collectors.RegisterJobCollector,
		"limitranges":            collectors.RegisterLimitRangeCollector,
		"nodes":                  collectors.RegisterNodeCollector,
		"pods":                   collectors.RegisterPodCollector,
		"replicasets":            collectors.RegisterReplicaSetCollector,
		"replicationcontrollers": collectors.RegisterReplicationControllerCollector,
		"resourcequotas":         collectors.RegisterResourceQuotaCollector,
		"services":               collectors.RegisterServiceCollector,
		"statefulsets":           collectors.RegisterStatefulSetCollector,
		"persistentvolumeclaims": collectors.RegisterPersistentVolumeClaimCollector,
		"namespaces":             collectors.RegisterNamespaceCollector,
	}
)

type collectorSet map[string]struct{}

func (c *collectorSet) String() string {
	s := *c
	return strings.Join(s.asSlice(), ",")
}

func (c *collectorSet) Set(value string) error {
	s := *c
	cols := strings.Split(value, ",")
	for _, col := range cols {
		_, ok := availableCollectors[col]
		if !ok {
			glog.Fatalf("Collector \"%s\" does not exist", col)
		}
		s[col] = struct{}{}
	}
	return nil
}

func (c collectorSet) asSlice() []string {
	cols := []string{}
	for col, _ := range c {
		cols = append(cols, col)
	}
	return cols
}

func (c collectorSet) isEmpty() bool {
	return len(c.asSlice()) == 0
}

func (c *collectorSet) Type() string {
	return "map[string]struct{}"
}

type options struct {
	inCluster  bool
	apiserver  string
	kubeconfig string
	help       bool
	port       int
	collectors collectorSet
	namespace  string
}

func main() {
	options := &options{collectors: make(collectorSet)}
	flags := pflag.NewFlagSet("", pflag.ExitOnError)
	// add glog flags
	flags.AddGoFlagSet(flag.CommandLine)
	flags.Lookup("logtostderr").Value.Set("true")
	flags.Lookup("logtostderr").DefValue = "true"
	flags.Lookup("logtostderr").NoOptDefVal = "true"
	flags.BoolVar(&options.inCluster, "in-cluster", true, `If true, use the built in kubernetes cluster for creating the client`)
	flags.StringVar(&options.apiserver, "apiserver", "", `The URL of the apiserver to use as a master`)
	flags.StringVar(&options.kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig file")
	flags.BoolVarP(&options.help, "help", "h", false, "Print help text")
	flags.IntVar(&options.port, "port", 80, `Port to expose metrics on.`)
	flags.Var(&options.collectors, "collectors", "Collectors to be enabled")
	flags.StringVar(&options.namespace, "namespace", api.NamespaceAll, "namespace to be enabled for collecting resources")

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

	err := flags.Parse(os.Args)
	if err != nil {
		glog.Fatalf("Error: %s", err)
	}

	if options.help {
		flags.Usage()
		os.Exit(0)
	}

	var collectors collectorSet
	if len(options.collectors) == 0 {
		glog.Info("Using default collectors")
		collectors = defaultCollectors
	} else {
		collectors = options.collectors
	}

	if options.namespace == api.NamespaceAll {
		glog.Info("Using all namespace")
	} else {
		glog.Infof("Using %s namespace", options.namespace)
	}

	if isNotExists(options.kubeconfig) && !(options.inCluster) {
		glog.Fatalf("kubeconfig invalid and --in-cluster is false; kubeconfig must be set to a valid file(kubeconfig default file name: $HOME/.kube/config)")
	}
	if options.apiserver != "" {
		glog.Infof("apiserver set to: %v", options.apiserver)
	}

	proc.StartReaper()

	kubeClient, err := createKubeClient(options.inCluster, options.apiserver, options.kubeconfig)
	if err != nil {
		glog.Fatalf("Failed to create client: %v", err)
	}

	registry := prometheus.NewRegistry()
	registerCollectors(registry, kubeClient, collectors, options.namespace)
	metricsServer(registry, options.port)
}

func isNotExists(file string) bool {
	if file == "" {
		file = clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename()
	}
	_, err := os.Stat(file)
	return os.IsNotExist(err)
}

func createKubeClient(inCluster bool, apiserver string, kubeconfig string) (kubeClient clientset.Interface, err error) {
	if inCluster {
		config, err := rest.InClusterConfig()
		if err != nil {
			return nil, err
		}
		// Allow overriding of apiserver even if using inClusterConfig
		// (necessary if kube-proxy isn't properly set up).
		if apiserver != "" {
			config.Host = apiserver
		}
		tokenPresent := false
		if len(config.BearerToken) > 0 {
			tokenPresent = true
		}
		glog.Infof("service account token present: %v", tokenPresent)
		glog.Infof("service host: %s", config.Host)
		if kubeClient, err = clientset.NewForConfig(config); err != nil {
			return nil, err
		}
	} else {
		loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
		// if you want to change the loading rules (which files in which order), you can do so here
		loadingRules.ExplicitPath = kubeconfig
		configOverrides := &clientcmd.ConfigOverrides{}
		// if you want to change override values or bind them to flags, there are methods to help you
		kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
		config, err := kubeConfig.ClientConfig()
		//config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
		//config, err := clientcmd.DefaultClientConfig.ClientConfig()
		if err != nil {
			return nil, err
		}
		kubeClient, err = clientset.NewForConfig(config)
		if err != nil {
			return nil, err
		}
	}

	// Informers don't seem to do a good job logging error messages when it
	// can't reach the server, making debugging hard. This makes it easier to
	// figure out if apiserver is configured incorrectly.
	glog.Infof("Testing communication with server")
	_, err = kubeClient.Discovery().ServerVersion()
	if err != nil {
		return nil, fmt.Errorf("ERROR communicating with apiserver: %v", err)
	}
	glog.Infof("Communication with server successful")

	return kubeClient, nil
}

func metricsServer(registry prometheus.Gatherer, port int) {
	// Address to listen on for web interface and telemetry
	listenAddress := fmt.Sprintf(":%d", port)

	glog.Infof("Starting metrics server: %s", listenAddress)

	mux := http.NewServeMux()

	mux.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
	mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
	mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
	mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
	mux.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))

	// Add metricsPath
	mux.Handle(metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
	// Add healthzPath
	mux.HandleFunc(healthzPath, func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("ok"))
	})
	// Add index
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
             <title>Kube Metrics Server</title>

Kube Metrics

<a href='` + metricsPath + `'>metrics

<a href='` + healthzPath + `'>healthz

             `))
	})
	log.Fatal(http.ListenAndServe(listenAddress, mux))
}

// registerCollectors creates and starts informers and initializes and
// registers metrics for collection.
func registerCollectors(registry prometheus.Registerer, kubeClient clientset.Interface, enabledCollectors collectorSet, namespace string) {
	activeCollectors := []string{}
	for c, _ := range enabledCollectors {
		f, ok := availableCollectors[c]
		if ok {
			f(registry, kubeClient, namespace)
			activeCollectors = append(activeCollectors, c)
		}
	}

	glog.Infof("Active collectors: %s", strings.Join(activeCollectors, ","))
}
<|endoftext|>


<commit_before>package main

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

	"io"

	"github.com/alistanis/silentinstall/silent"
	"github.com/alistanis/silentinstall/silent/ui"
)

// setup const messages
const (
	configVarMsg = "The path of the config file"
	verboseMsg   = "Prints verbose output if true"
)

var (
	configFile = flag.String("f", "", configVarMsg)
	coloredUi  = ui.NewColoredUi()
)

const (
	_ = iota // skip 0
	// starting at -1, decrement for each additional value
	exitNoFileProvided = -iota
	exitBadFile
	exitBadConfig
	exitCmdError
)

// set our flagvars
func init() {
	flag.StringVar(configFile, "file", "", configVarMsg)
	flag.BoolVar(&silent.Verbose, "v", false, verboseMsg)
	log.SetFlags(log.Lshortfile | log.LstdFlags)
}

// parse those flags
func parseFlags() {
	flag.Parse()
	if *configFile == "" {
		coloredUi.Err("Must provide -f or --file for the path of the config file to use.")
		os.Exit(exitNoFileProvided)
	}
}

func main() {
	parseFlags()
	// read config data
	data, err := ioutil.ReadFile(*configFile)
	if err != nil {
		coloredUi.Err(err)
		os.Exit(exitBadFile)
	}

	// convert json to list of commands
	cmds, err := silent.NewSilentCmdsFromJSON(data)
	if err != nil {
		coloredUi.Err(err)
		os.Exit(exitBadConfig)
	}
	// execute them!
	err = cmds.Exec()
	if err == io.EOF {
		coloredUi.Say("SilentInstall has finished successfully!")
	} else {
		coloredUi.Err(err)
		os.Exit(exitCmdError)
	}
}
<commit_msg>add log verbosity to verbose flag conditions<commit_after>package main

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

	"io"

	"github.com/alistanis/silentinstall/silent"
	"github.com/alistanis/silentinstall/silent/ui"
)

// setup const messages
const (
	configVarMsg = "The path of the config file"
	verboseMsg   = "Prints verbose output if true"
)

var (
	configFile = flag.String("f", "", configVarMsg)
	coloredUi  = ui.NewColoredUi()
)

const (
	_ = iota // skip 0
	// starting at -1, decrement for each additional value
	exitNoFileProvided = -iota
	exitBadFile
	exitBadConfig
	exitCmdError
)

// set our flagvars
func init() {
	flag.StringVar(configFile, "file", "", configVarMsg)
	flag.BoolVar(&silent.Verbose, "v", false, verboseMsg)
}

// parse those flags
func parseFlags() {
	flag.Parse()
	if silent.Verbose {
		log.SetFlags(log.Lshortfile | log.LstdFlags)
	}
	if *configFile == "" {
		coloredUi.Err("Must provide -f or --file for the path of the config file to use.")
		os.Exit(exitNoFileProvided)
	}
}

func main() {
	parseFlags()
	// read config data
	data, err := ioutil.ReadFile(*configFile)
	if err != nil {
		coloredUi.Err(err)
		os.Exit(exitBadFile)
	}

	// convert json to list of commands
	cmds, err := silent.NewSilentCmdsFromJSON(data)
	if err != nil {
		coloredUi.Err(err)
		os.Exit(exitBadConfig)
	}
	// execute them!
	err = cmds.Exec()
	if err == io.EOF {
		coloredUi.Say("SilentInstall has finished successfully!")
	} else {
		coloredUi.Err(err)
		os.Exit(exitCmdError)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"net/rpc/jsonrpc"
	"os"
	"os/signal"

	"github.com/MJKWoolnough/httpdir"
	"golang.org/x/net/websocket"
)

var dir http.FileSystem = httpdir.Default

func main() {
	configFile := flag.String("c", "config.json", "config file")
	flag.Parse()
	c, err := LoadConfig(*configFile)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	rpc.RegisterName("RPC", RPC{c})

	t := Transfer{c}
	http.Handle("/transfer", websocket.Handler(t.Websocket))
	http.Handle("/rpc", websocket.Handler(func(conn *websocket.Conn) { jsonrpc.ServeConn(conn) }))
	http.Handle("/", http.FileServer(dir))
	l, err := net.Listen("tcp", c.ServerSettings.ListenAddr)
	if err != nil {
		log.Println(err)
		return
	}

	cc := make(chan struct{})
	go func() {
		log.Println("Server Started")
		sc := make(chan os.Signal, 1)
		signal.Notify(sc, os.Interrupt)
		select {
		case <-sc:
			log.Println("Closing")
		case <-cc:
		}
		signal.Stop(sc)
		close(sc)
		l.Close()
		close(cc)
	}()

	err = http.Serve(l, nil)
	select {
	case <-cc:
	default:
		log.Println(err)
		close(cc)
	}
	<-cc
	// Close all running minecraft servers before closing
}
<commit_msg>Corrected shutdown ordering<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"net/rpc/jsonrpc"
	"os"
	"os/signal"

	"github.com/MJKWoolnough/httpdir"
	"golang.org/x/net/websocket"
)

var dir http.FileSystem = httpdir.Default

func main() {
	configFile := flag.String("c", "config.json", "config file")
	flag.Parse()
	c, err := LoadConfig(*configFile)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	rpc.RegisterName("RPC", RPC{c})

	t := Transfer{c}
	http.Handle("/transfer", websocket.Handler(t.Websocket))
	http.Handle("/rpc", websocket.Handler(func(conn *websocket.Conn) { jsonrpc.ServeConn(conn) }))
	http.Handle("/", http.FileServer(dir))
	l, err := net.Listen("tcp", c.ServerSettings.ListenAddr)
	if err != nil {
		log.Println(err)
		return
	}

	cc := make(chan struct{})
	go func() {
		log.Println("Server Started")
		sc := make(chan os.Signal, 1)
		signal.Notify(sc, os.Interrupt)
		select {
		case <-sc:
			log.Println("Closing")
		case <-cc:
		}
		signal.Stop(sc)
		close(sc)
		close(cc)
		l.Close()
	}()

	err = http.Serve(l, nil)
	select {
	case <-cc:
	default:
		log.Println(err)
		close(cc)
	}
	<-cc
	// Close all running minecraft servers before closing
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"

	"github.com/KevinGong2013/ggbot/service"
	"github.com/KevinGong2013/ggbot/uuidprocessor"
	"github.com/KevinGong2013/wechat"
	"github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var logger = logrus.WithFields(logrus.Fields{
	"module": "ggbot",
})

// Config ..
type Config struct {
	ShowQRCodeOnTerminal bool
	Features             struct {
		Assistant struct {
			Enable    bool
			OwnerGGID string
		}
		Guard struct {
			Enable bool
		}
		Tuling struct {
			Enable bool
			Key    string
		}
		Xiaoice struct {
			Enable bool
		}
		WebhookService struct {
			Enable            bool
			MsgWebhook        string
			LoginStateWebhook string
			UUIDWebhook       string
		}
	}
}

var config = Config{}

func main() {

	tf := logrus.TextFormatter{}
	tf.FullTimestamp = true
	tf.TimestampFormat = `2006-01-02 15:04:05`
	logrus.SetFormatter(&tf)
	logrus.SetLevel(logrus.DebugLevel)

	path := `conf.yaml`
	_, err := os.Stat(path)
	if !(err == nil || os.IsExist(err)) {
		config.ShowQRCodeOnTerminal = false
		config.Features.Tuling.Key = ``
		config.Features.Tuling.Enable = false
		data, _ := yaml.Marshal(config)
		createFile(path, data)
	}
	data, _ := ioutil.ReadFile(path)
	err = yaml.Unmarshal(data, &config)
	if err != nil {
		logger.Error(`配置文件不正确`)
	}

	options := wechat.DefaultConfigure()

	if config.ShowQRCodeOnTerminal {
		options.Processor = uuidprocessor.New()
	}

	var webhookService *service.Wrapper
	if config.Features.WebhookService.Enable {
		webhookService = service.NewWrapper(config.Features.WebhookService.UUIDWebhook)
	}

	if webhookService != nil && len(config.Features.WebhookService.UUIDWebhook) > 0 {
		options.Processor = webhookService
	}

	bot, err := wechat.AwakenNewBot(options)
	if err != nil {
		panic(err)
	}

	t := newTuling(config.Features.Tuling.Key, bot)
	x := newXiaoice(bot)
	a := newAssisant(bot, config.Features.Assistant.OwnerGGID)
	g := newGuard(bot)

	bot.Handle(`/msg`, func(evt wechat.Event) {
		logger.Debug(`begin handle [/msg]`)
		data := evt.Data.(wechat.EventMsgData)
		if config.Features.Tuling.Enable {
			go t.autoReplay(data)
		}
		if config.Features.Xiaoice.Enable {
			go x.autoReplay(data)
		}
		if config.Features.Guard.Enable {
			go g.autoAcceptAddFirendRequest(data)
		}
		if config.Features.Assistant.Enable {
			go a.handle(data)
		}
		if webhookService != nil && len(config.Features.WebhookService.MsgWebhook) > 0 {
			go webhookService.Forward(config.Features.WebhookService.MsgWebhook, data)
		}
	})

	bot.Handle(`/login`, func(arg2 wechat.Event) {
		isSuccess := arg2.Data.(int) == 1
		if isSuccess && x != nil {
			if cs, err := bot.ContactsByNickName(`小冰`); err == nil {
				for _, c := range cs {
					if c.Type == wechat.Offical {
						x.un = c.UserName // 更新小冰的UserName
						break
					}
				}
			}
		}
		if webhookService != nil && len(config.Features.WebhookService.LoginStateWebhook) > 0 {
			go webhookService.Forward(config.Features.WebhookService.LoginStateWebhook, arg2.Data)
		}
	})

	bot.Go()
}

func createFile(name string, data []byte) (err error) {

	defer func() {
		if err != nil {
			logger.Error(err)
		}
	}()

	oflag := os.O_CREATE | os.O_WRONLY | os.O_TRUNC

	file, err := os.OpenFile(name, oflag, 0666)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.Write(data)

	return
}
<commit_msg>Added fuzzy diff support.<commit_after>package main

import (
	"io/ioutil"
	"os"

	"github.com/KevinGong2013/ggbot/service"
	"github.com/KevinGong2013/ggbot/uuidprocessor"
	"github.com/KevinGong2013/wechat"
	"github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var logger = logrus.WithFields(logrus.Fields{
	"module": "ggbot",
})

// Config ..
type Config struct {
	ShowQRCodeOnTerminal bool
	FuzzyDiff            bool
	Features             struct {
		Assistant struct {
			Enable    bool
			OwnerGGID string
		}
		Guard struct {
			Enable bool
		}
		Tuling struct {
			Enable bool
			Key    string
		}
		Xiaoice struct {
			Enable bool
		}
		WebhookService struct {
			Enable            bool
			MsgWebhook        string
			LoginStateWebhook string
			UUIDWebhook       string
		}
	}
}

var config = Config{}

func main() {

	tf := logrus.TextFormatter{}
	tf.FullTimestamp = true
	tf.TimestampFormat = `2006-01-02 15:04:05`
	logrus.SetFormatter(&tf)
	logrus.SetLevel(logrus.DebugLevel)

	path := `conf.yaml`
	_, err := os.Stat(path)
	if !(err == nil || os.IsExist(err)) {
		config.ShowQRCodeOnTerminal = false
		config.Features.Tuling.Key = ``
		config.Features.Tuling.Enable = false
		config.FuzzyDiff = true
		data, _ := yaml.Marshal(config)
		createFile(path, data)
	}
	data, _ := ioutil.ReadFile(path)
	err = yaml.Unmarshal(data, &config)
	if err != nil {
		logger.Error(`配置文件不正确`)
	}

	options := wechat.DefaultConfigure()

	// 是否开启联系人模糊匹配
	options.FuzzyDiff = config.FuzzyDiff

	if config.ShowQRCodeOnTerminal {
		options.Processor = uuidprocessor.New()
	}

	var webhookService *service.Wrapper
	if config.Features.WebhookService.Enable {
		webhookService = service.NewWrapper(config.Features.WebhookService.UUIDWebhook)
	}

	if webhookService != nil && len(config.Features.WebhookService.UUIDWebhook) > 0 {
		options.Processor = webhookService
	}

	bot, err := wechat.AwakenNewBot(options)
	if err != nil {
		panic(err)
	}

	t := newTuling(config.Features.Tuling.Key, bot)
	x := newXiaoice(bot)
	a := newAssisant(bot, config.Features.Assistant.OwnerGGID)
	g := newGuard(bot)

	bot.Handle(`/msg`, func(evt wechat.Event) {
		logger.Debug(`begin handle [/msg]`)
		data := evt.Data.(wechat.EventMsgData)
		if config.Features.Tuling.Enable {
			go t.autoReplay(data)
		}
		if config.Features.Xiaoice.Enable {
			go x.autoReplay(data)
		}
		if config.Features.Guard.Enable {
			go g.autoAcceptAddFirendRequest(data)
		}
		if config.Features.Assistant.Enable {
			go a.handle(data)
		}
		if webhookService != nil && len(config.Features.WebhookService.MsgWebhook) > 0 {
			go webhookService.Forward(config.Features.WebhookService.MsgWebhook, data)
		}
	})

	bot.Handle(`/login`, func(arg2 wechat.Event) {
		isSuccess := arg2.Data.(int) == 1
		if isSuccess && x != nil {
			if cs, err := bot.ContactsByNickName(`小冰`); err == nil {
				for _, c := range cs {
					if c.Type == wechat.Offical {
						x.un = c.UserName // 更新小冰的UserName
						break
					}
				}
			}
		}
		if webhookService != nil && len(config.Features.WebhookService.LoginStateWebhook) > 0 {
			go webhookService.Forward(config.Features.WebhookService.LoginStateWebhook, arg2.Data)
		}
	})

	bot.Go()
}

func createFile(name string, data []byte) (err error) {

	defer func() {
		if err != nil {
			logger.Error(err)
		}
	}()

	oflag := os.O_CREATE | os.O_WRONLY | os.O_TRUNC

	file, err := os.OpenFile(name, oflag, 0666)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.Write(data)

	return
}
<|endoftext|>


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

// Package main
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/yaacov/mohawk/backends"
	"github.com/yaacov/mohawk/router"
)

// VER the server version
const VER = "0.6.0"

func main() {
	var db backend.Backend

	// Get user options
	// 	port    - default to 8443
	// 	backend - default to random
	portPtr := flag.Int("port", 8443, "server port")
	backendPtr := flag.String("backend", "random", "the backend to use [random, sqlite]")
	apiPtr := flag.String("api", "0.21.0", "the hawkulr api to mimic [e.g. 0.8.9.Testing, 0.21.2.Final]")
	apiTLS := flag.String("tls", "true", "use TLS server")
	flag.Parse()

	// Create and init the backend
	if *backendPtr == "sqlite" {
		db = &backend.Sqlite{}
	} else {
		db = &backend.Random{}
	}
	db.Open()

	// h common variables to be used by all Handler functions
	// backend the backend to use for metrics source
	// version the Hawkular server version we mimic
	h := Handler{
		backend: db,
		version: *apiPtr,
	}

	// Create the routers
	// Requests not handled by the routers will be forworded to BadRequest Handler
	rRoot := router.Router{
		Prefix: "/",
	}
	// Root Routing table
	rRoot.Add("GET", "oapi", h.GetAPIVersions)

	rAlerts := router.Router{
		Prefix: "/hawkular/alerts/",
	}
	// Alerts Routing table
	rAlerts.Add("GET", "status", h.GetStatus)

	rMetrics := router.Router{
		Prefix: "/hawkular/metrics/",
	}
	// Metrics Routing table
	rMetrics.Add("GET", "status", h.GetStatus)
	rMetrics.Add("GET", "metrics", h.GetMetrics)

	// api version >= 0.16.0
	rMetrics.Add("GET", "gauges/:id/raw", h.GetData)
	rMetrics.Add("GET", "counters/:id/raw", h.GetData)
	rMetrics.Add("GET", "availability/:id/raw", h.GetData)

	rMetrics.Add("GET", "gauges/:id/stats", h.GetData)
	rMetrics.Add("GET", "counters/:id/stats", h.GetData)
	rMetrics.Add("GET", "availability/:id/stats", h.GetData)

	rMetrics.Add("POST", "gauges/raw", h.PostData)
	rMetrics.Add("POST", "gauges/raw/query", h.PostQuery)
	rMetrics.Add("POST", "counters/raw", h.PostData)
	rMetrics.Add("POST", "counters/raw/query", h.PostQuery)

	rMetrics.Add("PUT", "gauges/:id/tags", h.PutTags)
	rMetrics.Add("PUT", "counters/:id/tags", h.PutTags)

	// api version < 0.16.0
	rMetrics.Add("GET", "gauges/:id/data", h.GetData)
	rMetrics.Add("GET", "counters/:id/data", h.GetData)
	rMetrics.Add("GET", "availability/:id/data", h.GetData)

	rMetrics.Add("POST", "gauges/data", h.PostData)
	rMetrics.Add("POST", "counters/data", h.PostData)

	// logger a logging middleware
	logger := Logger{}

	// concat middlewars and routes (first logger until rRoot) with a fallback to BadRequest
	router.ConcatMiddleWares([]router.MiddleWare{&logger, &rMetrics, &rAlerts, &rRoot}, BadRequest{})

	// Run the server
	srv := &http.Server{
		Addr:           fmt.Sprintf("0.0.0.0:%d", *portPtr),
		Handler:        logger,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	if *apiTLS == "true" {
		log.Printf("Start server, listen on https://%+v", srv.Addr)
		log.Fatal(srv.ListenAndServeTLS("server.pem", "server.key"))
	} else {
		log.Printf("Start server, listen on http://%+v", srv.Addr)
		log.Fatal(srv.ListenAndServe())
	}
}
<commit_msg>Add optional error backend<commit_after>// Copyright 2016 Red Hat, Inc. and/or its affiliates
// and other contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/yaacov/mohawk/backends"
	"github.com/yaacov/mohawk/router"
)

// VER the server version
const VER = "0.6.0"

func main() {
	var db backend.Backend

	// Get user options
	// 	port    - default to 8443
	// 	backend - default to random
	portPtr := flag.Int("port", 8443, "server port")
	backendPtr := flag.String("backend", "random", "the backend to use [random, sqlite]")
	apiPtr := flag.String("api", "0.21.0", "the hawkulr api to mimic [e.g. 0.8.9.Testing, 0.21.2.Final]")
	apiTLS := flag.String("tls", "true", "use TLS server")
	flag.Parse()

	// Create and init the backend
	if *backendPtr == "sqlite" {
		db = &backend.Sqlite{}
	} else {
		db = &backend.Random{}
	}
	db.Open()

	// h common variables to be used by all Handler functions
	// backend the backend to use for metrics source
	// version the Hawkular server version we mimic
	h := Handler{
		backend: db,
		version: *apiPtr,
	}

	// Create the routers
	// Requests not handled by the routers will be forworded to BadRequest Handler
	rRoot := router.Router{
		Prefix: "/",
	}
	// Root Routing table
	rRoot.Add("GET", "oapi", h.GetAPIVersions)
	rRoot.Add("GET", "hawkular/metrics/status", h.GetStatus)

	rMetrics := router.Router{
		Prefix: "/hawkular/metrics/",
	}
	// Metrics Routing table
	rMetrics.Add("GET", "metrics", h.GetMetrics)

	// api version >= 0.16.0
	rMetrics.Add("GET", "gauges/:id/raw", h.GetData)
	rMetrics.Add("GET", "counters/:id/raw", h.GetData)
	rMetrics.Add("GET", "availability/:id/raw", h.GetData)

	rMetrics.Add("GET", "gauges/:id/stats", h.GetData)
	rMetrics.Add("GET", "counters/:id/stats", h.GetData)
	rMetrics.Add("GET", "availability/:id/stats", h.GetData)

	rMetrics.Add("POST", "gauges/raw", h.PostData)
	rMetrics.Add("POST", "gauges/raw/query", h.PostQuery)
	rMetrics.Add("POST", "counters/raw", h.PostData)
	rMetrics.Add("POST", "counters/raw/query", h.PostQuery)

	rMetrics.Add("PUT", "gauges/:id/tags", h.PutTags)
	rMetrics.Add("PUT", "counters/:id/tags", h.PutTags)

	// api version < 0.16.0
	rMetrics.Add("GET", "gauges/:id/data", h.GetData)
	rMetrics.Add("GET", "counters/:id/data", h.GetData)
	rMetrics.Add("GET", "availability/:id/data", h.GetData)

	rMetrics.Add("POST", "gauges/data", h.PostData)
	rMetrics.Add("POST", "counters/data", h.PostData)

	// logger a logging middleware
	logger := Logger{}

	// concat middlewars and routes (first logger until rRoot) with a fallback to BadRequest
	if (*backendPtr == "error") {
		router.ConcatMiddleWares([]router.MiddleWare{&logger, &rRoot}, BadRequest{})
	} else {
		router.ConcatMiddleWares([]router.MiddleWare{&logger, &rMetrics, &rRoot}, BadRequest{})
	}

	// Run the server
	srv := &http.Server{
		Addr:           fmt.Sprintf("0.0.0.0:%d", *portPtr),
		Handler:        logger,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	if *apiTLS == "true" {
		log.Printf("Start server, listen on https://%+v", srv.Addr)
		log.Fatal(srv.ListenAndServeTLS("server.pem", "server.key"))
	} else {
		log.Printf("Start server, listen on http://%+v", srv.Addr)
		log.Fatal(srv.ListenAndServe())
	}
}
<|endoftext|>


<commit_before>package main

import "io"
import "fmt"
import "net/http"
import "os"
import "os/exec"
import "flag"
import "strings"
import "strconv"

import "github.com/gorilla/websocket"
import "github.com/kr/pty"
import "github.com/creack/goterm/win"

func start() (*exec.Cmd, *os.File) {
	var err error

	cmdString := "/bin/bash"
	cmd := exec.Command(cmdString)
	f, err := pty.Start(cmd)
	if err != nil {
		fmt.Println("Failed to start command: %s", err)
	}

	return cmd, f
}

func stop(pty *os.File, cmd *exec.Cmd) {
	pty.Close()
	cmd.Wait()
}

func ptyHandler(w http.ResponseWriter, r *http.Request, sizeFlag string) {
	var upgrader = websocket.Upgrader{
		ReadBufferSize:  1,
		WriteBufferSize: 1,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		fmt.Println("Websocket upgrade failed: %s", err)
	}
	defer conn.Close()

	cmd, file := start()

	size := strings.Split(sizeFlag, "x")
	cols, _ := strconv.Atoi(size[0])
	lines, _ := strconv.Atoi(size[1])
	if err := win.SetWinsize(file.Fd(), &win.Winsize{Height: uint16(lines), Width: uint16(cols)}); err != nil {
        panic(err)
    }

	// Copy everything from the pty master to the websocket.
	go func() {
		buf := make([]byte, 512)
		// TODO: more graceful exit on socket close / process exit
		for {
			n, err := file.Read(buf)
			if err != nil {
				fmt.Println("Failed to read from pty master: %s", err)
				return
			}

			err = conn.WriteMessage(websocket.BinaryMessage, buf[0:n])

			if err != nil {
				fmt.Println("Failed to send %d bytes on websocket: %s", n, err)
				return
			}
		}
	}()

	// Read from the websocket, copying to the pty master.
	for {
		mt, payload, err := conn.ReadMessage()
		if err != nil {
			if err != io.EOF {
				fmt.Println("conn.ReadMessage failed: %s", err)
				return
			}
		}

		switch mt {
		case websocket.BinaryMessage:
			file.Write(payload)
		default:
			fmt.Println("Invalid message type %d", mt)
			return
		}
	}

	stop(file, cmd)
}

func main() {
	addrFlag := flag.String("addr", ":12061", "IP:PORT or :PORT address to listen on")
	sizeFlag := flag.String("size", "80x24", "initial size for the tty")

	flag.Parse()

	http.HandleFunc("/pty", func(w http.ResponseWriter, r *http.Request) {
              ptyHandler(w, r, *sizeFlag)
       })

	err := http.ListenAndServe(*addrFlag, nil)
	if err != nil {
		fmt.Println("net.http could not listen on address '%s': %s", addrFlag, err)
	}
}<commit_msg>Refactored input output handling<commit_after>package main

import "io"
import "fmt"
import "net/http"
import "os"
import "os/exec"
import "flag"
import "strings"
import "strconv"

import "github.com/gorilla/websocket"
import "github.com/kr/pty"
import "github.com/creack/goterm/win"

func start() (*exec.Cmd, *os.File) {
	var err error

	cmdString := "/bin/bash"
	cmd := exec.Command(cmdString)
	f, err := pty.Start(cmd)
	if err != nil {
		fmt.Println("Failed to start command: %s", err)
	}

	return cmd, f
}

func stop(pty *os.File, cmd *exec.Cmd) {
	pty.Close()
	cmd.Wait()
}

// Read from the websocket, copying to the pty master.
func handleInput(file *os.File, conn *websocket.Conn) {
	for {
		mt, payload, err := conn.ReadMessage()
		if err != nil {
			if err != io.EOF {
				fmt.Println("conn.ReadMessage failed: ", err)
				return
			}
		}

		switch mt {
		case websocket.BinaryMessage:
			file.Write(payload)
		default:
			fmt.Println("Invalid message type %d", mt)
			return
		}
	}
}

// Copy everything from the pty master to the websocket.
func handleOutput(file *os.File, conn *websocket.Conn) {
	buf := make([]byte, 512)
	// TODO: more graceful exit on socket close / process exit
	for {
		n, err := file.Read(buf)
		if err != nil {
			fmt.Println("Failed to read from pty master: ", err)
			return
		}

		err = conn.WriteMessage(websocket.BinaryMessage, buf[0:n])

		if err != nil {
			fmt.Println("Failed to send %d bytes on websocket: %s", n, err)
			return
		}
	}
}

func ptyHandler(w http.ResponseWriter, r *http.Request, sizeFlag string) {
	var upgrader = websocket.Upgrader{
		ReadBufferSize:  1,
		WriteBufferSize: 1,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		fmt.Println("Websocket upgrade failed: %s", err)
	}
	defer conn.Close()

	cmd, file := start()

	size := strings.Split(sizeFlag, "x")
	cols, _ := strconv.Atoi(size[0])
	lines, _ := strconv.Atoi(size[1])
	if err := win.SetWinsize(file.Fd(), &win.Winsize{Height: uint16(lines), Width: uint16(cols)}); err != nil {
        panic(err)
    }

	go func() {
		handleOutput(file, conn)
	}()

	handleInput(file, conn)

	stop(file, cmd)
}

func main() {
	addrFlag := flag.String("addr", ":12061", "IP:PORT or :PORT address to listen on")
	sizeFlag := flag.String("size", "80x24", "initial size for the tty")

	flag.Parse()

	http.HandleFunc("/pty", func(w http.ResponseWriter, r *http.Request) {
              ptyHandler(w, r, *sizeFlag)
       })

	err := http.ListenAndServe(*addrFlag, nil)
	if err != nil {
		fmt.Println("net.http could not listen on address '%s': %s", addrFlag, err)
	}
}<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
	"text/template"
)

type MenuItem struct {
	Name string
	Link string
}

type SiteConfig struct {
	Title string
	Logo  string
	Style string
}

type Header struct {
	Style   string
	Title   string
	Logo    string
	IsIndex bool
}

type Page struct {
	Header Header
	Menu   string
	Body   string
}

func generateMenu(files []os.FileInfo, isIndex bool) string {
	var m []MenuItem

	if !isIndex {
		m = append(m, MenuItem{Name: ".", Link: "index.html"})
		m = append(m, MenuItem{Name: "..", Link: "../index.html"})
	} else {
		m = append(m, MenuItem{Name: "Home", Link: "index.html"})
	}

	for _, f := range files {
		if strings.HasPrefix(f.Name(), "index") {
			continue
		}
		fname := strings.Split(f.Name(), ".")[0]

		if f.IsDir() {
			m = append(m, MenuItem{Name: fname, Link: fname + "/index.html"})
		} else {
			m = append(m, MenuItem{Name: fname, Link: fname + ".html"})
		}
	}

	ret := &bytes.Buffer{}
	if err := menuTemplate.Execute(ret, m); err != nil {
		fmt.Println(err)
	}
	return ret.String()
}

func parseBody(file string) string {
	body, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println(err)
	}

	imageParser := regexp.MustCompile(`\[\[(.*?)\]\]`)
	linkParser := regexp.MustCompile(`\((.*)\)\[(.*?)\]`)

	imaged := imageParser.ReplaceAllString(string(body), "")
	linked := linkParser.ReplaceAllString(imaged, "$1")

	return linked
}

func generatePage(site Page) string {
	ret := &bytes.Buffer{}
	if err := siteTemplate.Execute(ret, site); err != nil {
		fmt.Println(err)
	}
	return ret.String()
}

func generateSite(header Header, inputDir string, outputDir string) {
	files, _ := ioutil.ReadDir(inputDir)
	menu := generateMenu(files, header.IsIndex)

	for _, f := range files {
		if f.IsDir() {
			if err := os.Mkdir(outputDir+"/"+f.Name(), 0755); err != nil {
				fmt.Println(err)
			}

			header.IsIndex = false
			generateSite(header, inputDir+"/"+f.Name(), outputDir+"/"+f.Name())
			continue
		}

		fname := strings.Split(f.Name(), ".")[0]
		body := parseBody(inputDir + "/" + f.Name())

		page := generatePage(Page{
			Header: header,
			Menu:   menu,
			Body:   string(body),
		})

		if err := ioutil.WriteFile(outputDir+"/"+fname+".html", []byte(page), 0755); err != nil {
			fmt.Println(err)
		}
	}

}

func main() {
	flag.Usage = usage
	flag.Parse()
	if flag.NArg() != 1 {
		usage()
		os.Exit(1)
	}
	siteDir := strings.Split(flag.Arg(0), "/")[0]

	var swagConfig SiteConfig
	config, err := ioutil.ReadFile("swag.conf")
	if err != nil {
		fmt.Println(err)
	}
	dec := json.NewDecoder(bytes.NewReader(config))
	if err := dec.Decode(&swagConfig); err != nil {
		fmt.Println(err)
	}

	outputDir := siteDir + ".static"
	if err := os.RemoveAll(outputDir); err != nil {
		fmt.Println(err)
	}
	if err := os.Mkdir(outputDir, 0755); err != nil {
		fmt.Println(err)
	}

	style, err := ioutil.ReadFile(swagConfig.Style)
	if err != nil {
		fmt.Println(err)
	}

	logo, err := ioutil.ReadFile(swagConfig.Logo)
	if err != nil {
		fmt.Println(err)
	}

	generateSite(Header{
		Style:   string(style),
		Logo:    string(logo),
		Title:   swagConfig.Title,
		IsIndex: true,
	}, siteDir, outputDir)
}

func usage() {
	fmt.Println("Usage: swag <site_dir>")
}

var menuTemplate = template.Must(template.New("menu").Parse(menuASCII))

const menuASCII = `
--{{range .}}| {{.Name}} {{end}}|--
`

var siteTemplate = template.Must(template.New("site").Parse(siteSkeleton))

const siteSkeleton = `

<title>{{.Header.Title}}</title>

{{.Header.Logo}}
{{.Menu}}

{{.Body}}

Powered by swag

`
<commit_msg>Added link to home in the menu of all pages.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
	"text/template"
)

type MenuItem struct {
	Name string
	Link string
}

type SiteConfig struct {
	Title string
	Logo  string
	Style string
}

type Header struct {
	Style    string
	Title    string
	Logo     string
	HomePath string
}

type Page struct {
	Header Header
	Menu   string
	Body   string
}

func generateMenu(files []os.FileInfo, homePath string) string {
	var m []MenuItem

	if homePath != "" {
		m = append(m, MenuItem{Name: ".", Link: "index.html"})
		m = append(m, MenuItem{Name: "..", Link: "../index.html"})
	}
	m = append(m, MenuItem{Name: "home", Link: homePath + "index.html"})

	for _, f := range files {
		if strings.HasPrefix(f.Name(), "index") {
			continue
		}
		fname := strings.Split(f.Name(), ".")[0]

		if f.IsDir() {
			m = append(m, MenuItem{Name: fname, Link: fname + "/index.html"})
		} else {
			m = append(m, MenuItem{Name: fname, Link: fname + ".html"})
		}
	}

	ret := &bytes.Buffer{}
	if err := menuTemplate.Execute(ret, m); err != nil {
		fmt.Println(err)
	}
	return ret.String()
}

func parseBody(file string) string {
	body, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println(err)
	}

	imageParser := regexp.MustCompile(`\[\[(.*?)\]\]`)
	linkParser := regexp.MustCompile(`\((.*)\)\[(.*?)\]`)

	imaged := imageParser.ReplaceAllString(string(body), "")
	linked := linkParser.ReplaceAllString(imaged, "$1")

	return linked
}

func generatePage(site Page) string {
	ret := &bytes.Buffer{}
	if err := siteTemplate.Execute(ret, site); err != nil {
		fmt.Println(err)
	}
	return ret.String()
}

func generateSite(header Header, inputDir string, outputDir string) {
	files, _ := ioutil.ReadDir(inputDir)
	menu := generateMenu(files, header.HomePath)

	for _, f := range files {
		if f.IsDir() {
			if err := os.Mkdir(outputDir+"/"+f.Name(), 0755); err != nil {
				fmt.Println(err)
			}

			header.HomePath = header.HomePath + "../"
			generateSite(header, inputDir+"/"+f.Name(), outputDir+"/"+f.Name())
			continue
		}

		fname := strings.Split(f.Name(), ".")[0]
		body := parseBody(inputDir + "/" + f.Name())

		page := generatePage(Page{
			Header: header,
			Menu:   menu,
			Body:   string(body),
		})

		if err := ioutil.WriteFile(outputDir+"/"+fname+".html", []byte(page), 0755); err != nil {
			fmt.Println(err)
		}
	}

}

func main() {
	flag.Usage = usage
	flag.Parse()
	if flag.NArg() != 1 {
		usage()
		os.Exit(1)
	}
	siteDir := strings.Split(flag.Arg(0), "/")[0]

	var swagConfig SiteConfig
	config, err := ioutil.ReadFile("swag.conf")
	if err != nil {
		fmt.Println(err)
	}
	dec := json.NewDecoder(bytes.NewReader(config))
	if err := dec.Decode(&swagConfig); err != nil {
		fmt.Println(err)
	}

	outputDir := siteDir + ".static"
	if err := os.RemoveAll(outputDir); err != nil {
		fmt.Println(err)
	}
	if err := os.Mkdir(outputDir, 0755); err != nil {
		fmt.Println(err)
	}

	style, err := ioutil.ReadFile(swagConfig.Style)
	if err != nil {
		fmt.Println(err)
	}

	logo, err := ioutil.ReadFile(swagConfig.Logo)
	if err != nil {
		fmt.Println(err)
	}

	generateSite(Header{
		Style:    string(style),
		Logo:     string(logo),
		Title:    swagConfig.Title,
		HomePath: "",
	}, siteDir, outputDir)
}

func usage() {
	fmt.Println("Usage: swag <site_dir>")
}

var menuTemplate = template.Must(template.New("menu").Parse(menuASCII))

const menuASCII = `
--{{range .}}| {{.Name}} {{end}}|--
`

var siteTemplate = template.Must(template.New("site").Parse(siteSkeleton))

const siteSkeleton = `

<title>{{.Header.Title}}</title>

{{.Header.Logo}}
{{.Menu}}

{{.Body}}

Powered by swag

`
<|endoftext|>