<commit_before>package handlers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"image/gif"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
)

type RootSearch struct {
	Kind    string       `json:"kind"`
	Items   []SearchItem `json:"items"`
	Queries Queries      `json:"queries"`
}

type Queries struct {
	NextPage []Next `json:"nextPage"`
}

type Next struct {
	StartIndex int `json:"startIndex"`
}

type SearchItem struct {
	Title string `json:"title"`
	Link  string `json:"link"`
	Mime  string `json:"mime"`
}

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

	query := r.URL.Query().Get("q")
	if query == "" {
		return
	}

	googleURL := "https://www.googleapis.com/customsearch/v1?key=" + os.Getenv("gis_key") + "&alt=json&searchType=image&fileType=gif&num=10&q=" + url.QueryEscape(query)
	validLinks := []string{}

	url := googleURL
	counter := 0
	for len(validLinks) < 10 && counter < 3 {
		root := googleQuery(url)
		if root == nil {
			return
		}

		validFromRoot := validLinksFromRoot(*root)
		validLinks = append(validLinks, validFromRoot...)

		url = googleURL + "&start=" + strconv.Itoa(root.Queries.NextPage[0].StartIndex)
		counter++
	}

	sliceIndex := 10
	if sliceIndex > len(validLinks) {
		sliceIndex = len(validLinks)
	}

	json, _ := json.Marshal(validLinks[0:sliceIndex])
	w.Write(json)
}

func validLinksFromRoot(root RootSearch) []string {
	validLinks := []string{}
	for _, item := range root.Items {
		if isValidGIF(item.Link) {
			validLinks = append(validLinks, item.Link)
		}
	}

	return validLinks
}

func googleQuery(url string) *RootSearch {
	resp, err := http.Get(url)
	defer resp.Body.Close()

	if err != nil {
		fmt.Println(err)
		return nil
	}

	var root RootSearch
	bodyBytes, _ := ioutil.ReadAll(resp.Body)
	err = json.Unmarshal(bodyBytes, &root)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	return &root
}

func isValidGIF(url string) bool {

	if !isValidHTTPURLString(url) {
		return false
	}

	resp, err := http.Get(url)
	defer resp.Body.Close()

	if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return false
	}

	bodyBytes, _ := ioutil.ReadAll(resp.Body)
	byteReader := bytes.NewReader(bodyBytes)

	decode, err := gif.DecodeAll(byteReader)
	if err != nil {
		return false
	}

	return len(decode.Image) > 1
}

func isValidHTTPURLString(s string) bool {
	URL, _ := url.Parse(s)
	return (URL.Scheme == "http" || URL.Scheme == "https")
}
<commit_msg>Significant speedup for google image processing<commit_after>package handlers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"image/gif"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"sync"
)

type RootSearch struct {
	Kind    string       `json:"kind"`
	Items   []SearchItem `json:"items"`
	Queries Queries      `json:"queries"`
}

type Queries struct {
	NextPage []Next `json:"nextPage"`
}

type Next struct {
	StartIndex int `json:"startIndex"`
}

type SearchItem struct {
	Title string `json:"title"`
	Link  string `json:"link"`
	Mime  string `json:"mime"`
}

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

	query := r.URL.Query().Get("q")
	if query == "" {
		return
	}

	googleURL := "https://www.googleapis.com/customsearch/v1?key=" + os.Getenv("gis_key") + "&alt=json&searchType=image&fileType=gif&num=10&q=" + url.QueryEscape(query)
	validLinks := []string{}

	url := googleURL
	counter := 0
	for len(validLinks) < 10 && counter < 3 {
		root := googleQuery(url)
		if root == nil {
			return
		}

		validFromRoot := validLinksFromRoot(*root)
		validLinks = append(validLinks, validFromRoot...)

		url = googleURL + "&start=" + strconv.Itoa(root.Queries.NextPage[0].StartIndex)
		counter++
	}

	sliceIndex := 10
	if sliceIndex > len(validLinks) {
		sliceIndex = len(validLinks)
	}

	json, _ := json.Marshal(validLinks[0:sliceIndex])
	w.Write(json)
}

func validLinksFromRoot(root RootSearch) []string {
	var wg sync.WaitGroup
	out := make(chan string)

	for _, item := range root.Items {
		wg.Add(1)
		go func(link string) {
			if isValidGIF(link) {
				out <- link
			} else {
				out <- ""
			}
			wg.Done()
		}(item.Link)
	}

	go func() {
		wg.Wait()
		close(out)
	}()

	validLinks := []string{}
	for result := range out {
		if result != "" {
			validLinks = append(validLinks, result)
		}
	}

	return validLinks
}

func googleQuery(url string) *RootSearch {
	resp, err := http.Get(url)
	defer resp.Body.Close()

	if err != nil {
		fmt.Println(err)
		return nil
	}

	var root RootSearch
	bodyBytes, _ := ioutil.ReadAll(resp.Body)
	err = json.Unmarshal(bodyBytes, &root)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	return &root
}

func isValidGIF(url string) bool {

	if !isValidHTTPURLString(url) {
		return false
	}

	resp, err := http.Get(url)
	defer resp.Body.Close()

	if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return false
	}

	bodyBytes, _ := ioutil.ReadAll(resp.Body)
	byteReader := bytes.NewReader(bodyBytes)

	decode, err := gif.DecodeAll(byteReader)
	if err != nil {
		return false
	}

	return len(decode.Image) > 1
}

func isValidHTTPURLString(s string) bool {
	URL, _ := url.Parse(s)
	return (URL.Scheme == "http" || URL.Scheme == "https")
}
<|endoftext|>


<commit_before>package handlers

import (
	middleware "github.com/go-openapi/runtime/middleware"

	"github.com/redhatanalytics/oshinko-rest/restapi/operations/server"
	. "github.com/redhatanalytics/oshinko-rest/version"
)

// ServerResponse respond to the server info request
func ServerResponse() middleware.Responder {
	version := GetVersion()
	appname := GetAppName()
	payload := server.GetServerInfoOKBodyBody{
		Application: &server.GetServerInfoOKBodyApplication{
			Name: &appname, Version: &version}}
	return server.NewGetServerInfoOK().WithPayload(payload)
}
<commit_msg>remove dot import for version<commit_after>package handlers

import (
	middleware "github.com/go-openapi/runtime/middleware"

	"github.com/redhatanalytics/oshinko-rest/restapi/operations/server"
	"github.com/redhatanalytics/oshinko-rest/version"
)

// ServerResponse respond to the server info request
func ServerResponse() middleware.Responder {
	vers := version.GetVersion()
	name := version.GetAppName()
	payload := server.GetServerInfoOKBodyBody{
		Application: &server.GetServerInfoOKBodyApplication{
			Name: &name, Version: &vers}}
	return server.NewGetServerInfoOK().WithPayload(payload)
}
<|endoftext|>


<commit_before>package fifty2

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

type Suit uint8

const (
	Clubs Suit = iota
	Diamonds
	Hearts
	Spades
)

func ParseSuit(r rune) (Suit, error) {
	switch r {
	case 'c', 'C', '♣':
		return Clubs, nil
	case 'd', 'D', '♦':
		return Diamonds, nil
	case 'h', 'H', '♥':
		return Hearts, nil
	case 's', 'S', '♠':
		return Spades, nil
	}
	return 0, fmt.Errorf("fifty2: unknown suit[%c]", r)
}

func (s Suit) Rune() rune {
	switch s {
	case Clubs:
		return '♣'
	case Diamonds:
		return '♦'
	case Hearts:
		return '♥'
	case Spades:
		return '♠'
	}
	return 0
}

func (s Suit) Mask() uint8 {
	return uint8(1) << s
}

func Suits() []Suit {
	return []Suit{Clubs, Diamonds, Hearts, Spades}
}

type Rank uint8

const (
	Ace Rank = iota
	Two
	Three
	Four
	Five
	Six
	Seven
	Eight
	Nine
	Ten
	Jack
	Queen
	King
)

func ParseRank(r rune) (Rank, error) {
	switch r {
	case 'a', 'A':
		return Ace, nil
	case '2':
		return Two, nil
	case '3':
		return Three, nil
	case '4':
		return Four, nil
	case '5':
		return Five, nil
	case '6':
		return Six, nil
	case '7':
		return Seven, nil
	case '8':
		return Eight, nil
	case '9':
		return Nine, nil
	case 't', 'T':
		return Ten, nil
	case 'j', 'J':
		return Jack, nil
	case 'q', 'Q':
		return Queen, nil
	case 'k', 'K':
		return King, nil
	}
	return 0, fmt.Errorf("fifty2: unknown rank[%c]", r)
}

func (r Rank) Rune() rune {
	switch r {
	case Ace:
		return 'A'
	case Two:
		return '2'
	case Three:
		return '3'
	case Four:
		return '4'
	case Five:
		return '5'
	case Six:
		return '6'
	case Seven:
		return '7'
	case Eight:
		return '8'
	case Nine:
		return '9'
	case Ten:
		return 'T'
	case Jack:
		return 'J'
	case Queen:
		return 'Q'
	case King:
		return 'K'
	}
	return 0
}

func (r Rank) Mask() uint16 {
	return uint16(1) << r
}

func Ranks() []Rank {
	return []Rank{Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King}
}

type Card struct {
	Rank Rank
	Suit Suit
}

func (c Card) String() string {
	return fmt.Sprintf("%c%c", c.Rank.Rune(), c.Suit.Rune())
}

type CardReader struct {
	reader *bufio.Reader
}

func NewCardReader(reader io.Reader) *CardReader {
	return &CardReader{bufio.NewReader(reader)}
}

func (cr *CardReader) Read() (Card, error) {
	r, _, err := cr.reader.ReadRune()
	if err != nil {
		return Card{}, err
	}

	rank, err := ParseRank(r)
	if err != nil {
		return Card{}, err
	}

	r, _, err = cr.reader.ReadRune()
	if err != nil {
		return Card{}, err
	}

	suit, err := ParseSuit(r)
	if err != nil {
		return Card{}, err
	}

	return Card{rank, suit}, nil
}

func (cr *CardReader) ReadAll() ([]Card, error) {
	cards := make([]Card, 0)
	for  {
		card, err := cr.Read()
		if err == nil {
			cards = append(cards, card)
		} else if err == io.EOF {
			return cards, nil
		} else {
			return cards, err
		}
	}
}

func NewDeck() []Card {
	deck := make([]Card, 52)
	index := 0
	for _, suit := range Suits() {
		for _, rank := range Ranks() {
			deck[index] = Card{Rank: rank, Suit: suit}
			index++
		}
	}
	return deck
}

func NewDeckSet(decks uint) []Card {
	deckSet := make([]Card, 52*decks)
	for d := uint(0); d < decks; d++ {
		a := d * 52
		b := a + 52
		copy(deckSet[a:b], NewDeck())
	}
	return deckSet
}

func Shuffle(slice []Card) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for src := 0; src < len(slice); src++ {
		dest := r.Intn(len(slice))
		slice[dest], slice[src] = slice[src], slice[dest]
	}
}

func Combinations(slice []Card, choose int) chan []Card {
	if choose > len(slice) {
		panic("fifty2: cannot produce combinations larger than given card slice")
	}

	ch := make(chan []Card)
	go func() {
		findCombinations(slice, make([]Card, choose), choose, ch)
		close(ch)
	}()

	return ch
}

func findCombinations(slice []Card, combo []Card, choose int, ch chan []Card) {
	for i, c := range slice {
		combo[len(combo)-choose] = c
		if choose == 1 {
			result := make([]Card, len(combo))
			copy(result, combo)
			ch <- result
		} else {
			findCombinations(slice[i+1:], combo, choose-1, ch)
		}
	}
}
<commit_msg>card slice helpers<commit_after>package fifty2

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

type Suit uint8

const (
	Clubs Suit = iota
	Diamonds
	Hearts
	Spades
)

func ParseSuit(r rune) (Suit, error) {
	switch r {
	case 'c', 'C', '♣':
		return Clubs, nil
	case 'd', 'D', '♦':
		return Diamonds, nil
	case 'h', 'H', '♥':
		return Hearts, nil
	case 's', 'S', '♠':
		return Spades, nil
	}
	return 0, fmt.Errorf("fifty2: unknown suit[%c]", r)
}

func (s Suit) Rune() rune {
	switch s {
	case Clubs:
		return '♣'
	case Diamonds:
		return '♦'
	case Hearts:
		return '♥'
	case Spades:
		return '♠'
	}
	return 0
}

func (s Suit) Mask() uint8 {
	return uint8(1) << s
}

func Suits() []Suit {
	return []Suit{Clubs, Diamonds, Hearts, Spades}
}

type Rank uint8

const (
	Ace Rank = iota
	Two
	Three
	Four
	Five
	Six
	Seven
	Eight
	Nine
	Ten
	Jack
	Queen
	King
)

func ParseRank(r rune) (Rank, error) {
	switch r {
	case 'a', 'A':
		return Ace, nil
	case '2':
		return Two, nil
	case '3':
		return Three, nil
	case '4':
		return Four, nil
	case '5':
		return Five, nil
	case '6':
		return Six, nil
	case '7':
		return Seven, nil
	case '8':
		return Eight, nil
	case '9':
		return Nine, nil
	case 't', 'T':
		return Ten, nil
	case 'j', 'J':
		return Jack, nil
	case 'q', 'Q':
		return Queen, nil
	case 'k', 'K':
		return King, nil
	}
	return 0, fmt.Errorf("fifty2: unknown rank[%c]", r)
}

func (r Rank) Rune() rune {
	switch r {
	case Ace:
		return 'A'
	case Two:
		return '2'
	case Three:
		return '3'
	case Four:
		return '4'
	case Five:
		return '5'
	case Six:
		return '6'
	case Seven:
		return '7'
	case Eight:
		return '8'
	case Nine:
		return '9'
	case Ten:
		return 'T'
	case Jack:
		return 'J'
	case Queen:
		return 'Q'
	case King:
		return 'K'
	}
	return 0
}

func (r Rank) Mask() uint16 {
	return uint16(1) << r
}

func Ranks() []Rank {
	return []Rank{Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King}
}

type Card struct {
	Rank Rank
	Suit Suit
}

func (c Card) String() string {
	return fmt.Sprintf("%c%c", c.Rank.Rune(), c.Suit.Rune())
}

type CardReader struct {
	reader *bufio.Reader
}

func NewCardReader(reader io.Reader) *CardReader {
	return &CardReader{bufio.NewReader(reader)}
}

func (cr *CardReader) Read() (Card, error) {
	r, _, err := cr.reader.ReadRune()
	if err != nil {
		return Card{}, err
	}

	rank, err := ParseRank(r)
	if err != nil {
		return Card{}, err
	}

	r, _, err = cr.reader.ReadRune()
	if err != nil {
		return Card{}, err
	}

	suit, err := ParseSuit(r)
	if err != nil {
		return Card{}, err
	}

	return Card{rank, suit}, nil
}

func (cr *CardReader) ReadAll() ([]Card, error) {
	cards := make([]Card, 0)
	for  {
		card, err := cr.Read()
		if err == nil {
			cards = append(cards, card)
		} else if err == io.EOF {
			return cards, nil
		} else {
			return cards, err
		}
	}
}

func NewDeck() []Card {
	deck := make([]Card, 52)
	index := 0
	for _, suit := range Suits() {
		for _, rank := range Ranks() {
			deck[index] = Card{Rank: rank, Suit: suit}
			index++
		}
	}
	return deck
}

func NewDeckSet(decks uint) []Card {
	deckSet := make([]Card, 52*decks)
	for d := uint(0); d < decks; d++ {
		a := d * 52
		b := a + 52
		copy(deckSet[a:b], NewDeck())
	}
	return deckSet
}

func Shuffle(slice []Card) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for src := 0; src < len(slice); src++ {
		dest := r.Intn(len(slice))
		slice[dest], slice[src] = slice[src], slice[dest]
	}
}

func Index(slice []Card, card Card) int {
	for i, c := range slice {
		if c == card {
			return i
		}
	}
	return -1
}

func Remove(slice []Card, card Card) []Card {
	index := Index(slice, card)
	if index < 0 {
		return slice
	}
	return append(slice[:index], slice[index+1:]...)
}

func Combinations(slice []Card, choose int) chan []Card {
	if choose > len(slice) {
		panic("fifty2: cannot produce combinations larger than given card slice")
	}

	ch := make(chan []Card)
	go func() {
		findCombinations(slice, make([]Card, choose), choose, ch)
		close(ch)
	}()

	return ch
}

func findCombinations(slice []Card, combo []Card, choose int, ch chan []Card) {
	for i, c := range slice {
		combo[len(combo)-choose] = c
		if choose == 1 {
			result := make([]Card, len(combo))
			copy(result, combo)
			ch <- result
		} else {
			findCombinations(slice[i+1:], combo, choose-1, ch)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
	"regexp"
)

// Prefix which identifies file contents as a git-lob SHA entry
// Use this prefix rather than just the SHA in case by accident a file's content
// actually is a 40-char pattern
const SHAPrefix = "git-lob: "
const SHALineLen = len(SHAPrefix) + 40

func SmudgeFilter() int {
	LogDebug("Running smudge filter")
	shaRegex := regexp.MustCompile("^git-lob: ([0-9A-Fa-f]{40})$")
	// read committed content from stdin
	// write actual file content to stdout if a git-lob SHA
	buf := make([]byte, SHALineLen)
	c, err := os.Stdin.Read(buf)
	if c == SHALineLen {
		if match := shaRegex.FindStringSubmatch(string(buf)); match != nil {
			sha := match[1]
			lobinfo, err := RetrieveLOB(sha, os.Stdout)
			if err == nil {
				LogDebugf("Retrieved LOB for %v from %v chunks\n", sha, lobinfo.NumChunks)
				return 0
			} else {
				LogErrorf("Error obtaining LOB data: %v\n", err)
			}

		}
	}
	// Otherwise, pass through content
	os.Stdout.Write(buf[:c])
	_, err = io.Copy(os.Stdout, os.Stdin)
	if err == nil {
		return 0
	}

	LogErrorf("Error copying stdin->stdout: %v\n", err)
	return 3
}

func CleanFilter() int {
	LogDebug("Running clean filter")
	shaRegex := regexp.MustCompile("^git-lob: ([0-9A-Fa-f]{40})$")
	// read working copy content from stdin
	// First check if this is an unexpanded LOB SHA (not downloaded)
	buf := make([]byte, SHALineLen)
	c, err := os.Stdin.Read(buf)
	if c == SHALineLen {
		if match := shaRegex.FindStringSubmatch(string(buf)); match != nil {
			sha := match[1]
			LogDebugf("Unexpanded LOB SHA in file content (%v), clean filter will not change\n", sha)
			// Yes, unexpanded SHA, just write
			os.Stdout.Write(buf[:c])
			_, err = io.Copy(os.Stdout, os.Stdin)
			if err == nil {
				return 0
			} else {
				LogErrorf("Error writing unexpanded LOB in clean filter: %v\n", err)
				return 3
			}

		}
	}
	// Otherwise if we got here, this is just binary data we need to hash
	lobinfo, err := StoreLOB(os.Stdin, buf)

	if err != nil {
		LogErrorf("Error storing LOB in clean filter: %v\n", err)
		return 4
	}

	LogDebugf("Successfully stored/checked LOB data for SHA %v, %d chunks, total size %v\n", lobinfo.SHA, lobinfo.NumChunks, lobinfo.Size)

	return 0
}
<commit_msg>If actual file is smaller than SHA identifier text, pass only the correct length of data for storage<commit_after>package main

import (
	"io"
	"os"
	"regexp"
)

// Prefix which identifies file contents as a git-lob SHA entry
// Use this prefix rather than just the SHA in case by accident a file's content
// actually is a 40-char pattern
const SHAPrefix = "git-lob: "
const SHALineLen = len(SHAPrefix) + 40

func SmudgeFilter() int {
	LogDebug("Running smudge filter")
	shaRegex := regexp.MustCompile("^git-lob: ([0-9A-Fa-f]{40})$")
	// read committed content from stdin
	// write actual file content to stdout if a git-lob SHA
	buf := make([]byte, SHALineLen)
	c, err := os.Stdin.Read(buf)
	if c == SHALineLen {
		if match := shaRegex.FindStringSubmatch(string(buf)); match != nil {
			sha := match[1]
			lobinfo, err := RetrieveLOB(sha, os.Stdout)
			if err == nil {
				LogDebugf("Retrieved LOB for %v from %v chunks\n", sha, lobinfo.NumChunks)
				return 0
			} else {
				LogErrorf("Error obtaining LOB data: %v\n", err)
			}

		}
	}
	// Otherwise, pass through content
	os.Stdout.Write(buf[:c])
	_, err = io.Copy(os.Stdout, os.Stdin)
	if err == nil {
		return 0
	}

	LogErrorf("Error copying stdin->stdout: %v\n", err)
	return 3
}

func CleanFilter() int {
	LogDebug("Running clean filter")
	shaRegex := regexp.MustCompile("^git-lob: ([0-9A-Fa-f]{40})$")
	// read working copy content from stdin
	// First check if this is an unexpanded LOB SHA (not downloaded)
	buf := make([]byte, SHALineLen)
	c, err := os.Stdin.Read(buf)
	if c == SHALineLen {
		if match := shaRegex.FindStringSubmatch(string(buf)); match != nil {
			sha := match[1]
			LogDebugf("Unexpanded LOB SHA in file content (%v), clean filter will not change\n", sha)
			// Yes, unexpanded SHA, just write
			os.Stdout.Write(buf[:c])
			_, err = io.Copy(os.Stdout, os.Stdin)
			if err == nil {
				return 0
			} else {
				LogErrorf("Error writing unexpanded LOB in clean filter: %v\n", err)
				return 3
			}

		}
	}
	// Otherwise if we got here, this is just binary data we need to hash
	lobinfo, err := StoreLOB(os.Stdin, buf[:c])

	if err != nil {
		LogErrorf("Error storing LOB in clean filter: %v\n", err)
		return 4
	}

	LogDebugf("Successfully stored/checked LOB data for SHA %v, %d chunks, total size %v\n", lobinfo.SHA, lobinfo.NumChunks, lobinfo.Size)

	return 0
}
<|endoftext|>


<commit_before>//Package gpsdfilter is for filtering gpsd JSON documents
package gpsdfilter

import (
	"encoding/json"
	"sync"
)

//Rule is a type that descripe how to filter a gpsd JSON document
type Rule struct {
	Class string
	DoLog bool
	Type  Type
}

//Filter contains all the filter rules of type *Rule
type Filter struct {
	mutex sync.Mutex
	rules map[string]*Rule
}

//AddRule adds a *Rule
//Error ErrRuleIsNil is returned if the *Rule is nil, otherwise
//the nil error is returned
func (f *Filter) AddRule(r *Rule) error {
	f.mutex.Lock()
	defer f.mutex.Unlock()

	if r == nil {
		return ErrRuleIsNil
	}
	f.rules[r.Class] = r

	return nil
}

//Filter takes a byte slice as input, and returns 3 types of information:
//  A boolean: If true, the gpsd JSON document should be logged, otherwise not logged
//  A Type: Tells what to do with the gpsd JSON document.
//  An error: Error ErrFilterNoSuchRule is returned if the rule is unknown.
//  An error from the json paser can also be returned, and
//  otherwise the nil error is returned.
func (f *Filter) Filter(p []byte) (bool, Type, error) {
	var (
		c   Class
		err error
	)
	if err = json.Unmarshal(p, &c); err != nil {
		return false, TypeUnknown, err
	}
	return f.FilterClass(c.Class)
}

//FilterClass takes a class of type string, fx. "TPV", as input, and returns 3
// types of information:
//  A boolean: If true, the gpsd JSON document should be logged, otherwise not logged
//  A Type: Tells what to do with the gpsd JSON document.
//  An error: Error ErrFilterNoSuchRule is returned if the rule is unknown.
//  An error from the json paser can also be returned
func (f *Filter) FilterClass(class string) (bool, Type, error) {
	var (
		rule *Rule
		ok   bool
	)
	f.mutex.Lock()
	defer f.mutex.Unlock()

	if rule, ok = f.rules[class]; ok == false {
		return false, TypeUnknown, ErrFilterNoSuchRule
	}
	return rule.DoLog, rule.Type, nil
}
<commit_msg> Changed Filter, and FilterClass return types 	modified:   filter.go<commit_after>//Package gpsdfilter is for filtering gpsd JSON documents
package gpsdfilter

import (
	"encoding/json"
	"sync"
)

//Rule is a type that descripe how to filter a gpsd JSON document
type Rule struct {
	Class string
	DoLog bool
	Type  Type
}

//Filter contains all the filter rules of type *Rule
type Filter struct {
	mutex sync.Mutex
	rules map[string]*Rule
}

//AddRule adds a *Rule
//Error ErrRuleIsNil is returned if the *Rule is nil, otherwise
//the nil error is returned
func (f *Filter) AddRule(r *Rule) error {
	f.mutex.Lock()
	defer f.mutex.Unlock()

	if r == nil {
		return ErrRuleIsNil
	}
	f.rules[r.Class] = r

	return nil
}

//Filter takes a byte slice as input, and returns a *Rule and an error
// The Error ErrFilterNoSuchRule is returned if the rule is unknown.
//  An error from the json paser can also be returned.
// If there is an error, then *Rule is nil.
// If there are no errors, then the error is nil
func (f *Filter) Filter(p []byte) (*Rule, error) {
	var (
		c   Class
		err error
	)
	if err = json.Unmarshal(p, &c); err != nil {
		return nil, err
	}
	return f.FilterClass(c.Class)
}

//FilterClass takes a class of type string, fx. "TPV", as input, and returns a
// *Rule and an error
// The Error ErrFilterNoSuchRule is returned if the rule is unknown.
//  An error from the json paser can also be returned.
// If there is an error, then *Rule is nil.
// If there are no errors, then the error is nil
func (f *Filter) FilterClass(class string) (*Rule, error) {
	var (
		rule *Rule
		ok   bool
	)
	f.mutex.Lock()
	defer f.mutex.Unlock()

	if rule, ok = f.rules[class]; ok == false {
		return nil, ErrFilterNoSuchRule
	}
	return rule, nil
}
<|endoftext|>


<commit_before>package repo

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/wallix/awless/config"
	"github.com/wallix/awless/graph"

	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type Rev struct {
	Id   string
	Date time.Time

	Infra  *graph.Graph
	Access *graph.Graph
}

func (r *Rev) DateString() string {
	return r.Date.Format("Mon Jan 2 15:04:05")
}

type Repo interface {
	Commit(files ...string) error
	List() ([]*Rev, error)
	LoadRev(version string) (*Rev, error)
}

type noRevisionRepo struct{}

func (*noRevisionRepo) Commit(files ...string) error         { return nil }
func (*noRevisionRepo) LoadRev(version string) (*Rev, error) { return &Rev{}, nil }
func (*noRevisionRepo) List() ([]*Rev, error)                { return nil, nil }

type gitRepo struct {
	repo  *git.Repository
	files []string
	path  string
}

func New() (Repo, error) {
	if IsGitInstalled() {
		return newGitRepo(config.RepoDir)
	} else {
		return &noRevisionRepo{}, nil
	}
}

func IsGitInstalled() bool {
	_, err := exec.LookPath("git")
	return err == nil
}

func newGitRepo(path string) (Repo, error) {
	if _, err := os.Stat(filepath.Join(path, ".git")); os.IsNotExist(err) {
		if _, err := newGit(path).run("init"); err != nil {
			return nil, err
		}
	}

	repo, err := git.NewFilesystemRepository(filepath.Join(path, ".git"))
	return &gitRepo{repo: repo, path: path}, err
}

func (r *gitRepo) List() ([]*Rev, error) {
	var all []*Rev

	iter, err := r.repo.Commits()
	if err != nil {
		return all, err
	}
	defer iter.Close()

	for {
		commit, err := iter.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			panic(fmt.Sprintf("error listing repo revisions: %s", err))
		}

		all = append(all, &Rev{Id: commit.Hash.String(), Date: commit.Committer.When})
	}

	sort.Sort(revsByDate(all))

	return all, nil
}

func reduceToLastRevOfEachDay(revs []*Rev) []*Rev {
	perDay := make(map[string][]*Rev)

	for _, rev := range revs {
		day := rev.Date.Format("2006-01-02")
		perDay[day] = append(perDay[day], rev)
	}

	reduce := []*Rev{}
	for _, v := range perDay {
		sort.Sort(sort.Reverse(revsByDate(v)))
		reduce = append(reduce, v[0])
	}

	return reduce
}

func (r *gitRepo) LoadRev(version string) (*Rev, error) {
	rev := &Rev{Id: version}

	commit, err := r.repo.Commit(plumbing.NewHash(version))
	if err != nil {
		return nil, err
	}

	rev.Date = commit.Committer.When

	f, err := commit.File(config.InfraFilename)
	if err != nil {
		return nil, err
	}
	contents, err := f.Contents()
	if err != nil {
		return nil, err
	}

	infraG := graph.NewGraph()
	infraG.Unmarshal([]byte(contents))
	rev.Infra = infraG

	f, err = commit.File(config.AccessFilename)
	if err != nil {
		return nil, err
	}
	contents, err = f.Contents()
	if err != nil {
		return nil, err
	}
	accessG := graph.NewGraph()
	accessG.Unmarshal([]byte(contents))
	rev.Access = accessG

	return rev, nil
}

func (r *gitRepo) Commit(files ...string) error {
	for _, path := range files {
		r.files = append(r.files, path)
	}

	for _, path := range r.files {
		if _, err := newGit(r.path).run("add", path); err != nil {
			return err
		}
	}

	if hasChanges, err := r.hasChanges(); err != nil {
		return err
	} else if !hasChanges {
		return nil
	}

	if _, err := newGit(r.path).run("-c", "user.name='awless'", "-c", "user.email='git@awless.io'", "commit", "-m", "new sync"); err != nil {
		return err
	}

	return nil
}

func (r *gitRepo) hasChanges() (bool, error) {
	stdout, err := newGit(r.path).run("status", "--porcelain")
	if err != nil {
		return false, err
	}

	return !(strings.TrimSpace(stdout) == ""), nil
}
<commit_msg>Sync: adding which files are synced in git message<commit_after>package repo

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/wallix/awless/config"
	"github.com/wallix/awless/graph"

	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type Rev struct {
	Id   string
	Date time.Time

	Infra  *graph.Graph
	Access *graph.Graph
}

func (r *Rev) DateString() string {
	return r.Date.Format("Mon Jan 2 15:04:05")
}

type Repo interface {
	Commit(files ...string) error
	List() ([]*Rev, error)
	LoadRev(version string) (*Rev, error)
}

type noRevisionRepo struct{}

func (*noRevisionRepo) Commit(files ...string) error         { return nil }
func (*noRevisionRepo) LoadRev(version string) (*Rev, error) { return &Rev{}, nil }
func (*noRevisionRepo) List() ([]*Rev, error)                { return nil, nil }

type gitRepo struct {
	repo  *git.Repository
	files []string
	path  string
}

func New() (Repo, error) {
	if IsGitInstalled() {
		return newGitRepo(config.RepoDir)
	} else {
		return &noRevisionRepo{}, nil
	}
}

func IsGitInstalled() bool {
	_, err := exec.LookPath("git")
	return err == nil
}

func newGitRepo(path string) (Repo, error) {
	if _, err := os.Stat(filepath.Join(path, ".git")); os.IsNotExist(err) {
		if _, err := newGit(path).run("init"); err != nil {
			return nil, err
		}
	}

	repo, err := git.NewFilesystemRepository(filepath.Join(path, ".git"))
	return &gitRepo{repo: repo, path: path}, err
}

func (r *gitRepo) List() ([]*Rev, error) {
	var all []*Rev

	iter, err := r.repo.Commits()
	if err != nil {
		return all, err
	}
	defer iter.Close()

	for {
		commit, err := iter.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			panic(fmt.Sprintf("error listing repo revisions: %s", err))
		}

		all = append(all, &Rev{Id: commit.Hash.String(), Date: commit.Committer.When})
	}

	sort.Sort(revsByDate(all))

	return all, nil
}

func reduceToLastRevOfEachDay(revs []*Rev) []*Rev {
	perDay := make(map[string][]*Rev)

	for _, rev := range revs {
		day := rev.Date.Format("2006-01-02")
		perDay[day] = append(perDay[day], rev)
	}

	reduce := []*Rev{}
	for _, v := range perDay {
		sort.Sort(sort.Reverse(revsByDate(v)))
		reduce = append(reduce, v[0])
	}

	return reduce
}

func (r *gitRepo) LoadRev(version string) (*Rev, error) {
	rev := &Rev{Id: version}

	commit, err := r.repo.Commit(plumbing.NewHash(version))
	if err != nil {
		return nil, err
	}

	rev.Date = commit.Committer.When

	f, err := commit.File(config.InfraFilename)
	if err != nil {
		return nil, err
	}
	contents, err := f.Contents()
	if err != nil {
		return nil, err
	}

	infraG := graph.NewGraph()
	infraG.Unmarshal([]byte(contents))
	rev.Infra = infraG

	f, err = commit.File(config.AccessFilename)
	if err != nil {
		return nil, err
	}
	contents, err = f.Contents()
	if err != nil {
		return nil, err
	}
	accessG := graph.NewGraph()
	accessG.Unmarshal([]byte(contents))
	rev.Access = accessG

	return rev, nil
}

func (r *gitRepo) Commit(files ...string) error {
	for _, path := range files {
		r.files = append(r.files, path)
	}

	for _, path := range r.files {
		if _, err := newGit(r.path).run("add", path); err != nil {
			return err
		}
	}

	if hasChanges, err := r.hasChanges(); err != nil {
		return err
	} else if !hasChanges {
		return nil
	}

	_, err := newGit(r.path).run(
		append(awlessCommitter, "commit", "-m", fmt.Sprintf("syncing %s", strings.Join(files, ", ")))...,
	)

	return err
}

var awlessCommitter = []string{"-c", "user.name='awless'", "-c", "user.email='git@awless.io'"}

func (r *gitRepo) hasChanges() (bool, error) {
	stdout, err := newGit(r.path).run("status", "--porcelain")
	if err != nil {
		return false, err
	}

	return !(strings.TrimSpace(stdout) == ""), nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 simulator

import (
	"fmt"
	"math"

	kube_api "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	kube_client "k8s.io/kubernetes/pkg/client/unversioned"
	cmd "k8s.io/kubernetes/pkg/kubectl/cmd"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"

	"github.com/golang/glog"
)

// FindNodesToRemove finds nodes that can be removed.
func FindNodesToRemove(candidates []*kube_api.Node, allNodes []*kube_api.Node, pods []*kube_api.Pod,
	client *kube_client.Client, predicateChecker *PredicateChecker, maxCount int,
	fastCheck bool) ([]*kube_api.Node, error) {

	nodeNameToNodeInfo := schedulercache.CreateNodeNameToInfoMap(pods)
	for _, node := range allNodes {
		if nodeInfo, found := nodeNameToNodeInfo[node.Name]; found {
			nodeInfo.SetNode(node)
		}
	}
	result := make([]*kube_api.Node, 0)

	for _, node := range candidates {
		glog.V(2).Infof("Considering %s for removal", node.Name)

		var podsToRemove []*kube_api.Pod
		var err error

		if fastCheck {
			if nodeInfo, found := nodeNameToNodeInfo[node.Name]; found {
				podsToRemove, err = FastGetPodsToMove(nodeInfo, false, kube_api.Codecs.UniversalDecoder())
			}
		} else {
			drainResult, _, _, err := cmd.GetPodsForDeletionOnNodeDrain(client, node.Name,
				kube_api.Codecs.UniversalDecoder(), false, true)

			if err != nil {
				glog.V(2).Infof("Node %s cannot be removed: %v", node.Name, err)
				continue
			}
			podsToRemove = make([]*kube_api.Pod, 0, len(drainResult))
			for i := range drainResult {
				podsToRemove = append(podsToRemove, &drainResult[i])
			}
		}

		findProblems := findPlaceFor(node.Name, podsToRemove, allNodes, nodeNameToNodeInfo, predicateChecker)
		if findProblems == nil {
			result = append(result, node)
			if len(result) >= maxCount {
				break
			}
		}
		glog.V(2).Infof("Node %s is not suitable for removal %v", node.Name, err)
	}
	return result, nil
}

// CalculateReservation calculates reservation of a node.
func CalculateReservation(node *kube_api.Node, nodeInfo *schedulercache.NodeInfo) (float64, error) {
	cpu, err := calculateReservationOfResource(node, nodeInfo, kube_api.ResourceCPU)
	if err != nil {
		return 0, err
	}
	mem, err := calculateReservationOfResource(node, nodeInfo, kube_api.ResourceMemory)
	if err != nil {
		return 0, err
	}
	return math.Max(cpu, mem), nil
}

func calculateReservationOfResource(node *kube_api.Node, nodeInfo *schedulercache.NodeInfo, resourceName kube_api.ResourceName) (float64, error) {
	nodeCapacity, found := node.Status.Capacity[resourceName]
	if !found {
		return 0, fmt.Errorf("Failed to get %v from %s", resourceName, node.Name)
	}
	if nodeCapacity.MilliValue() == 0 {
		return 0, fmt.Errorf("%v is 0 at %s", resourceName, node.Name)
	}
	podsRequest := resource.MustParse("0")
	for _, pod := range nodeInfo.Pods() {
		for _, container := range pod.Spec.Containers {
			if resourceValue, found := container.Resources.Requests[resourceName]; found {
				podsRequest.Add(resourceValue)
			}
		}
	}
	return float64(podsRequest.MilliValue()) / float64(nodeCapacity.MilliValue()), nil
}

// TODO: We don't need to pass list of nodes here as they are already available in nodeInfos.
func findPlaceFor(bannedNode string, pods []*kube_api.Pod, nodes []*kube_api.Node, nodeInfos map[string]*schedulercache.NodeInfo,
	predicateChecker *PredicateChecker) error {

	newNodeInfos := make(map[string]*schedulercache.NodeInfo)

	for _, pod := range pods {
		foundPlace := false
		glog.V(4).Infof("Looking for place for %s/%s", pod.Namespace, pod.Name)
		podKey := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)

		// TODO: Sort nodes by reservation
	nodeloop:
		for _, node := range nodes {
			if node.Name == bannedNode {
				continue
			}

			node.Status.Allocatable = node.Status.Capacity
			nodeInfo, found := newNodeInfos[node.Name]
			if !found {
				nodeInfo, found = nodeInfos[node.Name]
			}

			if found {
				err := predicateChecker.CheckPredicates(pod, nodeInfo)
				glog.V(4).Infof("Evaluation %s for %s -> %v", node.Name, podKey, err)
				if err == nil {
					foundPlace = true
					// TODO(mwielgus): Optimize it.
					podsOnNode := nodeInfo.Pods()
					podsOnNode = append(podsOnNode, pod)
					newNodeInfo := schedulercache.NewNodeInfo(podsOnNode...)
					newNodeInfo.SetNode(node)
					newNodeInfos[node.Name] = newNodeInfo
					break nodeloop
				}
			}
		}
		if !foundPlace {
			return fmt.Errorf("failed to find place for %s", podKey)
		}
	}
	return nil
}
<commit_msg>Cluster-autoscaler: clear hostname when looking for a new node for pod<commit_after>/*
Copyright 2016 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 simulator

import (
	"fmt"
	"math"

	kube_api "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	kube_client "k8s.io/kubernetes/pkg/client/unversioned"
	cmd "k8s.io/kubernetes/pkg/kubectl/cmd"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"

	"github.com/golang/glog"
)

// FindNodesToRemove finds nodes that can be removed.
func FindNodesToRemove(candidates []*kube_api.Node, allNodes []*kube_api.Node, pods []*kube_api.Pod,
	client *kube_client.Client, predicateChecker *PredicateChecker, maxCount int,
	fastCheck bool) ([]*kube_api.Node, error) {

	nodeNameToNodeInfo := schedulercache.CreateNodeNameToInfoMap(pods)
	for _, node := range allNodes {
		if nodeInfo, found := nodeNameToNodeInfo[node.Name]; found {
			nodeInfo.SetNode(node)
		}
	}
	result := make([]*kube_api.Node, 0)

	for _, node := range candidates {
		glog.V(2).Infof("Considering %s for removal", node.Name)

		var podsToRemove []*kube_api.Pod
		var err error

		if fastCheck {
			if nodeInfo, found := nodeNameToNodeInfo[node.Name]; found {
				podsToRemove, err = FastGetPodsToMove(nodeInfo, false, kube_api.Codecs.UniversalDecoder())
			}
		} else {
			drainResult, _, _, err := cmd.GetPodsForDeletionOnNodeDrain(client, node.Name,
				kube_api.Codecs.UniversalDecoder(), false, true)

			if err != nil {
				glog.V(2).Infof("Node %s cannot be removed: %v", node.Name, err)
				continue
			}
			podsToRemove = make([]*kube_api.Pod, 0, len(drainResult))
			for i := range drainResult {
				podsToRemove = append(podsToRemove, &drainResult[i])
			}
		}

		findProblems := findPlaceFor(node.Name, podsToRemove, allNodes, nodeNameToNodeInfo, predicateChecker)
		if findProblems == nil {
			result = append(result, node)
			if len(result) >= maxCount {
				break
			}
		}
		glog.V(2).Infof("Node %s is not suitable for removal %v", node.Name, err)
	}
	return result, nil
}

// CalculateReservation calculates reservation of a node.
func CalculateReservation(node *kube_api.Node, nodeInfo *schedulercache.NodeInfo) (float64, error) {
	cpu, err := calculateReservationOfResource(node, nodeInfo, kube_api.ResourceCPU)
	if err != nil {
		return 0, err
	}
	mem, err := calculateReservationOfResource(node, nodeInfo, kube_api.ResourceMemory)
	if err != nil {
		return 0, err
	}
	return math.Max(cpu, mem), nil
}

func calculateReservationOfResource(node *kube_api.Node, nodeInfo *schedulercache.NodeInfo, resourceName kube_api.ResourceName) (float64, error) {
	nodeCapacity, found := node.Status.Capacity[resourceName]
	if !found {
		return 0, fmt.Errorf("Failed to get %v from %s", resourceName, node.Name)
	}
	if nodeCapacity.MilliValue() == 0 {
		return 0, fmt.Errorf("%v is 0 at %s", resourceName, node.Name)
	}
	podsRequest := resource.MustParse("0")
	for _, pod := range nodeInfo.Pods() {
		for _, container := range pod.Spec.Containers {
			if resourceValue, found := container.Resources.Requests[resourceName]; found {
				podsRequest.Add(resourceValue)
			}
		}
	}
	return float64(podsRequest.MilliValue()) / float64(nodeCapacity.MilliValue()), nil
}

// TODO: We don't need to pass list of nodes here as they are already available in nodeInfos.
func findPlaceFor(bannedNode string, pods []*kube_api.Pod, nodes []*kube_api.Node, nodeInfos map[string]*schedulercache.NodeInfo,
	predicateChecker *PredicateChecker) error {

	newNodeInfos := make(map[string]*schedulercache.NodeInfo)

	for _, podptr := range pods {
		newpod := *podptr
		newpod.Spec.NodeName = ""
		pod := &newpod

		foundPlace := false
		glog.V(4).Infof("Looking for place for %s/%s", pod.Namespace, pod.Name)
		podKey := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)

		// TODO: Sort nodes by reservation
	nodeloop:
		for _, node := range nodes {
			if node.Name == bannedNode {
				continue
			}

			node.Status.Allocatable = node.Status.Capacity
			nodeInfo, found := newNodeInfos[node.Name]
			if !found {
				nodeInfo, found = nodeInfos[node.Name]
			}

			if found {
				err := predicateChecker.CheckPredicates(pod, nodeInfo)
				glog.V(4).Infof("Evaluation %s for %s -> %v", node.Name, podKey, err)
				if err == nil {
					foundPlace = true
					// TODO(mwielgus): Optimize it.
					podsOnNode := nodeInfo.Pods()
					podsOnNode = append(podsOnNode, pod)
					newNodeInfo := schedulercache.NewNodeInfo(podsOnNode...)
					newNodeInfo.SetNode(node)
					newNodeInfos[node.Name] = newNodeInfo
					break nodeloop
				}
			}
		}
		if !foundPlace {
			return fmt.Errorf("failed to find place for %s", podKey)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"

	"appengine"
	"appengine/taskqueue"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

	mdl "github.com/santiaago/gonawin/models"
)

// requestContext type holds the information needed read the request and log any errors.
type requestContext struct {
	c    appengine.Context // appengine context
	desc string            // handler description
	r    *http.Request     // the HTTP request
}

// tournament returns a tournament instance.
// It gets the 'tournamentId' from the request and queries the datastore to get
// the tournament.
func (rc requestContext) tournament() (*mdl.Tournament, error) {

	strTournamentId, err := route.Context.Get(rc.r, "tournamentId")
	if err != nil {
		log.Errorf(rc.c, "%s error getting tournament id, err:%v", rc.desc, err)
		return nil, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var tournamentId int64
	tournamentId, err = strconv.ParseInt(strTournamentId, 0, 64)
	if err != nil {
		log.Errorf(rc.c, "%s error converting tournament id from string to int64, err:%v", rc.desc, err)
		return nil, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var tournament *mdl.Tournament
	if tournament, err = mdl.TournamentById(rc.c, tournamentId); err != nil {
		log.Errorf(rc.c, "%s tournament not found: %v", rc.desc, err)
		return nil, &helpers.NotFound{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}
	return tournament, nil
}

// userId returns a userId.
// It gets the 'userId' from the request and parses it to int64
func (rc requestContext) userId() (int64, error) {

	strUserId, err := route.Context.Get(rc.r, "userId")
	if err != nil {
		log.Errorf(rc.c, "%s error getting user id, err:%v", rc.desc, err)
		return 0, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}

	var userId int64
	userId, err = strconv.ParseInt(strUserId, 0, 64)
	if err != nil {
		log.Errorf(rc.c, "%s error converting user id from string to int64, err:%v", rc.desc, err)
		return 0, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}
	return userId, nil
}

// admin returns a admin mdl.User object with respect to the
// userId passed as param.
func (rc requestContext) admin(userId int64) (*mdl.User, error) {

	a, err := mdl.UserById(rc.c, userId)
	log.Infof(rc.c, "%s User: %v", rc.desc, a)
	if err != nil {
		log.Errorf(rc.c, "%s user not found", rc.desc)
		return nil, &helpers.NotFound{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}
	return a, nil
}

// AddAdmin let you add an admin to a tournament.
//	GET	/j/tournaments/[0-9]+/admin/add/
//
func AddAdmin(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament add admin Handler:"

	rc := requestContext{c, desc, r}

	var tournament *mdl.Tournament
	var err error

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	var userId int64
	if userId, err = rc.userId(); err != nil {
		return err
	}

	var newAdmin *mdl.User
	if newAdmin, err = rc.admin(userId); err != nil {
		return err
	}

	// add admin to tournament
	if err = tournament.AddAdmin(c, newAdmin.Id); err != nil {
		log.Errorf(c, "%s error on AddAdmin to tournament: %v", desc, err)
		return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeInternal)}
	}

	// send response
	var tJson mdl.TournamentJson
	fieldsToKeep := []string{"Id", "Name", "AdminIds", "Private"}
	helpers.InitPointerStructure(tournament, &tJson, fieldsToKeep)

	msg := fmt.Sprintf("You added %s as admin of tournament %s.", newAdmin.Name, tournament.Name)
	data := struct {
		MessageInfo string `json:",omitempty"`
		Tournament  mdl.TournamentJson
	}{
		msg,
		tJson,
	}

	return templateshlp.RenderJson(w, c, data)
}

// RemoveAdmin handler lets you remove an admin from a tournament.
//
// Use this handler to remove a user as admin of the current tournament.
//	GET	/j/tournaments/[0-9]+/admin/remove/
//
func RemoveAdmin(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament remove admin Handler:"

	rc := requestContext{c, desc, r}

	var tournament *mdl.Tournament
	var err error

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	var userId int64
	if userId, err = rc.userId(); err != nil {
		return err
	}

	var oldAdmin *mdl.User
	if oldAdmin, err = rc.admin(userId); err != nil {
		return err
	}

	if err = tournament.RemoveAdmin(c, oldAdmin.Id); err != nil {
		log.Errorf(c, "%s error on RemoveAdmin to tournament: %v.", desc, err)
		return &helpers.InternalServerError{Err: err}
	}

	var tJson mdl.TournamentJson
	fieldsToKeep := []string{"Id", "Name", "AdminIds", "Private"}
	helpers.InitPointerStructure(tournament, &tJson, fieldsToKeep)

	msg := fmt.Sprintf("You removed %s as admin of tournament %s.", oldAdmin.Name, tournament.Name)
	data := struct {
		MessageInfo string `json:",omitempty"`
		Tournament  mdl.TournamentJson
	}{
		msg,
		tJson,
	}
	return templateshlp.RenderJson(w, c, data)

}

// SyncScores handler lets you syncronize scores in tournament.
//
// Use this handler to run taks to sync scores of all users in tournament.
//	GET	/j/tournaments/[0-9]+/admin/syncscores/
//
func SyncScores(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament sync scores Handler:"
	log.Infof(c, "%v", desc)

	rc := requestContext{c, desc, r}

	var err error
	var tournament *mdl.Tournament

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	// prepare data to add task to queue.
	b1, errm := json.Marshal(tournament)
	if errm != nil {
		log.Errorf(c, "%s Error marshaling", desc, errm)
	}

	task := taskqueue.NewPOSTTask("/a/sync/scores/", url.Values{
		"tournament": []string{string(b1)},
	})

	if _, err = taskqueue.Add(c, task, "gw-queue"); err != nil {
		log.Errorf(c, "%s unable to add task to taskqueue.", desc)
		return err
	} else {
		log.Infof(c, "%s add task to taskqueue successfully", desc)
	}

	msg := fmt.Sprintf("You send task to synch scores for all users.")
	data := struct {
		MessageInfo string `json:",omitempty"`
	}{
		msg,
	}

	return templateshlp.RenderJson(w, c, data)

}

// ActivatePhase handler let you  activate phase of tournament.
//
// Use this handler to activate all the matches of given phase in tournament.
//	GET	/j/tournaments/[0-9]+/admin/activatephase/
//
func ActivatePhase(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament activate phase handler:"
	log.Infof(c, "%v", desc)

	rc := requestContext{c, desc, r}

	var err error
	var tournament *mdl.Tournament

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	phaseName := r.FormValue("phaseName")

	matches := mdl.GetMatchesByPhase(c, tournament, phaseName)

	for _, match := range matches {
		match.Ready = true
	}

	return mdl.UpdateMatches(c, matches)

}
<commit_msg>clean spaces<commit_after>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"

	"appengine"
	"appengine/taskqueue"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

	mdl "github.com/santiaago/gonawin/models"
)

// requestContext type holds the information needed read the request and log any errors.
type requestContext struct {
	c    appengine.Context // appengine context
	desc string            // handler description
	r    *http.Request     // the HTTP request
}

// tournament returns a tournament instance.
// It gets the 'tournamentId' from the request and queries the datastore to get
// the tournament.
func (rc requestContext) tournament() (*mdl.Tournament, error) {

	strTournamentId, err := route.Context.Get(rc.r, "tournamentId")
	if err != nil {
		log.Errorf(rc.c, "%s error getting tournament id, err:%v", rc.desc, err)
		return nil, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var tournamentId int64
	tournamentId, err = strconv.ParseInt(strTournamentId, 0, 64)
	if err != nil {
		log.Errorf(rc.c, "%s error converting tournament id from string to int64, err:%v", rc.desc, err)
		return nil, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var tournament *mdl.Tournament
	if tournament, err = mdl.TournamentById(rc.c, tournamentId); err != nil {
		log.Errorf(rc.c, "%s tournament not found: %v", rc.desc, err)
		return nil, &helpers.NotFound{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}
	return tournament, nil
}

// userId returns a userId.
// It gets the 'userId' from the request and parses it to int64
func (rc requestContext) userId() (int64, error) {

	strUserId, err := route.Context.Get(rc.r, "userId")
	if err != nil {
		log.Errorf(rc.c, "%s error getting user id, err:%v", rc.desc, err)
		return 0, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}

	var userId int64
	userId, err = strconv.ParseInt(strUserId, 0, 64)
	if err != nil {
		log.Errorf(rc.c, "%s error converting user id from string to int64, err:%v", rc.desc, err)
		return 0, &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}
	return userId, nil
}

// admin returns a admin mdl.User object with respect to the
// userId passed as param.
func (rc requestContext) admin(userId int64) (*mdl.User, error) {

	a, err := mdl.UserById(rc.c, userId)
	log.Infof(rc.c, "%s User: %v", rc.desc, a)
	if err != nil {
		log.Errorf(rc.c, "%s user not found", rc.desc)
		return nil, &helpers.NotFound{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}
	return a, nil
}

// AddAdmin let you add an admin to a tournament.
//	GET	/j/tournaments/[0-9]+/admin/add/
//
func AddAdmin(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament add admin Handler:"

	rc := requestContext{c, desc, r}

	var tournament *mdl.Tournament
	var err error

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	var userId int64
	if userId, err = rc.userId(); err != nil {
		return err
	}

	var newAdmin *mdl.User
	if newAdmin, err = rc.admin(userId); err != nil {
		return err
	}

	// add admin to tournament
	if err = tournament.AddAdmin(c, newAdmin.Id); err != nil {
		log.Errorf(c, "%s error on AddAdmin to tournament: %v", desc, err)
		return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeInternal)}
	}

	// send response
	var tJson mdl.TournamentJson
	fieldsToKeep := []string{"Id", "Name", "AdminIds", "Private"}
	helpers.InitPointerStructure(tournament, &tJson, fieldsToKeep)

	msg := fmt.Sprintf("You added %s as admin of tournament %s.", newAdmin.Name, tournament.Name)
	data := struct {
		MessageInfo string `json:",omitempty"`
		Tournament  mdl.TournamentJson
	}{
		msg,
		tJson,
	}

	return templateshlp.RenderJson(w, c, data)
}

// RemoveAdmin handler lets you remove an admin from a tournament.
//
// Use this handler to remove a user as admin of the current tournament.
//	GET	/j/tournaments/[0-9]+/admin/remove/
//
func RemoveAdmin(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament remove admin Handler:"

	rc := requestContext{c, desc, r}

	var tournament *mdl.Tournament
	var err error

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	var userId int64
	if userId, err = rc.userId(); err != nil {
		return err
	}

	var oldAdmin *mdl.User
	if oldAdmin, err = rc.admin(userId); err != nil {
		return err
	}

	if err = tournament.RemoveAdmin(c, oldAdmin.Id); err != nil {
		log.Errorf(c, "%s error on RemoveAdmin to tournament: %v.", desc, err)
		return &helpers.InternalServerError{Err: err}
	}

	var tJson mdl.TournamentJson
	fieldsToKeep := []string{"Id", "Name", "AdminIds", "Private"}
	helpers.InitPointerStructure(tournament, &tJson, fieldsToKeep)

	msg := fmt.Sprintf("You removed %s as admin of tournament %s.", oldAdmin.Name, tournament.Name)
	data := struct {
		MessageInfo string `json:",omitempty"`
		Tournament  mdl.TournamentJson
	}{
		msg,
		tJson,
	}
	return templateshlp.RenderJson(w, c, data)
}

// SyncScores handler lets you syncronize scores in tournament.
//
// Use this handler to run taks to sync scores of all users in tournament.
//	GET	/j/tournaments/[0-9]+/admin/syncscores/
//
func SyncScores(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament sync scores Handler:"
	log.Infof(c, "%v", desc)

	rc := requestContext{c, desc, r}

	var err error
	var tournament *mdl.Tournament

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	// prepare data to add task to queue.
	b1, errm := json.Marshal(tournament)
	if errm != nil {
		log.Errorf(c, "%s Error marshaling", desc, errm)
	}

	task := taskqueue.NewPOSTTask("/a/sync/scores/", url.Values{
		"tournament": []string{string(b1)},
	})

	if _, err = taskqueue.Add(c, task, "gw-queue"); err != nil {
		log.Errorf(c, "%s unable to add task to taskqueue.", desc)
		return err
	} else {
		log.Infof(c, "%s add task to taskqueue successfully", desc)
	}

	msg := fmt.Sprintf("You send task to synch scores for all users.")
	data := struct {
		MessageInfo string `json:",omitempty"`
	}{
		msg,
	}

	return templateshlp.RenderJson(w, c, data)
}

// ActivatePhase handler let you  activate phase of tournament.
//
// Use this handler to activate all the matches of given phase in tournament.
//	GET	/j/tournaments/[0-9]+/admin/activatephase/
//
func ActivatePhase(w http.ResponseWriter, r *http.Request, u *mdl.User) error {

	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament activate phase handler:"
	log.Infof(c, "%v", desc)

	rc := requestContext{c, desc, r}

	var err error
	var tournament *mdl.Tournament

	if tournament, err = rc.tournament(); err != nil {
		return err
	}

	phaseName := r.FormValue("phaseName")

	matches := mdl.GetMatchesByPhase(c, tournament, phaseName)

	for _, match := range matches {
		match.Ready = true
	}

	return mdl.UpdateMatches(c, matches)
}
<|endoftext|>


<commit_before>package gateway

import (
	"io"
	"net/http"
	"strconv"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/cmd/kateway/manager"
	"github.com/funkygao/gafka/cmd/kateway/store"
	"github.com/funkygao/gafka/sla"
	"github.com/funkygao/httprouter"
	log "github.com/funkygao/log4go"
)

// PUT /v1/bury/:appid/:topic/:ver?group=xx&q=yy
func (this *subServer) buryHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	var (
		topic      string
		ver        string
		myAppid    string
		hisAppid   string
		group      string
		rawTopic   string
		shadow     string
		bury       string
		partition  string
		partitionN int = -1
		offset     string
		offsetN    int64 = -1
		err        error
	)

	query := r.URL.Query()
	group = query.Get("group")
	if !manager.Default.ValidateGroupName(r.Header, group) {
		writeBadRequest(w, "illegal group")
		return
	}

	ver = params.ByName(UrlParamVersion)
	topic = params.ByName(UrlParamTopic)
	hisAppid = params.ByName(UrlParamAppid)
	myAppid = r.Header.Get(HttpHeaderAppid)
	realIp := getHttpRemoteIp(r)

	bury = r.Header.Get(HttpHeaderMsgBury)
	if !sla.ValidateShadowName(bury) {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal bury: %s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), bury)

		writeBadRequest(w, "illegal bury")
		return
	}

	// auth
	if err = manager.Default.AuthSub(myAppid, r.Header.Get(HttpHeaderSubkey),
		hisAppid, topic, group); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeAuthFailure(w, err)
		return
	}

	partition = r.Header.Get(HttpHeaderPartition)
	offset = r.Header.Get(HttpHeaderOffset)
	if partition == "" || offset == "" {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} empty offset or partition",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"))

		writeBadRequest(w, "empty offset or partition")
		return
	}

	offsetN, err = strconv.ParseInt(offset, 10, 64)
	if err != nil || offsetN < 0 {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal offset:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), offset)

		writeBadRequest(w, "bad offset")
		return
	}
	partitionN, err = strconv.Atoi(partition)
	if err != nil || partitionN < 0 {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal partition:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), partition)

		writeBadRequest(w, "bad partition")
		return
	}

	shadow = query.Get("q")

	log.Debug("bury[%s] %s(%s): {app:%s bury:%s shadow=%s topic:%s ver:%s group:%s partition:%s offset:%s UA:%s}",
		myAppid, r.RemoteAddr, realIp, hisAppid, bury, shadow, topic, ver,
		partition, offset, r.Header.Get("User-Agent"))

	msgLen := int(r.ContentLength)
	msg := make([]byte, 0, msgLen)
	if _, err = io.ReadAtLeast(r.Body, msg, msgLen); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeBadRequest(w, err.Error())
		return
	}

	cluster, found := manager.Default.LookupCluster(hisAppid)
	if !found {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} invalid appid:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), hisAppid)

		writeBadRequest(w, "invalid appid")
		return
	}

	// calculate raw topic according to shadow
	if shadow != "" {
		if !sla.ValidateShadowName(shadow) {
			log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s q:%s UA:%s} invalid shadow name",
				myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
				group, shadow, r.Header.Get("User-Agent"))

			writeBadRequest(w, "invalid shadow name")
			return
		}

		if !manager.Default.IsShadowedTopic(hisAppid, topic, ver, myAppid, group) {
			log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s q:%s UA:%s} not a shadowed topic",
				myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
				group, shadow, r.Header.Get("User-Agent"))

			writeBadRequest(w, "register shadow first")
			return
		}

		rawTopic = manager.Default.ShadowTopic(shadow, myAppid, hisAppid, topic, ver, group)
	} else {
		rawTopic = manager.Default.KafkaTopic(hisAppid, topic, ver)
	}

	fetcher, err := store.DefaultSubStore.Fetch(cluster, rawTopic,
		myAppid+"."+group, r.RemoteAddr, realIp, "", Options.PermitStandbySub)
	if err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeBadRequest(w, err.Error())
		return
	}

	// step1: pub
	shadowTopic := manager.Default.ShadowTopic(bury, myAppid, hisAppid, topic, ver, group)
	_, _, err = store.DefaultPubStore.SyncPub(cluster, shadowTopic, nil, msg)
	if err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver, group, err)

		writeServerError(w, err.Error())
		return
	}

	// step2: skip this message in the master topic TODO atomic with step1
	if err = fetcher.CommitUpto(&sarama.ConsumerMessage{
		Topic:     rawTopic, // FIXME it's wrong!!!
		Partition: int32(partitionN),
		Offset:    offsetN,
	}); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver, group, err)

		writeServerError(w, err.Error())
		return
	}

	w.Write(ResponseOk)
}
<commit_msg>WIP on shadow<commit_after>package gateway

import (
	"io"
	"net/http"
	"strconv"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/cmd/kateway/manager"
	"github.com/funkygao/gafka/cmd/kateway/store"
	"github.com/funkygao/gafka/sla"
	"github.com/funkygao/httprouter"
	log "github.com/funkygao/log4go"
)

// PUT /v1/bury/:appid/:topic/:ver?group=xx&q=<dead|retry>
// FIXME X-Bury and param q is duplicated
func (this *subServer) buryHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	var (
		topic      string
		ver        string
		myAppid    string
		hisAppid   string
		group      string
		rawTopic   string
		shadow     string
		bury       string
		partition  string
		partitionN int = -1
		offset     string
		offsetN    int64 = -1
		err        error
	)

	query := r.URL.Query()
	group = query.Get("group")
	if !manager.Default.ValidateGroupName(r.Header, group) {
		writeBadRequest(w, "illegal group")
		return
	}

	ver = params.ByName(UrlParamVersion)
	topic = params.ByName(UrlParamTopic)
	hisAppid = params.ByName(UrlParamAppid)
	myAppid = r.Header.Get(HttpHeaderAppid)
	realIp := getHttpRemoteIp(r)

	bury = r.Header.Get(HttpHeaderMsgBury)
	if !sla.ValidateShadowName(bury) {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal bury: %s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), bury)

		writeBadRequest(w, "illegal bury")
		return
	}

	// auth
	if err = manager.Default.AuthSub(myAppid, r.Header.Get(HttpHeaderSubkey),
		hisAppid, topic, group); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeAuthFailure(w, err)
		return
	}

	partition = r.Header.Get(HttpHeaderPartition)
	offset = r.Header.Get(HttpHeaderOffset)
	if partition == "" || offset == "" {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} empty offset or partition",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"))

		writeBadRequest(w, "empty offset or partition")
		return
	}

	offsetN, err = strconv.ParseInt(offset, 10, 64)
	if err != nil || offsetN < 0 {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal offset:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), offset)

		writeBadRequest(w, "bad offset")
		return
	}
	partitionN, err = strconv.Atoi(partition)
	if err != nil || partitionN < 0 {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} illegal partition:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), partition)

		writeBadRequest(w, "bad partition")
		return
	}

	shadow = query.Get("q")

	log.Debug("bury[%s] %s(%s): {app:%s bury:%s shadow=%s topic:%s ver:%s group:%s partition:%s offset:%s UA:%s}",
		myAppid, r.RemoteAddr, realIp, hisAppid, bury, shadow, topic, ver, group,
		partition, offset, r.Header.Get("User-Agent"))

	msgLen := int(r.ContentLength)
	msg := make([]byte, msgLen)
	if _, err = io.ReadAtLeast(r.Body, msg, msgLen); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeBadRequest(w, err.Error())
		return
	}

	cluster, found := manager.Default.LookupCluster(hisAppid)
	if !found {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} invalid appid:%s",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), hisAppid)

		writeBadRequest(w, "invalid appid")
		return
	}

	// calculate raw topic according to shadow
	if shadow != "" {
		if !sla.ValidateShadowName(shadow) {
			log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s q:%s UA:%s} invalid shadow name",
				myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
				group, shadow, r.Header.Get("User-Agent"))

			writeBadRequest(w, "invalid shadow name")
			return
		}

		if !manager.Default.IsShadowedTopic(hisAppid, topic, ver, myAppid, group) {
			log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s q:%s UA:%s} not a shadowed topic",
				myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
				group, shadow, r.Header.Get("User-Agent"))

			writeBadRequest(w, "register shadow first")
			return
		}

		rawTopic = manager.Default.ShadowTopic(shadow, myAppid, hisAppid, topic, ver, group)
	} else {
		rawTopic = manager.Default.KafkaTopic(hisAppid, topic, ver)
	}

	fetcher, err := store.DefaultSubStore.Fetch(cluster, rawTopic,
		myAppid+"."+group, r.RemoteAddr, realIp, "", Options.PermitStandbySub)
	if err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s UA:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver,
			group, r.Header.Get("User-Agent"), err)

		writeBadRequest(w, err.Error())
		return
	}

	// step1: pub
	shadowTopic := manager.Default.ShadowTopic(bury, myAppid, hisAppid, topic, ver, group)
	_, _, err = store.DefaultPubStore.SyncPub(cluster, shadowTopic, nil, msg)
	if err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver, group, err)

		writeServerError(w, err.Error())
		return
	}

	// step2: skip this message in the master topic TODO atomic with step1
	if err = fetcher.CommitUpto(&sarama.ConsumerMessage{
		Topic:     rawTopic, // FIXME it's wrong!!!
		Partition: int32(partitionN),
		Offset:    offsetN,
	}); err != nil {
		log.Error("bury[%s] %s(%s): {app:%s topic:%s ver:%s group:%s} %v",
			myAppid, r.RemoteAddr, realIp, hisAppid, topic, ver, group, err)

		writeServerError(w, err.Error())
		return
	}

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


<commit_before>package collectors

import (
	"fmt"
	"math/big"
	"time"

	"bosun.org/metadata"
	"bosun.org/opentsdb"
)

const (
	ciscoCPU     = ".1.3.6.1.4.1.9.9.109.1.1.1.1.6"
	ciscoMemFree = ".1.3.6.1.4.1.9.9.48.1.1.1.6"
	ciscoMemName = ".1.3.6.1.4.1.9.9.48.1.1.1.2"
	ciscoMemUsed = ".1.3.6.1.4.1.9.9.48.1.1.1.5"
)

// SNMPCisco registers a SNMP CISCO collector for the given community and host.
func SNMPCisco(community, host string) {
	collectors = append(collectors, &IntervalCollector{
		F: func() (opentsdb.MultiDataPoint, error) {
			return c_snmp_cisco(community, host)
		},
		Interval: time.Second * 30,
		name:     fmt.Sprintf("snmp-cisco-%s", host),
	})
}

func c_snmp_cisco(community, host string) (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	var v *big.Int
	var err error
	if v, err = snmp_oid(host, community, ciscoCPU); err == nil {
	} else if v, err = snmp_oid(host, community, ciscoCPU+".1"); err == nil {
	} else {
		return nil, err
	}
	Add(&md, "cisco.cpu", v.String(), opentsdb.TagSet{"host": host}, metadata.Gauge, metadata.Pct, "The overall CPU busy percentage in the last five-second period.")
	names, err := snmp_subtree(host, community, ciscoMemName)
	if err != nil {
		return nil, err
	}
	used, err := snmp_subtree(host, community, ciscoMemUsed)
	if err != nil {
		return nil, err
	}
	free, err := snmp_subtree(host, community, ciscoMemFree)
	if err != nil {
		return nil, err
	}
	for id, name := range names {
		n := fmt.Sprintf("%s", name)
		u, present := used[id]
		if !present {
			continue
		}
		f, present := free[id]
		if !present {
			continue
		}
		Add(&md, "cisco.mem.used", u, opentsdb.TagSet{"host": host, "name": n}, metadata.Unknown, metadata.None, "")
		Add(&md, "cisco.mem.free", f, opentsdb.TagSet{"host": host, "name": n}, metadata.Unknown, metadata.None, "")
	}
	return md, nil
}
<commit_msg>Duplicating cisco.cpu to os.cpu<commit_after>package collectors

import (
	"fmt"
	"math/big"
	"time"

	"bosun.org/metadata"
	"bosun.org/opentsdb"
)

const (
	ciscoCPU     = ".1.3.6.1.4.1.9.9.109.1.1.1.1.6"
	ciscoMemFree = ".1.3.6.1.4.1.9.9.48.1.1.1.6"
	ciscoMemName = ".1.3.6.1.4.1.9.9.48.1.1.1.2"
	ciscoMemUsed = ".1.3.6.1.4.1.9.9.48.1.1.1.5"
)

// SNMPCisco registers a SNMP CISCO collector for the given community and host.
func SNMPCisco(community, host string) {
	collectors = append(collectors, &IntervalCollector{
		F: func() (opentsdb.MultiDataPoint, error) {
			return c_snmp_cisco(community, host)
		},
		Interval: time.Second * 30,
		name:     fmt.Sprintf("snmp-cisco-%s", host),
	})
}

func c_snmp_cisco(community, host string) (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	var v *big.Int
	var err error
	if v, err = snmp_oid(host, community, ciscoCPU); err == nil {
	} else if v, err = snmp_oid(host, community, ciscoCPU+".1"); err == nil {
	} else {
		return nil, err
	}
	Add(&md, "cisco.cpu", v.String(), opentsdb.TagSet{"host": host}, metadata.Gauge, metadata.Pct, "The overall CPU busy percentage in the last five-second period.")
	Add(&md, osCPU, v.String(), opentsdb.TagSet{"host": host}, metadata.Gauge, metadata.Pct, "")
	names, err := snmp_subtree(host, community, ciscoMemName)
	if err != nil {
		return nil, err
	}
	used, err := snmp_subtree(host, community, ciscoMemUsed)
	if err != nil {
		return nil, err
	}
	free, err := snmp_subtree(host, community, ciscoMemFree)
	if err != nil {
		return nil, err
	}
	for id, name := range names {
		n := fmt.Sprintf("%s", name)
		u, present := used[id]
		if !present {
			continue
		}
		f, present := free[id]
		if !present {
			continue
		}
		Add(&md, "cisco.mem.used", u, opentsdb.TagSet{"host": host, "name": n}, metadata.Unknown, metadata.None, "")
		Add(&md, "cisco.mem.free", f, opentsdb.TagSet{"host": host, "name": n}, metadata.Unknown, metadata.None, "")
	}
	return md, nil
}
<|endoftext|>


<commit_before>package down

import (
	"fmt"
)

type Noder interface {
	String() string
}

type Node struct{}

func (n Node) String() string {
	return ""
}

type LineNode struct {
	Child Noder
}

func (ln LineNode) String() string {
	return ln.Child.String() + "\n"
}

type CompositeStringNode struct {
	children []Noder
}

func (csn CompositeStringNode) String() string {
	var content string
	for _, node := range csn.children {
		content += node.String()
	}

	return content
}

func (csn *CompositeStringNode) AddChild(n Noder) {
	csn.children = append(csn.children, n)
}

type RawTextNode struct {
	Content string
}

func (rtn RawTextNode) String() string {
	return rtn.Content
}

type LinkNode struct {
	Text Noder
	Addr Noder
}

func (ln LinkNode) String() string {
	return fmt.Sprintf("%v", ln.Addr.String(), ln.Text.String())
}

type BoldStringNode struct {
	Child CompositeStringNode
}

func (bsn BoldStringNode) String() string {
	return "" + bsn.Child.String() + ""
}

type ItalicNode struct {
	Child CompositeStringNode
}

func (in ItalicNode) String() string {
	return "" + in.Child.String() + ""
}

type HeaderOneNode struct {
	Child RawTextNode
}

func (hon HeaderOneNode) String() string {
	return fmt.Sprintf("
%v
", hon.Child.String())
}

type HeaderNode struct {
	Child RawTextNode
	Level int
}

func (hn HeaderNode) String() string {
	return fmt.Sprintf("<h%[1]v>%[2]v</h%[1]v>", hn.Level, hn.Child.String())
	// return fmt.Sprintf("%[2] %[1]", ln., 22)
}

type ParagraphNode struct {
	Child CompositeStringNode
}

func (pn ParagraphNode) String() string {
	return fmt.Sprintf("
%v
", pn.Child.String())
}
<commit_msg>nodes: add documentation describing each nodes purpose.<commit_after>package down

import (
	"fmt"
)

// Noder is the interface used to describe a down Node that will be converted to html.
type Noder interface {
	String() string
}

// Node is a basic Node to show how Nodes should be constructed.
type Node struct{}

func (n Node) String() string {
	return ""
}

// LineNode describes a line of markdown.
type LineNode struct {
	Child Noder
}

func (ln LineNode) String() string {
	return ln.Child.String() + "\n"
}

// CompositeStringNode describes a string which can contain any number of RawTextNodes, ItalicNodes,
// BoldNodes and LinkNodes.
type CompositeStringNode struct {
	children []Noder
}

func (csn CompositeStringNode) String() string {
	var content string
	for _, node := range csn.children {
		content += node.String()
	}

	return content
}

// Add a node to a composite Node
func (csn *CompositeStringNode) AddChild(n Noder) {
	csn.children = append(csn.children, n)
}

// RawTextNode is a node that represents bare text.
type RawTextNode struct {
	Content string
}

func (rtn RawTextNode) String() string {
	return rtn.Content
}

// LinkNode is a node that represents a html link.
type LinkNode struct {
	Text Noder
	Addr Noder
}

func (ln LinkNode) String() string {
	return fmt.Sprintf("%v", ln.Addr.String(), ln.Text.String())
}

// BoldStringNode is a node to represent bold text.
type BoldStringNode struct {
	Child CompositeStringNode
}

func (bsn BoldStringNode) String() string {
	return "" + bsn.Child.String() + ""
}

// ItalicStringNode is a node to represent italic text.
type ItalicNode struct {
	Child CompositeStringNode
}

func (in ItalicNode) String() string {
	return "" + in.Child.String() + ""
}

// HeaderNode is a node that can represent any html header tag (h[1...6])
type HeaderNode struct {
	Child RawTextNode
	Level int
}

func (hn HeaderNode) String() string {
	return fmt.Sprintf("<h%[1]v>%[2]v</h%[1]v>", hn.Level, hn.Child.String())
	// return fmt.Sprintf("%[2] %[1]", ln., 22)
}

// ParahraphNode is a node to represent a paragraph of raw, links, bold and italic text.
type ParagraphNode struct {
	Child CompositeStringNode
}

func (pn ParagraphNode) String() string {
	return fmt.Sprintf("
%v
", pn.Child.String())
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/bjwbell/renfish/auth"
	"github.com/bjwbell/renfish/conf"
	"github.com/bjwbell/renfish/db"
	"github.com/bjwbell/renfish/submit"
	"github.com/bjwbell/renroll/src/renroll"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("indexhandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("idx.html", "templates/header.html", "templates/topbar.html", "templates/bottombar.html")
	if e != nil {
		panic(e)
	}
	log.Print("indexhandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func robotsHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("robothandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("robots.txt")
	if e != nil {
		panic(e)
	}
	log.Print("robothandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func googleAdwordsVerifyHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("adwordsVerifyHandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("google41fd03a6c9348593.html")
	if e != nil {
		panic(e)
	}
	log.Print("adwordsVerifyHandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func aboutHandler(w http.ResponseWriter, r *http.Request) {
	about := struct{ Conf conf.Configuration }{conf.Config()}
	t, _ := template.ParseFiles(
		"about.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	t.Execute(w, about)
}

func unreleasedHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct{ Conf renroll.Configuration }{renroll.Config()}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	t, _ := template.ParseFiles(
		"unreleased.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	t.Execute(w, conf)
}

func getNextIP() string {
	ips := db.DbGetIPs(db.DbName)
	return db.DbGetNextAvailableIP(ips)
}

func createSite(emailAddress, siteName string) {
	// Add nginx conf file
	nginxConf := `server {
     listen 443 ssl;
    listen [::]:443 ssl;
    server_name  <site-name>;
    ssl_certificate     /etc/letsencrypt/live/renfish.com/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/renfish.com/privkey.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    location / {
             proxy_pass https://<ip-address>;
            proxy_set_header Host $host;
    }
}
server {
    listen              80;
    server_name  <site-name>;
    location / {
            proxy_pass http://<ip-address>;
             proxy_set_header Host $host;
    }
}
`
	ipAddr := getNextIP()
	nginxConf = strings.Replace(nginxConf, "<site-name>", siteName+"."+"renfish.com", -1)
	nginxConf = strings.Replace(nginxConf, "<ip-address>", ipAddr, -1)
	fileName := "/etc/nginx/sites-available/" + siteName + "." + "renfish.com"
	if err := ioutil.WriteFile(fileName, []byte(nginxConf), 0644); err != nil {
		auth.LogError(fmt.Sprintf("ERROR WRITING NGINX CONF FILE, sitename: %v, filename: %v, err: %v", siteName, fileName, err))
		return
	}
	// Link nginx conf file to sites-enabled/
	symlink := "/etc/nginx/sites-enabled/" + siteName + "." + "renfish.com"
	if err := os.Symlink(fileName, symlink); err != nil {
		auth.LogError(fmt.Sprintf("ERROR CREATING NGINX CONF FILE SYMLINK, sitename: %v, filename: %v, symlink: %v, err: %v", siteName, fileName, symlink, err))
		return
	}
	// Reload nginx conf
	cmd := exec.Command("nginx", "-s", "reload")
	var out bytes.Buffer
	cmd.Stdout = &out
	if err := cmd.Run(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR RELOADING NGINX CONF, err: %v", err))
		log.Fatal(err)
	}
	// start Gophish container
	cmd = exec.Command("docker", "run", "--net", "gophish", "--ip", ipAddr, "bjwbell/gophish-container", "/gophish/gophish")
	var out2 bytes.Buffer
	cmd.Stdout = &out2
	if err := cmd.Run(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR STARTING GOPHISH CONTAINER, err: %v", err))
		log.Fatal(err)
	}
	// Save details to database
	if _, success := db.SaveSite(emailAddress, siteName, ipAddr); !success {
		auth.LogError(fmt.Sprintf("ERROR SAVING SITE TO DB email (%s), sitename (%s), ip (%s)",
			emailAddress, siteName, ipAddr))
		log.Fatal(nil)
	}
	return
}

func createsiteHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct {
		Conf     renroll.Configuration
		Email    string
		SiteName string
	}{renroll.Config(), "", ""}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	if err := r.ParseForm(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR PARSEFORM, ERR: %v", err))
		t, _ := template.ParseFiles(
			"setuperror.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	}
	email := r.Form.Get("email")
	siteName := r.Form.Get("sitename")
	conf.Email = email
	conf.SiteName = "https://" + siteName + "." + r.Host
	if email == "" || siteName == "" {
		auth.LogError(fmt.Sprintf("MiSSING EMAIL or SITENAME, email: %v, sitename: %v", email, siteName))
		t, _ := template.ParseFiles(
			"setuperror.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	} else {
		createSite(email, siteName)
		t, _ := template.ParseFiles(
			"setup.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	}
}

func settingsHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct{ Conf conf.Configuration }{conf.Config()}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	t, _ := template.ParseFiles(
		"settings.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	if err := t.Execute(w, conf); err != nil {
		auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
	}
}

func redir(w http.ResponseWriter, req *http.Request) {
	host := req.Host
	httpsPort := "443"
	if strings.Index(host, ":8080") != -1 {
		httpsPort = "8443"
	}
	host = strings.TrimSuffix(host, ":8080")
	host = strings.TrimSuffix(host, ":80")
	if httpsPort == "443" {
		http.Redirect(w, req, "https://"+host+req.RequestURI, http.StatusMovedPermanently)
	} else {
		http.Redirect(w, req, "https://"+host+":"+httpsPort+req.RequestURI, http.StatusMovedPermanently)
	}
}

func main() {
	http.HandleFunc("/about", aboutHandler)
	http.HandleFunc("/auth/getemail", auth.GetGPlusEmailHandler)
	http.HandleFunc("/createaccount", auth.CreateAccountHandler)
	http.HandleFunc("/index", indexHandler)
	http.HandleFunc("/logerror", auth.LogErrorHandler)
	http.HandleFunc("/oauth2callback", auth.Oauth2callback)
	http.HandleFunc("/settings", settingsHandler)
	http.HandleFunc("/signinform", auth.SigninFormHandler)
	http.HandleFunc("/submit", submit.SubmitHandler)
	http.HandleFunc("/unreleased", unreleasedHandler)
	http.HandleFunc("/createsite", createsiteHandler)

	http.HandleFunc("/index.html", indexHandler)
	http.HandleFunc("/robots.txt", robotsHandler)
	http.HandleFunc("/google41fd03a6c9348593.html", googleAdwordsVerifyHandler)

	http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css"))))
	http.Handle("/font-awesome-4.7.0/", http.StripPrefix("/font-awesome-4.7.0/", http.FileServer(http.Dir("./font-awesome-4.7.0"))))
	http.Handle("/fonts/", http.StripPrefix("/fonts/", http.FileServer(http.Dir("./fonts"))))
	http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("./images"))))
	http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./js"))))
	http.Handle("/screenshots/", http.StripPrefix("/screenshots/", http.FileServer(http.Dir("./screenshots"))))
	http.HandleFunc("/", indexHandler)

	// HTTP to HTTPS redirection
	// go func() {
	// 	err := http.ListenAndServe(":80", http.HandlerFunc(redir))
	// 	if err != nil {
	// 		log.Print("HTTP ListenAndServe :8080", err)
	// 		log.Print("Trying HTTP ListenAndServe :8080.")
	// 		panic(http.ListenAndServe(":8080", http.HandlerFunc(redir)))

	// 	}
	// }()

	if !db.Exists(db.DbName) {
		db.Create(db.DbName)
	}

	go func() {
		err := http.ListenAndServe(":80", nil)
		if err != nil {
			log.Print("HTTP ListenAndServe :80, ", err)
			log.Print("Trying HTTP ListenAndServe :8080.")
			if err != nil {
				panic(http.ListenAndServe(":8080", nil))
			}

		}
	}()

	cert := "/etc/letsencrypt/live/renfish.com/cert.pem"
	privkey := "/etc/letsencrypt/live/renfish.com/privkey.pem"
	if _, err := os.Stat(cert); os.IsNotExist(err) {
		log.Print("cert: ", err)
		cert = "./generate_cert/cert.pem"
	}
	if _, err := os.Stat(privkey); os.IsNotExist(err) {
		log.Print("cert: ", err)
		privkey = "./generate_cert/key.pem"
	}
	err := http.ListenAndServeTLS(":443", cert, privkey, nil)
	if err != nil {
		log.Print("HTTPS ListenAndServe :8443")
		err = http.ListenAndServeTLS(":8443", cert, privkey, nil)
		if err != nil {
			log.Print("HTTPS ListenAndServe: ", err)
		}
	}
}
<commit_msg>Mount host ssl keys in docker gophish container<commit_after>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/bjwbell/renfish/auth"
	"github.com/bjwbell/renfish/conf"
	"github.com/bjwbell/renfish/db"
	"github.com/bjwbell/renfish/submit"
	"github.com/bjwbell/renroll/src/renroll"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("indexhandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("idx.html", "templates/header.html", "templates/topbar.html", "templates/bottombar.html")
	if e != nil {
		panic(e)
	}
	log.Print("indexhandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func robotsHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("robothandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("robots.txt")
	if e != nil {
		panic(e)
	}
	log.Print("robothandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func googleAdwordsVerifyHandler(w http.ResponseWriter, r *http.Request) {
	log.Print("adwordsVerifyHandler - start")
	index := struct{ Conf conf.Configuration }{conf.Config()}
	t, e := template.ParseFiles("google41fd03a6c9348593.html")
	if e != nil {
		panic(e)
	}
	log.Print("adwordsVerifyHandler - execute")
	if e = t.Execute(w, index); e != nil {
		panic(e)
	}
}

func aboutHandler(w http.ResponseWriter, r *http.Request) {
	about := struct{ Conf conf.Configuration }{conf.Config()}
	t, _ := template.ParseFiles(
		"about.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	t.Execute(w, about)
}

func unreleasedHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct{ Conf renroll.Configuration }{renroll.Config()}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	t, _ := template.ParseFiles(
		"unreleased.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	t.Execute(w, conf)
}

func getNextIP() string {
	ips := db.DbGetIPs(db.DbName)
	return db.DbGetNextAvailableIP(ips)
}

func createSite(emailAddress, siteName string) {
	// Add nginx conf file
	nginxConf := `server {
     listen 443 ssl;
    listen [::]:443 ssl;
    server_name  <site-name>;
    ssl_certificate     /etc/letsencrypt/live/renfish.com/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/renfish.com/privkey.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    location / {
             proxy_pass https://<ip-address>;
            proxy_set_header Host $host;
    }
}
server {
    listen              80;
    server_name  <site-name>;
    location / {
            proxy_pass http://<ip-address>;
             proxy_set_header Host $host;
    }
}
`
	ipAddr := getNextIP()
	nginxConf = strings.Replace(nginxConf, "<site-name>", siteName+"."+"renfish.com", -1)
	nginxConf = strings.Replace(nginxConf, "<ip-address>", ipAddr, -1)
	fileName := "/etc/nginx/sites-available/" + siteName + "." + "renfish.com"
	if err := ioutil.WriteFile(fileName, []byte(nginxConf), 0644); err != nil {
		auth.LogError(fmt.Sprintf("ERROR WRITING NGINX CONF FILE, sitename: %v, filename: %v, err: %v", siteName, fileName, err))
		return
	}
	// Link nginx conf file to sites-enabled/
	symlink := "/etc/nginx/sites-enabled/" + siteName + "." + "renfish.com"
	if err := os.Symlink(fileName, symlink); err != nil {
		auth.LogError(fmt.Sprintf("ERROR CREATING NGINX CONF FILE SYMLINK, sitename: %v, filename: %v, symlink: %v, err: %v", siteName, fileName, symlink, err))
		return
	}
	// Reload nginx conf
	cmd := exec.Command("nginx", "-s", "reload")
	var out bytes.Buffer
	cmd.Stdout = &out
	if err := cmd.Run(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR RELOADING NGINX CONF, err: %v", err))
		log.Fatal(err)
	}
	// start Gophish container
	cmd = exec.Command("docker", "run", "-v", "/etc/letsencrypt/live/renfish.com:/gophish/keys", "--net", "gophish", "--ip", ipAddr, "bjwbell/gophish-container", "/gophish/gophish")
	var out2 bytes.Buffer
	cmd.Stdout = &out2
	if err := cmd.Run(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR STARTING GOPHISH CONTAINER, err: %v", err))
		log.Fatal(err)
	}
	// Save details to database
	if _, success := db.SaveSite(emailAddress, siteName, ipAddr); !success {
		auth.LogError(fmt.Sprintf("ERROR SAVING SITE TO DB email (%s), sitename (%s), ip (%s)",
			emailAddress, siteName, ipAddr))
		log.Fatal(nil)
	}
	return
}

func createsiteHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct {
		Conf     renroll.Configuration
		Email    string
		SiteName string
	}{renroll.Config(), "", ""}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	if err := r.ParseForm(); err != nil {
		auth.LogError(fmt.Sprintf("ERROR PARSEFORM, ERR: %v", err))
		t, _ := template.ParseFiles(
			"setuperror.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	}
	email := r.Form.Get("email")
	siteName := r.Form.Get("sitename")
	conf.Email = email
	conf.SiteName = "https://" + siteName + "." + r.Host
	if email == "" || siteName == "" {
		auth.LogError(fmt.Sprintf("MiSSING EMAIL or SITENAME, email: %v, sitename: %v", email, siteName))
		t, _ := template.ParseFiles(
			"setuperror.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	} else {
		createSite(email, siteName)
		t, _ := template.ParseFiles(
			"setup.html",
			"templates/header.html",
			"templates/topbar.html",
			"templates/bottombar.html")
		if err := t.Execute(w, conf); err != nil {
			auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
		}
	}
}

func settingsHandler(w http.ResponseWriter, r *http.Request) {
	conf := struct{ Conf conf.Configuration }{conf.Config()}
	conf.Conf.GPlusSigninCallback = "gSettings"
	conf.Conf.FacebookSigninCallback = "fbSettings"
	t, _ := template.ParseFiles(
		"settings.html",
		"templates/header.html",
		"templates/topbar.html",
		"templates/bottombar.html")
	if err := t.Execute(w, conf); err != nil {
		auth.LogError(fmt.Sprintf("ERROR t.EXECUTE, ERR: %v", err))
	}
}

func redir(w http.ResponseWriter, req *http.Request) {
	host := req.Host
	httpsPort := "443"
	if strings.Index(host, ":8080") != -1 {
		httpsPort = "8443"
	}
	host = strings.TrimSuffix(host, ":8080")
	host = strings.TrimSuffix(host, ":80")
	if httpsPort == "443" {
		http.Redirect(w, req, "https://"+host+req.RequestURI, http.StatusMovedPermanently)
	} else {
		http.Redirect(w, req, "https://"+host+":"+httpsPort+req.RequestURI, http.StatusMovedPermanently)
	}
}

func main() {
	http.HandleFunc("/about", aboutHandler)
	http.HandleFunc("/auth/getemail", auth.GetGPlusEmailHandler)
	http.HandleFunc("/createaccount", auth.CreateAccountHandler)
	http.HandleFunc("/index", indexHandler)
	http.HandleFunc("/logerror", auth.LogErrorHandler)
	http.HandleFunc("/oauth2callback", auth.Oauth2callback)
	http.HandleFunc("/settings", settingsHandler)
	http.HandleFunc("/signinform", auth.SigninFormHandler)
	http.HandleFunc("/submit", submit.SubmitHandler)
	http.HandleFunc("/unreleased", unreleasedHandler)
	http.HandleFunc("/createsite", createsiteHandler)

	http.HandleFunc("/index.html", indexHandler)
	http.HandleFunc("/robots.txt", robotsHandler)
	http.HandleFunc("/google41fd03a6c9348593.html", googleAdwordsVerifyHandler)

	http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css"))))
	http.Handle("/font-awesome-4.7.0/", http.StripPrefix("/font-awesome-4.7.0/", http.FileServer(http.Dir("./font-awesome-4.7.0"))))
	http.Handle("/fonts/", http.StripPrefix("/fonts/", http.FileServer(http.Dir("./fonts"))))
	http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("./images"))))
	http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./js"))))
	http.Handle("/screenshots/", http.StripPrefix("/screenshots/", http.FileServer(http.Dir("./screenshots"))))
	http.HandleFunc("/", indexHandler)

	// HTTP to HTTPS redirection
	// go func() {
	// 	err := http.ListenAndServe(":80", http.HandlerFunc(redir))
	// 	if err != nil {
	// 		log.Print("HTTP ListenAndServe :8080", err)
	// 		log.Print("Trying HTTP ListenAndServe :8080.")
	// 		panic(http.ListenAndServe(":8080", http.HandlerFunc(redir)))

	// 	}
	// }()

	if !db.Exists(db.DbName) {
		db.Create(db.DbName)
	}

	go func() {
		err := http.ListenAndServe(":80", nil)
		if err != nil {
			log.Print("HTTP ListenAndServe :80, ", err)
			log.Print("Trying HTTP ListenAndServe :8080.")
			if err != nil {
				panic(http.ListenAndServe(":8080", nil))
			}

		}
	}()

	cert := "/etc/letsencrypt/live/renfish.com/cert.pem"
	privkey := "/etc/letsencrypt/live/renfish.com/privkey.pem"
	if _, err := os.Stat(cert); os.IsNotExist(err) {
		log.Print("cert: ", err)
		cert = "./generate_cert/cert.pem"
	}
	if _, err := os.Stat(privkey); os.IsNotExist(err) {
		log.Print("cert: ", err)
		privkey = "./generate_cert/key.pem"
	}
	err := http.ListenAndServeTLS(":443", cert, privkey, nil)
	if err != nil {
		log.Print("HTTPS ListenAndServe :8443")
		err = http.ListenAndServeTLS(":8443", cert, privkey, nil)
		if err != nil {
			log.Print("HTTPS ListenAndServe: ", err)
		}
	}
}
<|endoftext|>