<commit_before>package provider

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/digitalocean/godo"
	"github.com/gianarb/orbiter/autoscaler"
	"golang.org/x/oauth2"
)

type DigitalOceanProvider struct {
	client *godo.Client
	config map[string]string
	ctx    context.Context
}

func NewDigitalOceanProvider(c map[string]string) (autoscaler.Provider, error) {
	tokenSource := &TokenSource{
		AccessToken: c["token"],
	}
	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
	client := godo.NewClient(oauthClient)
	p := DigitalOceanProvider{
		client: client,
		config: c,
		ctx:    context.Background(),
	}
	return p, nil
}

func (p DigitalOceanProvider) Scale(serviceId string, target int, direction bool) error {
	var wg sync.WaitGroup
	responseChannel := make(chan response, target)

	if direction == true {
		for ii := 0; ii < target; ii++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				t := time.Now()
				i, _ := strconv.ParseInt(p.config["key_id"], 10, 64)
				createRequest := &godo.DropletCreateRequest{
					Name:     fmt.Sprintf("%s-%s", serviceId, t.Format("20060102150405")),
					Region:   p.config["region"],
					Size:     p.config["size"],
					UserData: p.config["userdata"],
					SSHKeys:  []godo.DropletCreateSSHKey{{ID: int(i)}},
					Image: godo.DropletCreateImage{
						Slug: p.config["image"],
					},
				}
				droplet, _, err := p.client.Droplets.Create(p.ctx, createRequest)
				responseChannel <- response{
					err:       err,
					droplet:   droplet,
					direction: true,
				}
			}()
		}
	} else {
		// TODO(gianarb): This can not work forever. We need to have proper pagination
		droplets, _, err := p.client.Droplets.List(p.ctx, &godo.ListOptions{
			Page:    1,
			PerPage: 500,
		})

		if err != nil {
			logrus.WithFields(logrus.Fields{
				"provider": "digitalocean",
				"error":    err,
			}).Warnf("Impossibile to get the list of droplets.")
			return err
		}

		ii := 0
		for _, single := range droplets {
			if p.isGoodToBeDeleted(single, serviceId) && ii < target {
				go func() {
					defer wg.Done()
					_, err := p.client.Droplets.Delete(p.ctx, single.ID)
					responseChannel <- response{
						err:       err,
						droplet:   &single,
						direction: false,
					}
				}()
				wg.Add(1)
				ii++
			}
		}

		//go func() {
		//for iii := 0; iii < target; iii++ {
		//select {
		//case err := <-errorChannel:
		//logrus.WithFields(logrus.Fields{
		//"error":    err.Error(),
		//"provider": "digitalocean",
		//}).Warnf("We was not able to delete the droplet.")
		//case droplet := <-dropletChannel:
		//logrus.WithFields(logrus.Fields{
		//"provider":    "digitalocean",
		//"dropletName": droplet.ID,
		//}).Debugf()
		//}
		//}
		//wg.Wait()
		//}()
	}
	go func() {
		var message string
		for iii := 0; iii < target; iii++ {
			r := <-responseChannel
			if r.err != nil {
				message = "We was not able to instantiate a new droplet."
				if r.direction == false {
					message = fmt.Sprintf("Impossibile to delete droplet %d ", r.droplet.ID)
				}
				logrus.WithFields(logrus.Fields{
					"error":    r.err.Error(),
					"provider": "digitalocean",
				}).Warn(message)
			} else {
				message = fmt.Sprintf("New droplet named %s with id %d created.", r.droplet.Name, r.droplet.ID)
				if r.direction == false {
					message = fmt.Sprintf("Droplet named %s with id %d deleted.", r.droplet.Name, r.droplet.ID)
				}
				logrus.WithFields(logrus.Fields{
					"provider":    "digitalocean",
					"dropletName": r.droplet.ID,
				}).Debug(message)
			}
		}
		wg.Wait()
	}()
	return nil
}

// Check if a drople is eligible to be deleted
func (p DigitalOceanProvider) isGoodToBeDeleted(droplet godo.Droplet, serviceId string) bool {
	if droplet.Status == "active" && strings.Contains(strings.ToUpper(droplet.Name), strings.ToUpper(serviceId)) {
		// TODO(gianarb): This can not work forever. We need to have proper pagination
		actions, _, _ := p.client.Droplets.Actions(p.ctx, droplet.ID, &godo.ListOptions{
			Page:    1,
			PerPage: 500,
		})
		// If there is an action in progress the droplet can not be deleted.
		for _, action := range actions {
			if action.Status == godo.ActionInProgress {
				fmt.Println(fmt.Sprintf("%d has an action in progress", droplet.ID))
				return false
			}
		}
		return true
	}
	return false
}

type TokenSource struct {
	AccessToken string
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}

type response struct {
	err       error
	droplet   *godo.Droplet
	direction bool
}
<commit_msg>remove dead code and fix if<commit_after>package provider

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/digitalocean/godo"
	"github.com/gianarb/orbiter/autoscaler"
	"golang.org/x/oauth2"
)

type DigitalOceanProvider struct {
	client *godo.Client
	config map[string]string
	ctx    context.Context
}

func NewDigitalOceanProvider(c map[string]string) (autoscaler.Provider, error) {
	tokenSource := &TokenSource{
		AccessToken: c["token"],
	}
	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
	client := godo.NewClient(oauthClient)
	p := DigitalOceanProvider{
		client: client,
		config: c,
		ctx:    context.Background(),
	}
	return p, nil
}

func (p DigitalOceanProvider) Scale(serviceId string, target int, direction bool) error {
	var wg sync.WaitGroup
	responseChannel := make(chan response, target)

	if direction == true {
		for ii := 0; ii < target; ii++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				t := time.Now()
				i, _ := strconv.ParseInt(p.config["key_id"], 10, 64)
				createRequest := &godo.DropletCreateRequest{
					Name:     fmt.Sprintf("%s-%s", serviceId, t.Format("20060102150405")),
					Region:   p.config["region"],
					Size:     p.config["size"],
					UserData: p.config["userdata"],
					SSHKeys:  []godo.DropletCreateSSHKey{{ID: int(i)}},
					Image: godo.DropletCreateImage{
						Slug: p.config["image"],
					},
				}
				droplet, _, err := p.client.Droplets.Create(p.ctx, createRequest)
				if err == nil {
					responseChannel <- response{
						err:       err,
						droplet:   droplet,
						direction: true,
					}
				}
			}()
		}
	} else {
		// TODO(gianarb): This can not work forever. We need to have proper pagination
		droplets, _, err := p.client.Droplets.List(p.ctx, &godo.ListOptions{
			Page:    1,
			PerPage: 500,
		})

		if err != nil {
			logrus.WithFields(logrus.Fields{
				"provider": "digitalocean",
				"error":    err,
			}).Warnf("Impossibile to get the list of droplets.")
			return err
		}

		ii := 0
		for _, single := range droplets {
			if p.isGoodToBeDeleted(single, serviceId) && ii < target {
				go func() {
					defer wg.Done()
					_, err := p.client.Droplets.Delete(p.ctx, single.ID)
					responseChannel <- response{
						err:       err,
						droplet:   &single,
						direction: false,
					}
				}()
				wg.Add(1)
				ii++
			}
		}
	}
	go func() {
		var message string
		for iii := 0; iii < target; iii++ {
			r := <-responseChannel
			if r.err != nil {
				message = "We was not able to instantiate a new droplet."
				if r.direction == false {
					message = fmt.Sprintf("Impossibile to delete droplet %d ", r.droplet.ID)
				}
				logrus.WithFields(logrus.Fields{
					"error":    r.err.Error(),
					"provider": "digitalocean",
				}).Warn(message)
			} else {
				message = fmt.Sprintf("New droplet named %s with id %d created.", r.droplet.Name, r.droplet.ID)
				if r.direction == false {
					message = fmt.Sprintf("Droplet named %s with id %d deleted.", r.droplet.Name, r.droplet.ID)
				}
				logrus.WithFields(logrus.Fields{
					"provider":    "digitalocean",
					"dropletName": r.droplet.ID,
				}).Debug(message)
			}
		}
		wg.Wait()
	}()
	return nil
}

// Check if a drople is eligible to be deleted
func (p DigitalOceanProvider) isGoodToBeDeleted(droplet godo.Droplet, serviceId string) bool {
	if droplet.Status == "active" && strings.Contains(strings.ToUpper(droplet.Name), strings.ToUpper(serviceId)) {
		// TODO(gianarb): This can not work forever. We need to have proper pagination
		actions, _, _ := p.client.Droplets.Actions(p.ctx, droplet.ID, &godo.ListOptions{
			Page:    1,
			PerPage: 500,
		})
		// If there is an action in progress the droplet can not be deleted.
		for _, action := range actions {
			if action.Status == godo.ActionInProgress {
				fmt.Println(fmt.Sprintf("%d has an action in progress", droplet.ID))
				return false
			}
		}
		return true
	}
	return false
}

type TokenSource struct {
	AccessToken string
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}

type response struct {
	err       error
	droplet   *godo.Droplet
	direction bool
}
<|endoftext|>


<commit_before>package giphy

import (
	"fmt"
	"net/url"

	"github.com/zquestz/s/providers"
)

func init() {
	providers.AddProvider("giphy", &Provider{})
}

// Provider merely implements the Provider interface.
type Provider struct{}

// BuildURI generates a search URL for Giphy.
func (p *Provider) BuildURI(q string) string {
	return fmt.Sprintf("https://giphy.com/search/%s", url.QueryEscape(q))
}

// Tags returns the tags relevant to this provider.
func (p *Provider) Tags() []string {
	return []string{"gifs"}
}
<commit_msg>changed tag from "gifs" to "pics"<commit_after>package giphy

import (
	"fmt"
	"net/url"

	"github.com/zquestz/s/providers"
)

func init() {
	providers.AddProvider("giphy", &Provider{})
}

// Provider merely implements the Provider interface.
type Provider struct{}

// BuildURI generates a search URL for Giphy.
func (p *Provider) BuildURI(q string) string {
	return fmt.Sprintf("https://giphy.com/search/%s", url.QueryEscape(q))
}

// Tags returns the tags relevant to this provider.
func (p *Provider) Tags() []string {
	return []string{"pics"}
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Nicolas Lamirault <nicolas.lamirault@gmail.com>

// 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 lcapb

import (
	"bytes"
	"fmt"
	"golang.org/x/net/html"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"

	"github.com/olekukonko/tablewriter"
)

const (
	uri = "http://lcapb.euskalpilota.fr/resultats.php"
)

func fetch() ([]byte, error) {
	data := url.Values{}
	data.Add("InSel", "")
	data.Add("InCompet", "20170501")
	data.Add("InSpec", "2")
	data.Add("InVille", "0")
	data.Add("InClub", "0")
	data.Add("InDate", "")
	data.Add("InDatef", "")
	data.Add("InCat", "1")
	data.Add("InPhase", "0")
	data.Add("InPoule", "0")
	data.Add("InGroupe", "0")
	data.Add("InVoir", "Voir les résultats")
	u, _ := url.ParseRequestURI(uri)
	urlStr := fmt.Sprintf("%v", u) // "https://api.com/user/"

	client := &http.Client{}
	r, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(data.Encode()))
	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
	resp, err := client.Do(r)
	defer resp.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("Http request to %s failed: %s", r.URL, err.Error())
	}
	fmt.Println(resp.Status)
	body, err := ioutil.ReadAll(resp.Body)
	if nil != err {
		return nil, fmt.Errorf("errorination happened reading the body: %s", err.Error())
	}
	return body, nil
}

func Display() error {
	body, err := fetch()
	if err != nil {
		return err
	}
	z := html.NewTokenizer(strings.NewReader(string(body)))

	content := []string{"", "", "", "", ""}
	i := -1
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Date", "Club 1", "Club 2", "Score", "Commentaire"})

	// While have not hit the </html> tag
	for z.Token().Data != "html" {
		tt := z.Next()
		if tt == html.StartTagToken {
			t := z.Token()
			if t.Data == "tr" {
				i = -1
				if len(content[0]) > 0 {
					fmt.Printf("==> %d\n", len(content))
					for rank, elem := range content {
						fmt.Printf("%d = %s\n", rank, elem)
					}
					fmt.Println("OK")
					table.Append(content)
					content = []string{"", "", "", "", ""}
				}

			} else if t.Data == "td" {
				inner := z.Next()
				if inner == html.TextToken {
					if len(t.Attr) > 0 {
						if t.Attr[0].Val == "L0" { // Text to extract
							text := (string)(z.Text())
							value := strings.TrimSpace(text)
							if len(value) > 0 {
								i = i + 1
								fmt.Printf("%d Attr::::::::::: %s :: %s\n", i, value, t.Attr)
								content[i] = value
							}
						}
					}
				}

				// } else if t.Data == "li" {
				// 	inner := z.Next()
				// 	if inner == html.TextToken {
				// 		text := (string)(z.Text())
				// 		value := strings.TrimSpace(text)
				// 		content[i] = fmt.Sprintf("%s %s", content[i], value)
			}

			// } else if tt == html.EndTagToken {
			// 	t := z.Token()
			// 	if t.Data == "td" {
			// 		i = i + 1
			// 	}
		}
	}
	// fmt.Println(content)
	table.Render()
	return nil
}
<commit_msg>Refactorint parsing HTML<commit_after>// Copyright (C) 2016 Nicolas Lamirault <nicolas.lamirault@gmail.com>

// 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 lcapb

import (
	"bytes"
	"fmt"
	"golang.org/x/net/html"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"

	"github.com/olekukonko/tablewriter"
)

const (
	uri = "http://lcapb.euskalpilota.fr/resultats.php"
)

func fetch() ([]byte, error) {
	data := url.Values{}
	data.Add("InSel", "")
	data.Add("InCompet", "20170501")
	data.Add("InSpec", "2")
	data.Add("InVille", "0")
	data.Add("InClub", "0")
	data.Add("InDate", "")
	data.Add("InDatef", "")
	data.Add("InCat", "1")
	data.Add("InPhase", "0")
	data.Add("InPoule", "0")
	data.Add("InGroupe", "0")
	data.Add("InVoir", "Voir les résultats")
	u, _ := url.ParseRequestURI(uri)
	urlStr := fmt.Sprintf("%v", u) // "https://api.com/user/"

	client := &http.Client{}
	r, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(data.Encode()))
	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
	resp, err := client.Do(r)
	defer resp.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("Http request to %s failed: %s", r.URL, err.Error())
	}
	fmt.Println(resp.Status)
	body, err := ioutil.ReadAll(resp.Body)
	if nil != err {
		return nil, fmt.Errorf("errorination happened reading the body: %s", err.Error())
	}
	return body, nil
}

func Display() error {
	body, err := fetch()
	if err != nil {
		return err
	}
	z := html.NewTokenizer(strings.NewReader(string(body)))

	content := []string{"", "", "", "", ""}
	i := -1
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Date", "Club 1", "Club 2", "Score", "Commentaire"})

	for {
		// token type
		tokenType := z.Next()
		if tokenType == html.ErrorToken {
			break
		}
		// token := z.Token()
		switch tokenType {
		case html.StartTagToken: // <tag>
			t := z.Token()
			if t.Data == "tr" {
				i = -1

			} else if t.Data == "td" {
				inner := z.Next()
				if inner == html.TextToken {
					if len(t.Attr) > 0 {
						if t.Attr[0].Val == "L0" { // Text to extract
							text := (string)(z.Text())
							value := strings.TrimSpace(text)
							if len(value) > 0 {
								i = i + 1
								fmt.Printf("%d Attr::::::::::: %s :: %s\n", i, value, t.Attr)
								content[i] = value
							}
						}
					}
				}

				// } else if t.Data == "li" {
				// 	inner := z.Next()
				// 	if inner == html.TextToken {
				// 		text := (string)(z.Text())
				// 		value := strings.TrimSpace(text)
				// 		content[i] = fmt.Sprintf("%s %s", content[i], value)
			}
		case html.TextToken: // text between start and end tag
		case html.EndTagToken: // </tag>
			t := z.Token()
			if t.Data == "tr" {
				if len(content[0]) > 0 {
					fmt.Printf("==> %d\n", len(content))
					for rank, elem := range content {
						fmt.Printf("%d = %s\n", rank, elem)
					}
					fmt.Println("OK")
					table.Append(content)
					content = []string{"", "", "", "", ""}
				}
			}

		case html.SelfClosingTagToken: // <tag/>
		}
	}

	// While have not hit the </html> tag
	// for z.Token().Data != "html" {
	// 	tt := z.Next()
	// 	if tt == html.StartTagToken {
	// 		t := z.Token()
	// 		if t.Data == "tr" {
	// 			i = -1

	// 		} else if t.Data == "td" {
	// 			inner := z.Next()
	// 			if inner == html.TextToken {
	// 				if len(t.Attr) > 0 {
	// 					if t.Attr[0].Val == "L0" { // Text to extract
	// 						text := (string)(z.Text())
	// 						value := strings.TrimSpace(text)
	// 						if len(value) > 0 {
	// 							i = i + 1
	// 							fmt.Printf("%d Attr::::::::::: %s :: %s\n", i, value, t.Attr)
	// 							content[i] = value
	// 						}
	// 					}
	// 				}
	// 			}

	// 			// } else if t.Data == "li" {
	// 			// 	inner := z.Next()
	// 			// 	if inner == html.TextToken {
	// 			// 		text := (string)(z.Text())
	// 			// 		value := strings.TrimSpace(text)
	// 			// 		content[i] = fmt.Sprintf("%s %s", content[i], value)
	// 		}

	// 	} else if tt == html.EndTagToken {
	// 		t := z.Token()
	// 		if t.Data == "tr" {
	// 			if len(content[0]) > 0 {
	// 				fmt.Printf("==> %d\n", len(content))
	// 				for rank, elem := range content {
	// 					fmt.Printf("%d = %s\n", rank, elem)
	// 				}
	// 				fmt.Println("OK")
	// 				table.Append(content)
	// 				content = []string{"", "", "", "", ""}
	// 			}
	// 		}
	// 	}
	// }

	// fmt.Println(content)
	fmt.Printf("Finished")
	table.Render()
	return nil
}
<|endoftext|>


<commit_before>package backup

import (
	"fmt"
	"github.com/pkg/errors"
	"github.com/pkg/sftp"
	"github.com/stefanprodan/mgob/config"
	"golang.org/x/crypto/ssh"
	"io"
	"net"
	"os"
	"path/filepath"
)

func sftpUpload(file string, plan config.Plan) (string, error) {
	sshConf := &ssh.ClientConfig{
		User: plan.SFTP.Username,
		Auth: []ssh.AuthMethod{ssh.Password(plan.SFTP.Password)},
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			return nil
		},
	}

	sshCon, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", plan.SFTP.Host, plan.SFTP.Port), sshConf)
	if err != nil {
		return "", errors.Wrapf(err, "SSH dial to %v:%v failed", plan.SFTP.Host, plan.SFTP.Port)
	}
	defer sshCon.Close()

	sftpClient, err := sftp.NewClient(sshCon)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP client init %v:%v failed", plan.SFTP.Host, plan.SFTP.Port)
	}
	defer sftpClient.Close()

	f, err := os.Open(file)
	if err != nil {
		return "", errors.Wrapf(err, "Opening file %v failed", file)
	}
	defer f.Close()

	_, fname := filepath.Split(file)
	dstPath := filepath.Join(plan.SFTP.Dir, fname)
	sf, err := sftpClient.Create(dstPath)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP %v:%v creating file %v failed", plan.SFTP.Host, plan.SFTP.Port, dstPath)
	}

	_, err = io.Copy(sf, f)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP %v:%v upload file %v failed", plan.SFTP.Host, plan.SFTP.Port, dstPath)
	}
	sf.Close()

	//listSftpBackups(sftpClient, plan.SFTP.Dir)

	return fmt.Sprintf("SFTP %v:%v upload %v finished", plan.SFTP.Host, plan.SFTP.Port, dstPath), nil
}

func listSftpBackups(client *sftp.Client, dir string) error {
	list, err := client.ReadDir(fmt.Sprintf("/%v", dir))
	if err != nil {
		return errors.Wrapf(err, "SFTP reading %v dir failed", dir)
	}

	for _, item := range list {
		fmt.Println(item.Name())
	}

	return nil
}
<commit_msg>log SFTP upload duration<commit_after>package backup

import (
	"fmt"
	"github.com/pkg/errors"
	"github.com/pkg/sftp"
	"github.com/stefanprodan/mgob/config"
	"golang.org/x/crypto/ssh"
	"io"
	"net"
	"os"
	"path/filepath"
	"time"
)

func sftpUpload(file string, plan config.Plan) (string, error) {
	t1 := time.Now()
	sshConf := &ssh.ClientConfig{
		User: plan.SFTP.Username,
		Auth: []ssh.AuthMethod{ssh.Password(plan.SFTP.Password)},
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			return nil
		},
	}

	sshCon, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", plan.SFTP.Host, plan.SFTP.Port), sshConf)
	if err != nil {
		return "", errors.Wrapf(err, "SSH dial to %v:%v failed", plan.SFTP.Host, plan.SFTP.Port)
	}
	defer sshCon.Close()

	sftpClient, err := sftp.NewClient(sshCon)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP client init %v:%v failed", plan.SFTP.Host, plan.SFTP.Port)
	}
	defer sftpClient.Close()

	f, err := os.Open(file)
	if err != nil {
		return "", errors.Wrapf(err, "Opening file %v failed", file)
	}
	defer f.Close()

	_, fname := filepath.Split(file)
	dstPath := filepath.Join(plan.SFTP.Dir, fname)
	sf, err := sftpClient.Create(dstPath)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP %v:%v creating file %v failed", plan.SFTP.Host, plan.SFTP.Port, dstPath)
	}

	_, err = io.Copy(sf, f)
	if err != nil {
		return "", errors.Wrapf(err, "SFTP %v:%v upload file %v failed", plan.SFTP.Host, plan.SFTP.Port, dstPath)
	}
	sf.Close()

	//listSftpBackups(sftpClient, plan.SFTP.Dir)

	t2 := time.Now()
	msg := fmt.Sprintf("SFTP %v:%v upload %v finished in %v",
		plan.SFTP.Host, plan.SFTP.Port, dstPath, t2.Sub(t1))
	return msg, nil
}

func listSftpBackups(client *sftp.Client, dir string) error {
	list, err := client.ReadDir(fmt.Sprintf("/%v", dir))
	if err != nil {
		return errors.Wrapf(err, "SFTP reading %v dir failed", dir)
	}

	for _, item := range list {
		fmt.Println(item.Name())
	}

	return nil
}
<|endoftext|>


<commit_before>package bot

import (
	"testing"
)

type message struct {
	text string
}

func (m *message) Text() string {
	return m.text
}

func (m *message) Sender() string {
	return ""
}

type adapter struct {
	response string
	msg Message
}

func (a *adapter) Listen() Message {
	return &message{}
}

func (a *adapter) Reply(msg Message, text string) {
	a.response = text
	a.msg = msg
}

func TestAdapter(t *testing.T) {
	var i interface{} = &adapter{}
	_, ok := i.(Adapter)
	if !ok {
		t.Error("adapter{} doesn't implement Adapter")
	}
}

func TestMessage(t *testing.T) {
	var i interface{} = &message{}
	_, ok := i.(Message)
	if !ok {
		t.Error("message{} doesn't implement Message")
	}
}

func TestNew(t *testing.T) {
	a := &adapter{}
	var i interface{} = New(a)
	b, ok := i.(*Bot)
	if !ok {
		t.Error("New doesn't return a bot")
	}
	if b.adapter != a {
		t.Error("New doesn't set the adpater")
	}
	if b.handlers == nil {
		t.Error("New doesn't initialize handlers map")
	}
}

func TestBotHandle(t *testing.T) {
	a := &adapter{}
	b := New(a)
	expr := `test`
	handler := func(msg Message) {}
	b.Handle(expr, handler)
	if len(b.handlers) < 1 {
		t.Error("Bot.Handle doesn't register new handler")
	}
	if b.handlers[0].re.String() != `(?i)`+expr {
		t.Error("Bot.Handle doesn't add case insensitive flag to the expr")
	}
}

func TestBotReceive(t *testing.T) {
	a := &adapter{}
	b := New(a)
	handle1 := false
	b.Handle(`handle1|any`, func(msg Message) {
		handle1 = true
	})
	handle2 := false
	b.Handle(`handle2|any`, func(msg Message) {
		handle2 = true
	})
	b.Receive(&message{text: "handle1"})
	if !handle1 || handle2 {
		t.Error("Bot.Receive got the wrong handler")
	}
	b.Receive(&message{text: "handle2"})
	if !handle2 {
		t.Error("Bot.Receive got the wrong handler")
	}
	handle1 = false
	handle2 = false
	b.Receive(&message{text: "any"})
	if !handle1 {
		t.Error("Bot.Receive isn't preserving order")
	}
	if handle2 {
		t.Error("Bot.Receive isn't breaking after first match")
	}
}
<commit_msg>Add test for Bot.Reply<commit_after>package bot

import (
	"testing"
)

type message struct {
	text string
}

func (m *message) Text() string {
	return m.text
}

func (m *message) Sender() string {
	return ""
}

type adapter struct {
	response string
	msg Message
}

func (a *adapter) Listen() Message {
	return &message{}
}

func (a *adapter) Reply(msg Message, text string) {
	a.response = text
	a.msg = msg
}

func TestAdapter(t *testing.T) {
	var i interface{} = &adapter{}
	_, ok := i.(Adapter)
	if !ok {
		t.Error("adapter{} doesn't implement Adapter")
	}
}

func TestMessage(t *testing.T) {
	var i interface{} = &message{}
	_, ok := i.(Message)
	if !ok {
		t.Error("message{} doesn't implement Message")
	}
}

func TestNew(t *testing.T) {
	a := &adapter{}
	var i interface{} = New(a)
	b, ok := i.(*Bot)
	if !ok {
		t.Error("New doesn't return a bot")
	}
	if b.adapter != a {
		t.Error("New doesn't set the adpater")
	}
	if b.handlers == nil {
		t.Error("New doesn't initialize handlers map")
	}
}

func TestBotHandle(t *testing.T) {
	a := &adapter{}
	b := New(a)
	expr := `test`
	handler := func(msg Message) {}
	b.Handle(expr, handler)
	if len(b.handlers) < 1 {
		t.Error("Bot.Handle doesn't register new handler")
	}
	if b.handlers[0].re.String() != `(?i)`+expr {
		t.Error("Bot.Handle doesn't add case insensitive flag to the expr")
	}
}

func TestBotReceive(t *testing.T) {
	a := &adapter{}
	b := New(a)
	handle1 := false
	b.Handle(`handle1|any`, func(msg Message) {
		handle1 = true
	})
	handle2 := false
	b.Handle(`handle2|any`, func(msg Message) {
		handle2 = true
	})
	b.Receive(&message{text: "handle1"})
	if !handle1 || handle2 {
		t.Error("Bot.Receive got the wrong handler")
	}
	b.Receive(&message{text: "handle2"})
	if !handle2 {
		t.Error("Bot.Receive got the wrong handler")
	}
	handle1 = false
	handle2 = false
	b.Receive(&message{text: "any"})
	if !handle1 {
		t.Error("Bot.Receive isn't preserving order")
	}
	if handle2 {
		t.Error("Bot.Receive isn't breaking after first match")
	}
}

func TestBotReply(t *testing.T) {
	a := &adapter{}
	b := New(a)
	msg := &message{}
	response := "test"
	b.Reply(msg, response)
	if a.response != response || a.msg != msg {
		t.Error("Bot.Reply isn't properly calling Adapter.Reply")
	}
}
<|endoftext|>


<commit_before><commit_msg>Add new Cgroup limits field to ProcessSpec<commit_after><|endoftext|>


<commit_before>package controllers

import (
	"net/http"
	"net/http/httptest"
	//"net/url"
	"path/filepath"
	"runtime"
	"testing"

	"fmt"
	"strings"

	"github.com/astaxie/beego"
	//"github.com/dghubble/sling"
	"github.com/stretchr/testify/assert"
)

//const (
//	adminName = "admin"
//	adminPwd  = "Harbor12345"
//)

//type usrInfo struct {
//	Name   string
//	Passwd string
//}

//var admin *usrInfo

func init() {

	_, file, _, _ := runtime.Caller(1)
	apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
	beego.BConfig.WebConfig.Session.SessionOn = true
	beego.TestBeegoInit(apppath)
	beego.AddTemplateExt("htm")

	beego.Router("/", &IndexController{})
	beego.Router("/dashboard", &DashboardController{})
	beego.Router("/project", &ProjectController{})
	beego.Router("/repository", &RepositoryController{})
	beego.Router("/sign_up", &SignUpController{})
	beego.Router("/add_new", &AddNewController{})
	beego.Router("/account_setting", &AccountSettingController{})
	beego.Router("/change_password", &ChangePasswordController{})
	beego.Router("/admin_option", &AdminOptionController{})
	beego.Router("/forgot_password", &ForgotPasswordController{})
	beego.Router("/reset_password", &ResetPasswordController{})
	beego.Router("/search", &SearchController{})

	beego.Router("/login", &CommonController{}, "post:Login")
	beego.Router("/log_out", &CommonController{}, "get:LogOut")
	beego.Router("/reset", &CommonController{}, "post:ResetPassword")
	beego.Router("/userExists", &CommonController{}, "post:UserExists")
	beego.Router("/sendEmail", &CommonController{}, "get:SendEmail")
	beego.Router("/language", &CommonController{}, "get:SwitchLanguage")

	beego.Router("/optional_menu", &OptionalMenuController{})
	beego.Router("/navigation_header", &NavigationHeaderController{})
	beego.Router("/navigation_detail", &NavigationDetailController{})
	beego.Router("/sign_in", &SignInController{})

	//Init user Info
	//admin = &usrInfo{adminName, adminPwd}

}

// TestMain is a sample to run an endpoint test
func TestMain(t *testing.T) {
	assert := assert.New(t)

	//	v := url.Values{}
	//	v.Set("principal", "admin")
	//	v.Add("password", "Harbor12345")

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_index</title>"), "http respond should have '<title>page_title_index</title>'")

	r, _ = http.NewRequest("GET", "/dashboard", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/dashboard' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_dashboard</title>"), "http respond should have '<title>page_title_dashboard</title>'")

	r, _ = http.NewRequest("GET", "/project", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/project' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_project</title>"), "http respond should have '<title>page_title_project</title>'")

	r, _ = http.NewRequest("GET", "/repository", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/repository' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_repository</title>"), "http respond should have '<title>page_title_repository</title>'")

	r, _ = http.NewRequest("GET", "/sign_up", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/sign_up' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_sign_up</title>"), "http respond should have '<title>page_title_sign_up</title>'")

	r, _ = http.NewRequest("GET", "/add_new", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(401), w.Code, "'/add_new' httpStatusCode should be 401")

	r, _ = http.NewRequest("GET", "/account_setting", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/account_setting' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_account_setting</title>"), "http respond should have '<title>page_title_account_setting</title>'")

	r, _ = http.NewRequest("GET", "/change_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/change_password' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_change_password</title>"), "http respond should have '<title>page_title_change_password</title>'")

	r, _ = http.NewRequest("GET", "/admin_option", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/admin_option' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_admin_option</title>"), "http respond should have '<title>page_title_admin_option</title>'")

	r, _ = http.NewRequest("GET", "/forgot_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/forgot_password' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_forgot_password</title>"), "http respond should have '<title>page_title_forgot_password</title>'")

	r, _ = http.NewRequest("GET", "/reset_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/reset_password' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/search", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/search' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_search</title>"), "http respond should have '<title>page_title_searc</title>'")

	r, _ = http.NewRequest("POST", "/login", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(401), w.Code, "'/login' httpStatusCode should be 401")

	r, _ = http.NewRequest("GET", "/log_out", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/log_out' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), ""), "http respond should be empty")

	r, _ = http.NewRequest("POST", "/reset", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(400), w.Code, "'/reset' httpStatusCode should be 400")

	r, _ = http.NewRequest("POST", "/userExists", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(500), w.Code, "'/userExists' httpStatusCode should be 500")

	r, _ = http.NewRequest("GET", "/sendEmail", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(400), w.Code, "'/sendEmail' httpStatusCode should be 400")

	r, _ = http.NewRequest("GET", "/language", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/language' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/optional_menu", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/optional_menu: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/optional_menu' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/navigation_header", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/navigation_header: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/navigation_header' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/navigation_detail", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/navigation_detail: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/navigation_detail' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/sign_in", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/sign_in: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/sign_in' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

}
<commit_msg>Updates for controller test cases.<commit_after>package controllers

import (
	"net/http"
	"net/http/httptest"
	//"net/url"
	"path/filepath"
	"runtime"
	"testing"

	"fmt"
	"strings"

	"github.com/astaxie/beego"
	//"github.com/dghubble/sling"
	"github.com/stretchr/testify/assert"
)

//const (
//	adminName = "admin"
//	adminPwd  = "Harbor12345"
//)

//type usrInfo struct {
//	Name   string
//	Passwd string
//}

//var admin *usrInfo

func init() {

	_, file, _, _ := runtime.Caller(1)
	apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
	beego.BConfig.WebConfig.Session.SessionOn = true
	beego.TestBeegoInit(apppath)
	beego.AddTemplateExt("htm")

	beego.Router("/", &IndexController{})
	beego.Router("/dashboard", &DashboardController{})
	beego.Router("/project", &ProjectController{})
	beego.Router("/repository", &RepositoryController{})
	beego.Router("/sign_up", &SignUpController{})
	beego.Router("/add_new", &AddNewController{})
	beego.Router("/account_setting", &AccountSettingController{})
	beego.Router("/change_password", &ChangePasswordController{})
	beego.Router("/admin_option", &AdminOptionController{})
	beego.Router("/forgot_password", &ForgotPasswordController{})
	beego.Router("/reset_password", &ResetPasswordController{})
	beego.Router("/search", &SearchController{})

	beego.Router("/login", &CommonController{}, "post:Login")
	beego.Router("/log_out", &CommonController{}, "get:LogOut")
	beego.Router("/reset", &CommonController{}, "post:ResetPassword")
	beego.Router("/userExists", &CommonController{}, "post:UserExists")
	beego.Router("/sendEmail", &CommonController{}, "get:SendEmail")
	beego.Router("/language", &CommonController{}, "get:SwitchLanguage")

	beego.Router("/optional_menu", &OptionalMenuController{})
	beego.Router("/navigation_header", &NavigationHeaderController{})
	beego.Router("/navigation_detail", &NavigationDetailController{})
	beego.Router("/sign_in", &SignInController{})

	//Init user Info
	//admin = &usrInfo{adminName, adminPwd}

}

// TestMain is a sample to run an endpoint test
func TestMain(t *testing.T) {
	assert := assert.New(t)

	//	v := url.Values{}
	//	v.Set("principal", "admin")
	//	v.Add("password", "Harbor12345")

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_index</title>"), "http respond should have '<title>page_title_index</title>'")

	r, _ = http.NewRequest("GET", "/dashboard", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/dashboard' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_dashboard</title>"), "http respond should have '<title>page_title_dashboard</title>'")

	r, _ = http.NewRequest("GET", "/project", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/project' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_project</title>"), "http respond should have '<title>page_title_project</title>'")

	r, _ = http.NewRequest("GET", "/repository", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/repository' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_repository</title>"), "http respond should have '<title>page_title_repository</title>'")

	r, _ = http.NewRequest("GET", "/sign_up", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/sign_up' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_sign_up</title>"), "http respond should have '<title>page_title_sign_up</title>'")

	r, _ = http.NewRequest("GET", "/add_new", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(401), w.Code, "'/add_new' httpStatusCode should be 401")

	r, _ = http.NewRequest("GET", "/account_setting", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/account_setting' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/change_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/change_password' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/admin_option", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/admin_option' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/forgot_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/forgot_password' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_forgot_password</title>"), "http respond should have '<title>page_title_forgot_password</title>'")

	r, _ = http.NewRequest("GET", "/reset_password", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/reset_password' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/search", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/search' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title>page_title_search</title>"), "http respond should have '<title>page_title_searc</title>'")

	r, _ = http.NewRequest("POST", "/login", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(401), w.Code, "'/login' httpStatusCode should be 401")

	r, _ = http.NewRequest("GET", "/log_out", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(200), w.Code, "'/log_out' httpStatusCode should be 200")
	assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), ""), "http respond should be empty")

	r, _ = http.NewRequest("POST", "/reset", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(400), w.Code, "'/reset' httpStatusCode should be 400")

	r, _ = http.NewRequest("POST", "/userExists", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(500), w.Code, "'/userExists' httpStatusCode should be 500")

	r, _ = http.NewRequest("GET", "/sendEmail", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(400), w.Code, "'/sendEmail' httpStatusCode should be 400")

	r, _ = http.NewRequest("GET", "/language", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	assert.Equal(int(302), w.Code, "'/language' httpStatusCode should be 302")

	r, _ = http.NewRequest("GET", "/optional_menu", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/optional_menu: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/optional_menu' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/navigation_header", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/navigation_header: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/navigation_header' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/navigation_detail", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/navigation_detail: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/navigation_detail' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

	r, _ = http.NewRequest("GET", "/sign_in", nil)
	w = httptest.NewRecorder()
	beego.BeeApp.Handlers.ServeHTTP(w, r)
	//fmt.Printf("/sign_in: %s\n", w.Body)
	assert.Equal(int(200), w.Code, "'/sign_in' httpStatusCode should be 200")
	//assert.Equal(true, strings.Contains(fmt.Sprintf("%s", w.Body), "<title> </title>"), "http respond should have '<title> </title>'")

}
<|endoftext|>


<commit_before>package inventory

import (
	"log"

	"chunkymonkey/itemtype"
	"chunkymonkey/recipe"
	"chunkymonkey/slot"
	. "chunkymonkey/types"
)

const (
	furnaceSlotReagent = SlotId(0)
	furnaceSlotFuel    = SlotId(1)
	furnaceSlotOutput  = SlotId(2)
	furnaceNumSlots    = 3

	reactionDuration = Ticks(185)
)

type FurnaceInventory struct {
	Inventory
	furnaceData       *recipe.FurnaceData
	itemTypes         itemtype.ItemTypeMap
	maxFuel           Ticks
	curFuel           Ticks
	reactionRemaining Ticks
}

// NewFurnaceInventory creates a furnace inventory.
func NewFurnaceInventory(furnaceData *recipe.FurnaceData, itemTypes itemtype.ItemTypeMap) (inv *FurnaceInventory) {
	inv = &FurnaceInventory{
		furnaceData:       furnaceData,
		itemTypes:         itemTypes,
		maxFuel:           0,
		curFuel:           0,
		reactionRemaining: reactionDuration,
	}
	inv.Inventory.Init(furnaceNumSlots)
	return
}

func (inv *FurnaceInventory) Click(slotId SlotId, cursor *slot.Slot, rightClick bool, shiftClick bool, txId TxId, expectedSlot *slot.Slot) (txState TxState) {

	switch slotId {
	case furnaceSlotReagent:
		slotBefore := inv.slots[furnaceSlotReagent]

		txState = inv.Inventory.Click(
			slotId, cursor, rightClick, shiftClick, txId, expectedSlot)

		slotAfter := &inv.slots[furnaceSlotReagent]

		// If the reagent type changes, the reaction restarts.
		if slotBefore.ItemType != slotAfter.ItemType || slotBefore.Data != slotAfter.Data {
			inv.reactionRemaining = reactionDuration
		}
	case furnaceSlotFuel:
		cursorItemId := cursor.GetItemTypeId()
		_, cursorIsFuel := inv.furnaceData.Fuels[cursorItemId]
		if cursorIsFuel || cursor.IsEmpty() {
			txState = inv.Inventory.Click(
				slotId, cursor, rightClick, shiftClick, txId, expectedSlot)
		}
	case furnaceSlotOutput:
		// Player may only *take* the *whole* stack from the output slot.
		txState = inv.Inventory.TakeOnlyClick(
			slotId, cursor, rightClick, shiftClick, txId, expectedSlot)
	}

	inv.stateCheck()

	inv.sendProgressUpdates()

	return
}

func (inv *FurnaceInventory) stateCheck() {
	reagentSlot := &inv.slots[furnaceSlotReagent]
	fuelSlot := &inv.slots[furnaceSlotFuel]
	outputSlot := &inv.slots[furnaceSlotOutput]

	reaction, haveReagent := inv.furnaceData.Reactions[reagentSlot.GetItemTypeId()]
	fuelTicks, haveFuel := inv.furnaceData.Fuels[fuelSlot.GetItemTypeId()]

	// Work out if the output slot is ready for items to be produced from the
	// reaction.
	var outputReady bool
	if outputSlot.ItemType != nil {
		// Output has items in.
		if !haveReagent {
			outputReady = false
		} else if outputSlot.Count >= outputSlot.ItemType.MaxStack {
			// Output is full.
			outputReady = false
		} else if outputSlot.GetItemTypeId() != reaction.Output || outputSlot.Data != reaction.OutputData {
			// Output has a different type from the reaction.
			outputReady = false
		} else {
			// Output contains compatible items and is not full.
			outputReady = true
		}
	} else {
		// Output is empty.
		outputReady = true
	}

	if inv.curFuel > 0 {
		// Furnace is lit.
		if !outputReady {
			inv.reactionRemaining = reactionDuration
		} else if haveReagent && inv.reactionRemaining == 0 {
			// One reaction complete.
			if itemType, ok := inv.itemTypes[reaction.Output]; !ok {
				log.Printf("Furnace encountered unknown output type in reaction %#v", reaction)
			} else {
				itemCreated := slot.Slot{
					ItemType: itemType,
					Count: 1,
					Data: reaction.OutputData,
				}
				inv.reactionRemaining = reactionDuration

				outputSlot.AddOne(&itemCreated)
				inv.slotUpdate(outputSlot, furnaceSlotOutput)
				reagentSlot.Decrement()
				inv.slotUpdate(reagentSlot, furnaceSlotReagent)
			}
		}
	} else {
		inv.reactionRemaining = reactionDuration

		// Furnace is unlit.
		if haveReagent && haveFuel && outputReady {
			// Everything is in place, light the furnace by consuming one unit of
			// fuel.
			fuelSlot.Decrement()
			inv.curFuel = fuelTicks
			inv.slotUpdate(fuelSlot, furnaceSlotFuel)
		} else {
			inv.reactionRemaining = reactionDuration
		}
	}
}

func (inv *FurnaceInventory) sendProgressUpdates() {
	// TODO
	log.Printf("Furnace progress: reaction=%d/%d fuel=%d/%d", inv.reactionRemaining, reactionDuration, inv.curFuel, inv.maxFuel)
}

func (inv *FurnaceInventory) IsLit() bool {
	return inv.curFuel > 0
}

// Tick runs the furnace for a single tick.
func (inv *FurnaceInventory) Tick() {
	if inv.curFuel > 0 {
		inv.curFuel--

		if inv.reactionRemaining > 0 {
			inv.reactionRemaining--
		}

		inv.stateCheck()

		inv.sendProgressUpdates()
	}
}
<commit_msg>Fix setting maxFuel when a furnace consumes fuel.<commit_after>package inventory

import (
	"log"

	"chunkymonkey/itemtype"
	"chunkymonkey/recipe"
	"chunkymonkey/slot"
	. "chunkymonkey/types"
)

const (
	furnaceSlotReagent = SlotId(0)
	furnaceSlotFuel    = SlotId(1)
	furnaceSlotOutput  = SlotId(2)
	furnaceNumSlots    = 3

	reactionDuration = Ticks(185)
)

type FurnaceInventory struct {
	Inventory
	furnaceData       *recipe.FurnaceData
	itemTypes         itemtype.ItemTypeMap
	maxFuel           Ticks
	curFuel           Ticks
	reactionRemaining Ticks
}

// NewFurnaceInventory creates a furnace inventory.
func NewFurnaceInventory(furnaceData *recipe.FurnaceData, itemTypes itemtype.ItemTypeMap) (inv *FurnaceInventory) {
	inv = &FurnaceInventory{
		furnaceData:       furnaceData,
		itemTypes:         itemTypes,
		maxFuel:           0,
		curFuel:           0,
		reactionRemaining: reactionDuration,
	}
	inv.Inventory.Init(furnaceNumSlots)
	return
}

func (inv *FurnaceInventory) Click(slotId SlotId, cursor *slot.Slot, rightClick bool, shiftClick bool, txId TxId, expectedSlot *slot.Slot) (txState TxState) {

	switch slotId {
	case furnaceSlotReagent:
		slotBefore := inv.slots[furnaceSlotReagent]

		txState = inv.Inventory.Click(
			slotId, cursor, rightClick, shiftClick, txId, expectedSlot)

		slotAfter := &inv.slots[furnaceSlotReagent]

		// If the reagent type changes, the reaction restarts.
		if slotBefore.ItemType != slotAfter.ItemType || slotBefore.Data != slotAfter.Data {
			inv.reactionRemaining = reactionDuration
		}
	case furnaceSlotFuel:
		cursorItemId := cursor.GetItemTypeId()
		_, cursorIsFuel := inv.furnaceData.Fuels[cursorItemId]
		if cursorIsFuel || cursor.IsEmpty() {
			txState = inv.Inventory.Click(
				slotId, cursor, rightClick, shiftClick, txId, expectedSlot)
		}
	case furnaceSlotOutput:
		// Player may only *take* the *whole* stack from the output slot.
		txState = inv.Inventory.TakeOnlyClick(
			slotId, cursor, rightClick, shiftClick, txId, expectedSlot)
	}

	inv.stateCheck()

	inv.sendProgressUpdates()

	return
}

func (inv *FurnaceInventory) stateCheck() {
	reagentSlot := &inv.slots[furnaceSlotReagent]
	fuelSlot := &inv.slots[furnaceSlotFuel]
	outputSlot := &inv.slots[furnaceSlotOutput]

	reaction, haveReagent := inv.furnaceData.Reactions[reagentSlot.GetItemTypeId()]
	fuelTicks, haveFuel := inv.furnaceData.Fuels[fuelSlot.GetItemTypeId()]

	// Work out if the output slot is ready for items to be produced from the
	// reaction.
	var outputReady bool
	if outputSlot.ItemType != nil {
		// Output has items in.
		if !haveReagent {
			outputReady = false
		} else if outputSlot.Count >= outputSlot.ItemType.MaxStack {
			// Output is full.
			outputReady = false
		} else if outputSlot.GetItemTypeId() != reaction.Output || outputSlot.Data != reaction.OutputData {
			// Output has a different type from the reaction.
			outputReady = false
		} else {
			// Output contains compatible items and is not full.
			outputReady = true
		}
	} else {
		// Output is empty.
		outputReady = true
	}

	if inv.curFuel > 0 {
		// Furnace is lit.
		if !outputReady {
			inv.reactionRemaining = reactionDuration
		} else if haveReagent && inv.reactionRemaining == 0 {
			// One reaction complete.
			if itemType, ok := inv.itemTypes[reaction.Output]; !ok {
				log.Printf("Furnace encountered unknown output type in reaction %#v", reaction)
			} else {
				itemCreated := slot.Slot{
					ItemType: itemType,
					Count: 1,
					Data: reaction.OutputData,
				}
				inv.reactionRemaining = reactionDuration

				outputSlot.AddOne(&itemCreated)
				inv.slotUpdate(outputSlot, furnaceSlotOutput)
				reagentSlot.Decrement()
				inv.slotUpdate(reagentSlot, furnaceSlotReagent)
			}
		}
	} else {
		inv.reactionRemaining = reactionDuration

		// Furnace is unlit.
		if haveReagent && haveFuel && outputReady {
			// Everything is in place, light the furnace by consuming one unit of
			// fuel.
			fuelSlot.Decrement()
			inv.maxFuel = fuelTicks
			inv.curFuel = fuelTicks
			inv.slotUpdate(fuelSlot, furnaceSlotFuel)
		} else {
			inv.reactionRemaining = reactionDuration
		}
	}
}

func (inv *FurnaceInventory) sendProgressUpdates() {
	// TODO
	log.Printf("Furnace progress: reaction=%d/%d fuel=%d/%d", inv.reactionRemaining, reactionDuration, inv.curFuel, inv.maxFuel)
}

func (inv *FurnaceInventory) IsLit() bool {
	return inv.curFuel > 0
}

// Tick runs the furnace for a single tick.
func (inv *FurnaceInventory) Tick() {
	if inv.curFuel > 0 {
		inv.curFuel--

		if inv.reactionRemaining > 0 {
			inv.reactionRemaining--
		}

		inv.stateCheck()

		inv.sendProgressUpdates()
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

import (
	"fmt"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/transform"
	"regexp"
	"strings"
	"unicode/utf8"

	"github.com/arachnist/gorepost/irc"
)

var trimTitle *regexp.Regexp
var trimLink *regexp.Regexp
var enc = charmap.ISO8859_2

func getURLTitle(l string) string {
	title, err := httpGetXpath(l, "//head/title")
	if err == errElementNotFound {
		return "no title"
	} else if err != nil {
		return fmt.Sprint("error:", err)
	}

	title = string(trimTitle.ReplaceAll([]byte(title), []byte{' '})[:])
	if !utf8.ValidString(title) {
		title, _, err = transform.String(enc.NewDecoder(), title)
		if err != nil {
			return fmt.Sprint("error:", err)
		}
	}

	return title
}

func linktitle(output func(irc.Message), msg irc.Message) {
	var r []string

	for _, s := range strings.Split(msg.Trailing, " ") {
		if s == "notitle" {
			return
		}

		b, _ := regexp.Match("https?://", []byte(s))

		s = string(trimLink.ReplaceAll([]byte(s), []byte("http"))[:])

		if b {
			t := getURLTitle(s)
			if t != "no title" {
				r = append(r, t)
			}
		}
	}

	if len(r) > 0 {
		t := cfg.LookupString(msg.Context, "LinkTitlePrefix") + strings.Join(r, cfg.LookupString(msg.Context, "LinkTitleDelimiter"))

		output(reply(msg, t))
	}
}

func init() {
	trimTitle, _ = regexp.Compile("[\\s]+")
	trimLink, _ = regexp.Compile("^.*?http")
	addCallback("PRIVMSG", "LINKTITLE", linktitle)
}
<commit_msg>Trim CTCP characters.<commit_after>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

import (
	"fmt"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/transform"
	"regexp"
	"strings"
	"unicode/utf8"

	"github.com/arachnist/gorepost/irc"
)

var trimTitle *regexp.Regexp
var trimLink *regexp.Regexp
var enc = charmap.ISO8859_2

func getURLTitle(l string) string {
	title, err := httpGetXpath(l, "//head/title")
	if err == errElementNotFound {
		return "no title"
	} else if err != nil {
		return fmt.Sprint("error:", err)
	}

	title = string(trimTitle.ReplaceAll([]byte(title), []byte{' '})[:])
	if !utf8.ValidString(title) {
		title, _, err = transform.String(enc.NewDecoder(), title)
		if err != nil {
			return fmt.Sprint("error:", err)
		}
	}

	return title
}

func linktitle(output func(irc.Message), msg irc.Message) {
	var r []string

	for _, s := range strings.Split(strings.Trim(msg.Trailing, "\001"), " ") {
		if s == "notitle" {
			return
		}

		b, _ := regexp.Match("https?://", []byte(s))

		s = string(trimLink.ReplaceAll([]byte(s), []byte("http"))[:])

		if b {
			t := getURLTitle(s)
			if t != "no title" {
				r = append(r, t)
			}
		}
	}

	if len(r) > 0 {
		t := cfg.LookupString(msg.Context, "LinkTitlePrefix") + strings.Join(r, cfg.LookupString(msg.Context, "LinkTitleDelimiter"))

		output(reply(msg, t))
	}
}

func init() {
	trimTitle, _ = regexp.Compile("[\\s]+")
	trimLink, _ = regexp.Compile("^.*?http")
	addCallback("PRIVMSG", "LINKTITLE", linktitle)
}
<|endoftext|>


<commit_before>package lazycache

import "fmt"
import "net/http"
import "encoding/json"

func RootHandler(w http.ResponseWriter, req *http.Request) {

	// Map RootMap to a different structure

	type APIPathOut struct {
		V1 string
	}

	type RootMapOut struct {
		APIPath APIPathOut
	}

	jsonRootMap := make(map[string]RootMapOut)

	for key, root := range RootMap {
		jsonRootMap[key] = RootMapOut{
			APIPath: APIPathOut{
				V1: root.node.trimPath,
			},
		}
	}

	//	if jsonExtension.MatchString(req.URL.Path) {

	b, err := json.MarshalIndent(jsonRootMap, "", "  ")
	if err != nil {
		fmt.Fprintln(w, "JSON error:", err)
	}

	w.Write(b)
	//	} else {

	// 	fmt.Fprintf(w, "
")
	// 	for key, val := range RootMap {
	// 		fmt.Fprintf(w, "
%s
\n", val, key)
	// 	}
	// 	fmt.Fprintf(w, "
")
	// 	//fmt.Println("Indexing from ", req.URL.String())
	// }
}
<commit_msg>Added comment for RootHandler<commit_after>package lazycache

import "fmt"
import "net/http"
import "encoding/json"

// RootHandler is the default HTTP handler, registered at "/"
// It returns a JSON structure giving the relative path to
// each of the registered mirrors.
//
// e.g.
//
//   {
//     "https://rawdata.oceanobservatories.org/files/": {
//       "APIPath": {
//         "V1": "/v1/org/oceanobservatories/rawdata/files/"
//       }
//     }
//   }
func RootHandler(w http.ResponseWriter, req *http.Request) {

	// Map RootMap to a different structure

	type APIPathOut struct {
		V1 string
	}

	type RootMapOut struct {
		APIPath APIPathOut
	}

	jsonRootMap := make(map[string]RootMapOut)

	for key, root := range RootMap {
		jsonRootMap[key] = RootMapOut{
			APIPath: APIPathOut{
				V1: root.node.trimPath,
			},
		}
	}

	//	if jsonExtension.MatchString(req.URL.Path) {

	b, err := json.MarshalIndent(jsonRootMap, "", "  ")
	if err != nil {
		fmt.Fprintln(w, "JSON error:", err)
	}

	w.Write(b)
	//	} else {

	// 	fmt.Fprintf(w, "
")
	// 	for key, val := range RootMap {
	// 		fmt.Fprintf(w, "
%s
\n", val, key)
	// 	}
	// 	fmt.Fprintf(w, "
")
	// 	//fmt.Println("Indexing from ", req.URL.String())
	// }
}
<|endoftext|>


<commit_before>// Copyright 2013 Matthew Baird
// 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 elastigo

import (
	"encoding/json"
	"fmt"
	. "github.com/araddon/gou"
)

var (
	_ = DEBUG
)

// A bool (and/or) clause
type BoolClause string

type TermExecutionMode string

const (
	TEM_DEFAULT TermExecutionMode = ""
	TEM_PLAIN                     = "plain"
	TEM_FIELD                     = "field_data"
	TEM_BOOL                      = "bool"
	TEM_AND                       = "and"
	TEM_OR                        = "or"
)

// Filter clause is either a boolClause or FilterOp
type FilterClause interface {
	String() string
}

// A wrapper to allow for custom serialization
type FilterWrap struct {
	boolClause string
	filters    []interface{}
}

func NewFilterWrap() *FilterWrap {
	return &FilterWrap{filters: make([]interface{}, 0), boolClause: "and"}
}

func (f *FilterWrap) String() string {
	return fmt.Sprintf(`fopv: %d:%v`, len(f.filters), f.filters)
}

// Custom marshalling to support the query dsl
func (f *FilterWrap) addFilters(fl []interface{}) {
	if len(fl) > 1 {
		fc := fl[0]
		switch fc.(type) {
		case BoolClause, string:
			f.boolClause = fc.(string)
			fl = fl[1:]
		}
	}
	f.filters = append(f.filters, fl...)
}

// Custom marshalling to support the query dsl
func (f *FilterWrap) MarshalJSON() ([]byte, error) {
	var root interface{}
	if len(f.filters) > 1 {
		root = map[string]interface{}{f.boolClause: f.filters}
	} else if len(f.filters) == 1 {
		root = f.filters[0]
	}
	return json.Marshal(root)
}

/*
	"filter": {
		"range": {
		  "@timestamp": {
		    "from": "2012-12-29T16:52:48+00:00",
		    "to": "2012-12-29T17:52:48+00:00"
		  }
		}
	}
	"filter": {
	    "missing": {
	        "field": "repository.name"
	    }
	}

	"filter" : {
	    "terms" : {
	        "user" : ["kimchy", "elasticsearch"],
	        "execution" : "bool",
	        "_cache": true
	    }
	}

	"filter" : {
	    "term" : { "user" : "kimchy"}
	}

	"filter" : {
	    "and" : [
	        {
	            "range" : {
	                "postDate" : {
	                    "from" : "2010-03-01",
	                    "to" : "2010-04-01"
	                }
	            }
	        },
	        {
	            "prefix" : { "name.second" : "ba" }
	        }
	    ]
	}

*/

// Filter Operation
//
//   Filter().Term("user","kimchy")
//
//   // we use variadics to allow n arguments, first is the "field" rest are values
//   Filter().Terms("user", "kimchy", "elasticsearch")
//
//   Filter().Exists("repository.name")
//
func Filter() *FilterOp {
	return &FilterOp{}
}

func CompoundFilter(fl ...interface{}) *FilterWrap {
	FilterVal := NewFilterWrap()
	FilterVal.addFilters(fl)
	return FilterVal
}

type FilterOp struct {
	TermsMap     map[string][]interface{} `json:"terms,omitempty"`
	TermMap      map[string]interface{}   `json:"term,omitempty"`
	RangeMap     map[string]RangeFilter   `json:"range,omitempty"`
	ExistsProp   *PropertyPathMarker      `json:"exists,omitempty"`
	MissingProp  *PropertyPathMarker      `json:"missing,omitempty"`
	AndFilters   []FilterOp               `json:"and,omitempty"`
	OrFilters    []FilterOp               `json:"or,omitempty"`
	NotFilters   []FilterOp               `json:"not,omitempty"`
	Limit        *LimitFilter             `json:"limit,omitempty"`
	Type         *TypeFilter              `json:"type,omitempty"`
	Ids          *IdFilter                `json:"ids,omitempty"`
	Script       *ScriptFilter            `json:"script,omitempty"`
	GeoDist      map[string]interface{}   `json:"geo_distance,omitempty"`
	GeoDistRange map[string]interface{}   `json:"geo_distance_range,omitempty"`
}

type PropertyPathMarker struct {
	Field string `json:"field"`
}

type LimitFilter struct {
	Value int `json:"value"`
}

type TypeFilter struct {
	Value string `json:"value"`
}

type IdFilter struct {
	Type   string   `json:"type,omitempty"`
	Values []string `json:"values,omitempty"`
}

type ScriptFilter struct {
	Script   string                 `json:"script"`
	Params   map[string]interface{} `json:"params,omitempty"`
	IsCached bool                   `json:"_cache,omitempty"`
}

type RangeFilter struct {
	Gte      interface{} `json:"gte,omitempty"`
	Lte      interface{} `json:"lte,omitempty"`
	Gt       interface{} `json:"gt,omitempty"`
	Lt       interface{} `json:"lt,omitempty"`
	TimeZone string      `json:"time_zone,omitempty"` //Ideally this would be an int
}

type GeoLocation struct {
	Latitude  float32 `json:"lat"`
	Longitude float32 `json:"lon"`
}

type GeoField struct {
	GeoLocation
	Field string
}

// Term will add a term to the filter.
// Multiple Term filters can be added, and ES will OR them.
func (f *FilterOp) Term(field string, value interface{}) *FilterOp {
	if len(f.TermMap) == 0 {
		f.TermMap = make(map[string]interface{})
	}

	f.TermMap[field] = value
	return f
}

func (f *FilterOp) And(filter *FilterOp) *FilterOp {
	if len(f.AndFilters) == 0 {
		f.AndFilters = []FilterOp{*filter}
	} else {
		f.AndFilters = append(f.AndFilters, *filter)
	}

	return f
}

func (f *FilterOp) Or(filter *FilterOp) *FilterOp {
	if len(f.OrFilters) == 0 {
		f.OrFilters = []FilterOp{*filter}
	} else {
		f.OrFilters = append(f.OrFilters, *filter)
	}

	return f
}

func (f *FilterOp) GeoDistance(distance string, fields ...GeoField) *FilterOp {
	f.GeoDist = make(map[string]interface{})
	f.GeoDist["distance"] = distance
	for _, val := range fields {
		f.GeoDist[val.Field] = val.GeoLocation
	}

	return f
}

func (f *FilterOp) GeoDistanceRange(from string, to string, fields ...GeoField) *FilterOp {
	f.GeoDist = make(map[string]interface{})
	f.GeoDist["from"] = from
	f.GeoDist["to"] = to

	for _, val := range fields {
		f.GeoDist[val.Field] = val.GeoLocation
	}

	return f
}

// Helper to create values for the GeoDistance filters
func NewGeoField(field string, latitude float32, longitude float32) GeoField {
	return GeoField{
		GeoLocation: GeoLocation{Latitude: latitude, Longitude: longitude},
		Field:       field}
}

// Filter Terms
//
//   Filter().Terms("user","kimchy","stuff")
//	 Note: you can only have one terms clause in a filter. Use a bool filter to combine
func (f *FilterOp) Terms(field string, executionMode TermExecutionMode, values ...interface{}) *FilterOp {
	//You can only have one terms in a filter
	f.TermsMap = make(map[string][]interface{})

	if executionMode != "" {
		f.TermsMap["execution"] = executionMode
	}

	for _, val := range values {
		f.TermsMap[field] = append(f.TermsMap[field], val)
	}

	return f
}

// Range adds a range filter for the given field.
func (f *FilterOp) Range(field string, gte interface{},
	gt interface{}, lte interface{}, lt interface{}, timeZone string) *FilterOp {

	if f.RangeMap == nil {
		f.RangeMap = make(map[string]RangeFilter)
	}

	f.RangeMap[field] = RangeFilter{
		Gte:      gte,
		Gt:       gt,
		Lte:      lte,
		Lt:       lt,
		TimeZone: timeZone}

	return f
}

func (f *FilterOp) Exists(field string) *FilterOp {
	f.ExistsProp = &PropertyPathMarker{Field: field}
	return f
}

func (f *FilterOp) Missing(field string) *FilterOp {
	f.MissingProp = &PropertyPathMarker{Field: field}
	return f
}

func (f *FilterOp) SetLimit(maxResults int) *FilterOp {
	f.Limit = &LimitFilter{Value: maxResults}
	return f
}
<commit_msg>Forgot this file change for the last commit<commit_after>// Copyright 2013 Matthew Baird
// 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 elastigo

import (
	"encoding/json"
	"fmt"
	. "github.com/araddon/gou"
)

var (
	_ = DEBUG
)

// A bool (and/or) clause
type BoolClause string

type TermExecutionMode string

const (
	TEM_DEFAULT TermExecutionMode = ""
	TEM_PLAIN                     = "plain"
	TEM_FIELD                     = "field_data"
	TEM_BOOL                      = "bool"
	TEM_AND                       = "and"
	TEM_OR                        = "or"
)

// Filter clause is either a boolClause or FilterOp
type FilterClause interface {
	String() string
}

// A wrapper to allow for custom serialization
type FilterWrap struct {
	boolClause string
	filters    []interface{}
}

func NewFilterWrap() *FilterWrap {
	return &FilterWrap{filters: make([]interface{}, 0), boolClause: "and"}
}

func (f *FilterWrap) String() string {
	return fmt.Sprintf(`fopv: %d:%v`, len(f.filters), f.filters)
}

// Custom marshalling to support the query dsl
func (f *FilterWrap) addFilters(fl []interface{}) {
	if len(fl) > 1 {
		fc := fl[0]
		switch fc.(type) {
		case BoolClause, string:
			f.boolClause = fc.(string)
			fl = fl[1:]
		}
	}
	f.filters = append(f.filters, fl...)
}

// Custom marshalling to support the query dsl
func (f *FilterWrap) MarshalJSON() ([]byte, error) {
	var root interface{}
	if len(f.filters) > 1 {
		root = map[string]interface{}{f.boolClause: f.filters}
	} else if len(f.filters) == 1 {
		root = f.filters[0]
	}
	return json.Marshal(root)
}

/*
	"filter": {
		"range": {
		  "@timestamp": {
		    "from": "2012-12-29T16:52:48+00:00",
		    "to": "2012-12-29T17:52:48+00:00"
		  }
		}
	}
	"filter": {
	    "missing": {
	        "field": "repository.name"
	    }
	}

	"filter" : {
	    "terms" : {
	        "user" : ["kimchy", "elasticsearch"],
	        "execution" : "bool",
	        "_cache": true
	    }
	}

	"filter" : {
	    "term" : { "user" : "kimchy"}
	}

	"filter" : {
	    "and" : [
	        {
	            "range" : {
	                "postDate" : {
	                    "from" : "2010-03-01",
	                    "to" : "2010-04-01"
	                }
	            }
	        },
	        {
	            "prefix" : { "name.second" : "ba" }
	        }
	    ]
	}

*/

// Filter Operation
//
//   Filter().Term("user","kimchy")
//
//   // we use variadics to allow n arguments, first is the "field" rest are values
//   Filter().Terms("user", "kimchy", "elasticsearch")
//
//   Filter().Exists("repository.name")
//
func Filter() *FilterOp {
	return &FilterOp{}
}

func CompoundFilter(fl ...interface{}) *FilterWrap {
	FilterVal := NewFilterWrap()
	FilterVal.addFilters(fl)
	return FilterVal
}

type FilterOp struct {
	TermsMap     map[string]interface{} `json:"terms,omitempty"`
	TermMap      map[string]interface{} `json:"term,omitempty"`
	RangeMap     map[string]RangeFilter `json:"range,omitempty"`
	ExistsProp   *PropertyPathMarker    `json:"exists,omitempty"`
	MissingProp  *PropertyPathMarker    `json:"missing,omitempty"`
	AndFilters   []FilterOp             `json:"and,omitempty"`
	OrFilters    []FilterOp             `json:"or,omitempty"`
	NotFilters   []FilterOp             `json:"not,omitempty"`
	Limit        *LimitFilter           `json:"limit,omitempty"`
	Type         *TypeFilter            `json:"type,omitempty"`
	Ids          *IdFilter              `json:"ids,omitempty"`
	Script       *ScriptFilter          `json:"script,omitempty"`
	GeoDist      map[string]interface{} `json:"geo_distance,omitempty"`
	GeoDistRange map[string]interface{} `json:"geo_distance_range,omitempty"`
}

type PropertyPathMarker struct {
	Field string `json:"field"`
}

type LimitFilter struct {
	Value int `json:"value"`
}

type TypeFilter struct {
	Value string `json:"value"`
}

type IdFilter struct {
	Type   string   `json:"type,omitempty"`
	Values []string `json:"values,omitempty"`
}

type ScriptFilter struct {
	Script   string                 `json:"script"`
	Params   map[string]interface{} `json:"params,omitempty"`
	IsCached bool                   `json:"_cache,omitempty"`
}

type RangeFilter struct {
	Gte      interface{} `json:"gte,omitempty"`
	Lte      interface{} `json:"lte,omitempty"`
	Gt       interface{} `json:"gt,omitempty"`
	Lt       interface{} `json:"lt,omitempty"`
	TimeZone string      `json:"time_zone,omitempty"` //Ideally this would be an int
}

type GeoLocation struct {
	Latitude  float32 `json:"lat"`
	Longitude float32 `json:"lon"`
}

type GeoField struct {
	GeoLocation
	Field string
}

// Term will add a term to the filter.
// Multiple Term filters can be added, and ES will OR them.
func (f *FilterOp) Term(field string, value interface{}) *FilterOp {
	if len(f.TermMap) == 0 {
		f.TermMap = make(map[string]interface{})
	}

	f.TermMap[field] = value
	return f
}

func (f *FilterOp) And(filter *FilterOp) *FilterOp {
	if len(f.AndFilters) == 0 {
		f.AndFilters = []FilterOp{*filter}
	} else {
		f.AndFilters = append(f.AndFilters, *filter)
	}

	return f
}

func (f *FilterOp) Or(filter *FilterOp) *FilterOp {
	if len(f.OrFilters) == 0 {
		f.OrFilters = []FilterOp{*filter}
	} else {
		f.OrFilters = append(f.OrFilters, *filter)
	}

	return f
}

func (f *FilterOp) GeoDistance(distance string, fields ...GeoField) *FilterOp {
	f.GeoDist = make(map[string]interface{})
	f.GeoDist["distance"] = distance
	for _, val := range fields {
		f.GeoDist[val.Field] = val.GeoLocation
	}

	return f
}

func (f *FilterOp) GeoDistanceRange(from string, to string, fields ...GeoField) *FilterOp {
	f.GeoDist = make(map[string]interface{})
	f.GeoDist["from"] = from
	f.GeoDist["to"] = to

	for _, val := range fields {
		f.GeoDist[val.Field] = val.GeoLocation
	}

	return f
}

// Helper to create values for the GeoDistance filters
func NewGeoField(field string, latitude float32, longitude float32) GeoField {
	return GeoField{
		GeoLocation: GeoLocation{Latitude: latitude, Longitude: longitude},
		Field:       field}
}

// Filter Terms
//
//   Filter().Terms("user","kimchy","stuff")
//	 Note: you can only have one terms clause in a filter. Use a bool filter to combine
func (f *FilterOp) Terms(field string, executionMode TermExecutionMode, values ...interface{}) *FilterOp {
	//You can only have one terms in a filter
	f.TermsMap = make(map[string]interface{})

	if executionMode != "" {
		f.TermsMap["execution"] = executionMode
	}

	f.TermsMap[field] = values

	return f
}

// Range adds a range filter for the given field.
func (f *FilterOp) Range(field string, gte interface{},
	gt interface{}, lte interface{}, lt interface{}, timeZone string) *FilterOp {

	if f.RangeMap == nil {
		f.RangeMap = make(map[string]RangeFilter)
	}

	f.RangeMap[field] = RangeFilter{
		Gte:      gte,
		Gt:       gt,
		Lte:      lte,
		Lt:       lt,
		TimeZone: timeZone}

	return f
}

func (f *FilterOp) Exists(field string) *FilterOp {
	f.ExistsProp = &PropertyPathMarker{Field: field}
	return f
}

func (f *FilterOp) Missing(field string) *FilterOp {
	f.MissingProp = &PropertyPathMarker{Field: field}
	return f
}

func (f *FilterOp) SetLimit(maxResults int) *FilterOp {
	f.Limit = &LimitFilter{Value: maxResults}
	return f
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
)

func JobDelay(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)

	returnChannel := make(chan bool)
	handler := handlerMap[`jobDelay`].(jobDelay)
	handler.input <- waitSpec{
		JobId: params.ByName(`jobid`),
		Reply: returnChannel,
	}
	<-returnChannel
	w.WriteHeader(http.StatusNoContent)
	w.Write(nil)
}

/* Read functions
 */
func ListJobs(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_list`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `job`,
		Action:     `list`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func ShowJob(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_show`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `job`,
		Action:     `show`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
		Job:        proto.Job{Id: params.ByName(`jobid`)},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func SearchJob(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_search`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	cReq := proto.NewJobFilter()
	err := DecodeJsonBody(r, &cReq)
	if err != nil {
		DispatchBadRequest(&w, err)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `jobs`,
		Action:     `search/idlist`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
		Search: msg.Filter{
			IsDetailed: cReq.Flags.Detailed,
			Job: proto.JobFilter{
				IdList: cReq.Filter.Job.IdList,
			},
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>FIX SearchJob message type<commit_after>package main

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
)

func JobDelay(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)

	returnChannel := make(chan bool)
	handler := handlerMap[`jobDelay`].(jobDelay)
	handler.input <- waitSpec{
		JobId: params.ByName(`jobid`),
		Reply: returnChannel,
	}
	<-returnChannel
	w.WriteHeader(http.StatusNoContent)
	w.Write(nil)
}

/* Read functions
 */
func ListJobs(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_list`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `job`,
		Action:     `list`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func ShowJob(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_show`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `job`,
		Action:     `show`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
		Job:        proto.Job{Id: params.ByName(`jobid`)},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func SearchJob(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	var ok, admin bool
	if ok, admin = IsAuthorized(params.ByName(`AuthenticatedUser`),
		`jobs_search`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	cReq := proto.NewJobFilter()
	err := DecodeJsonBody(r, &cReq)
	if err != nil {
		DispatchBadRequest(&w, err)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`jobs_r`].(jobsRead)
	handler.input <- msg.Request{
		Type:       `job`,
		Action:     `search/idlist`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		IsAdmin:    admin,
		Search: msg.Filter{
			IsDetailed: cReq.Flags.Detailed,
			Job: proto.JobFilter{
				IdList: cReq.Filter.Job.IdList,
			},
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>package httpbackend

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

type tokenResponse struct {
	Token string `json:"access_token"`
}
type nameResponse struct {
	Name string
}

func oauth(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	if code == "" {
		http.Error(w, "Incoming Twitch code is missing", http.StatusUnprocessableEntity)
		return
	}
	resp, err := http.PostForm("https://api.twitch.tv/kraken/oauth2/token",
		url.Values{
			"client_id":     {repos.Config.ClientID},
			"client_secret": {repos.Config.ClientSecret},
			"grant_type":    {"authorization_code"},
			"redirect_uri":  {repos.Config.AppOauthURL},
			"code":          {code}})
	//"state":         {}
	if err != nil {
		log.Println(err)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	var tokenStruct = new(tokenResponse)

	marshallError := json.NewDecoder(resp.Body).Decode(tokenStruct)
	if marshallError != nil {
		log.Println(marshallError)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	nameResp, err := http.Get("https://api.twitch.tv/kraken/user?client_id=" + repos.Config.ClientID + "&oauth_token=" + tokenStruct.Token)
	if err != nil {
		log.Println(err)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}

	var usernameStruct = new(nameResponse)
	nameMarshallError := json.NewDecoder(nameResp.Body).Decode(usernameStruct)
	if nameMarshallError != nil {
		log.Println(marshallError)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	log.Println("We got credentials of ", usernameStruct.Name)
	log.Println(nameResp.Body)

	session, err := repos.GetSession(r)
	session.Values["sessions"] = models.HTTPSession{Username: usernameStruct.Name, Key: tokenStruct.Token}
	session.Save(r, w)
	fmt.Fprintf(w, "Hello, %s!", usernameStruct.Name)

	defer resp.Body.Close()
}
<commit_msg>trying to log oauth reponse from server<commit_after>package httpbackend

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

type tokenResponse struct {
	Token string `json:"access_token"`
}
type nameResponse struct {
	Name string
}

func oauth(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	if code == "" {
		http.Error(w, "Incoming Twitch code is missing", http.StatusUnprocessableEntity)
		return
	}
	resp, err := http.PostForm("https://api.twitch.tv/kraken/oauth2/token",
		url.Values{
			"client_id":     {repos.Config.ClientID},
			"client_secret": {repos.Config.ClientSecret},
			"grant_type":    {"authorization_code"},
			"redirect_uri":  {repos.Config.AppOauthURL},
			"code":          {code}})
	//"state":         {}
	if err != nil {
		log.Println(err)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	var tokenStruct = new(tokenResponse)

	marshallError := json.NewDecoder(resp.Body).Decode(tokenStruct)
	if marshallError != nil {
		log.Println(marshallError)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	nameResp, err := http.Get("https://api.twitch.tv/kraken/user?client_id=" + repos.Config.ClientID + "&oauth_token=" + tokenStruct.Token)
	if err != nil {
		log.Println(err)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}

	var usernameStruct = new(nameResponse)
	body, err := ioutil.ReadAll(nameResp.Body)
	if err != nil {
		log.Println(body)
	}
	nameMarshallError := json.NewDecoder(nameResp.Body).Decode(usernameStruct)
	if nameMarshallError != nil {
		log.Println(marshallError)
		http.Error(w, "Twitch Error", http.StatusUnprocessableEntity)
		return
	}
	log.Println("We got credentials of ", usernameStruct.Name)
	log.Println(nameResp.Body)

	session, err := repos.GetSession(r)
	session.Values["sessions"] = models.HTTPSession{Username: usernameStruct.Name, Key: tokenStruct.Token}
	session.Save(r, w)
	fmt.Fprintf(w, "Hello, %s!", usernameStruct.Name)

	defer resp.Body.Close()
}
<|endoftext|>


<commit_before>package database

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	"github.com/go-gorp/gorp"
	"github.com/lib/pq"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

// DBConnectionFactory is a database connection factory on postgres with gorp
type DBConnectionFactory struct {
	DBDriver         string
	DBRole           string
	DBUser           string
	DBPassword       string
	DBName           string
	DBHost           string
	DBPort           int
	DBSSLMode        string
	DBTimeout        int
	DBConnectTimeout int
	DBMaxConn        int
	Database         *sql.DB
	mutex            *sync.Mutex
}

// DB returns the current sql.DB object
func (f *DBConnectionFactory) DB() *sql.DB {
	if f.Database == nil {
		if f.DBName == "" {
			return nil
		}
		newF, err := Init(f.DBUser, f.DBRole, f.DBPassword, f.DBName, f.DBHost, f.DBPort, f.DBSSLMode, f.DBConnectTimeout, f.DBTimeout, f.DBMaxConn)
		if err != nil {
			log.Error("Database> cannot init db connection : %s", err)
			return nil
		}
		*f = *newF
	}
	if err := f.Database.Ping(); err != nil {
		log.Error("Database> cannot ping db : %s", err)
		f.Database = nil
		return nil
	}
	return f.Database
}

// GetDBMap returns a gorp.DbMap pointer
func (f *DBConnectionFactory) GetDBMap() *gorp.DbMap {
	return DBMap(f.DB())
}

//Set is for tetsing purpose, we need to set manually the connection
func (f *DBConnectionFactory) Set(d *sql.DB) {
	f.Database = d
}

// Init initialize sql.DB object by checking environment variables and connecting to database
func Init(user, role, password, name, host string, port int, sslmode string, connectTimeout, timeout, maxconn int) (*DBConnectionFactory, error) {
	f := &DBConnectionFactory{
		DBDriver:         "postgres",
		DBRole:           role,
		DBUser:           user,
		DBPassword:       password,
		DBName:           name,
		DBHost:           host,
		DBPort:           port,
		DBSSLMode:        sslmode,
		DBTimeout:        timeout,
		DBConnectTimeout: connectTimeout,
		DBMaxConn:        maxconn,
		mutex:            &sync.Mutex{},
	}

	f.mutex.Lock()
	defer f.mutex.Unlock()

	// Try to close before reinit
	if f.Database != nil {
		if err := f.Database.Close(); err != nil {
			log.Error("Cannot close connection to DB : %s", err)
		}
	}

	var err error

	if f.DBUser == "" ||
		f.DBPassword == "" ||
		f.DBName == "" ||
		f.DBHost == "" ||
		f.DBPort == 0 {
		return nil, fmt.Errorf("Missing database infos")
	}

	if f.DBTimeout < 200 || f.DBTimeout > 30000 {
		f.DBTimeout = 3000
	}

	if f.DBConnectTimeout <= 0 {
		f.DBConnectTimeout = 10
	}

	// connect_timeout in seconds
	// statement_timeout in milliseconds
	dsn := f.dsn()
	f.Database, err = sql.Open(f.DBDriver, dsn)
	if err != nil {
		f.Database = nil
		log.Error("cannot open database: %s", err)
		return nil, err
	}

	if err = f.Database.Ping(); err != nil {
		f.Database = nil
		return nil, err
	}

	f.Database.SetMaxOpenConns(f.DBMaxConn)
	f.Database.SetMaxIdleConns(int(f.DBMaxConn / 2))

	// Set role if specified
	if role != "" {
		log.Debug("database> setting role %s on database", role)
		if _, err := f.Database.Exec("SET ROLE '" + role + "'"); err != nil {
			log.Error("unable to set role %s on database: %s", role, err)
			return nil, sdk.WrapError(err, "unable to set role %s", role)
		}
	}

	return f, nil
}

func (f *DBConnectionFactory) dsn() string {
	return fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%d sslmode=%s connect_timeout=%d statement_timeout=%d", f.DBUser, f.DBPassword, f.DBName, f.DBHost, f.DBPort, f.DBSSLMode, f.DBConnectTimeout, f.DBTimeout)
}

// Status returns database driver and status in a printable string
func (f *DBConnectionFactory) Status() sdk.MonitoringStatusLine {
	if f.Database == nil {
		return sdk.MonitoringStatusLine{Component: "Database Conns", Value: "No Connection", Status: sdk.MonitoringStatusAlert}
	}

	if err := f.Database.Ping(); err != nil {
		return sdk.MonitoringStatusLine{Component: "Database Conns", Value: "No Ping", Status: sdk.MonitoringStatusAlert}
	}

	return sdk.MonitoringStatusLine{Component: "Database Conns", Value: fmt.Sprintf("%d", f.Database.Stats().OpenConnections), Status: sdk.MonitoringStatusOK}
}

// Close closes the database, releasing any open resources.
func (f *DBConnectionFactory) Close() error {
	if f.Database != nil {
		return f.Database.Close()
	}
	return nil
}

// NewListener creates a new database connection dedicated to LISTEN / NOTIFY.
func (f *DBConnectionFactory) NewListener(minReconnectInterval time.Duration, maxReconnectInterval time.Duration, eventCallback pq.EventCallbackType) *pq.Listener {
	return pq.NewListener(f.dsn(), minReconnectInterval, maxReconnectInterval, eventCallback)
}
<commit_msg>fix(api): fix set statement timeout option after connect (#4196)<commit_after>package database

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	"github.com/go-gorp/gorp"
	"github.com/lib/pq"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

// DBConnectionFactory is a database connection factory on postgres with gorp
type DBConnectionFactory struct {
	DBDriver         string
	DBRole           string
	DBUser           string
	DBPassword       string
	DBName           string
	DBHost           string
	DBPort           int
	DBSSLMode        string
	DBTimeout        int
	DBConnectTimeout int
	DBMaxConn        int
	Database         *sql.DB
	mutex            *sync.Mutex
}

// DB returns the current sql.DB object
func (f *DBConnectionFactory) DB() *sql.DB {
	if f.Database == nil {
		if f.DBName == "" {
			return nil
		}
		newF, err := Init(f.DBUser, f.DBRole, f.DBPassword, f.DBName, f.DBHost, f.DBPort, f.DBSSLMode, f.DBConnectTimeout, f.DBTimeout, f.DBMaxConn)
		if err != nil {
			log.Error("Database> cannot init db connection : %s", err)
			return nil
		}
		*f = *newF
	}
	if err := f.Database.Ping(); err != nil {
		log.Error("Database> cannot ping db : %s", err)
		f.Database = nil
		return nil
	}
	return f.Database
}

// GetDBMap returns a gorp.DbMap pointer
func (f *DBConnectionFactory) GetDBMap() *gorp.DbMap {
	return DBMap(f.DB())
}

//Set is for tetsing purpose, we need to set manually the connection
func (f *DBConnectionFactory) Set(d *sql.DB) {
	f.Database = d
}

// Init initialize sql.DB object by checking environment variables and connecting to database
func Init(user, role, password, name, host string, port int, sslmode string, connectTimeout, timeout, maxconn int) (*DBConnectionFactory, error) {
	f := &DBConnectionFactory{
		DBDriver:         "postgres",
		DBRole:           role,
		DBUser:           user,
		DBPassword:       password,
		DBName:           name,
		DBHost:           host,
		DBPort:           port,
		DBSSLMode:        sslmode,
		DBTimeout:        timeout,
		DBConnectTimeout: connectTimeout,
		DBMaxConn:        maxconn,
		mutex:            &sync.Mutex{},
	}

	f.mutex.Lock()
	defer f.mutex.Unlock()

	// Try to close before reinit
	if f.Database != nil {
		if err := f.Database.Close(); err != nil {
			log.Error("Cannot close connection to DB : %s", err)
		}
	}

	var err error

	if f.DBUser == "" ||
		f.DBPassword == "" ||
		f.DBName == "" ||
		f.DBHost == "" ||
		f.DBPort == 0 {
		return nil, fmt.Errorf("Missing database infos")
	}

	if f.DBTimeout < 200 || f.DBTimeout > 30000 {
		f.DBTimeout = 3000
	}

	if f.DBConnectTimeout <= 0 {
		f.DBConnectTimeout = 10
	}

	// connect_timeout in seconds
	// statement_timeout in milliseconds
	dsn := f.dsn()
	f.Database, err = sql.Open(f.DBDriver, dsn)
	if err != nil {
		f.Database = nil
		log.Error("cannot open database: %s", err)
		return nil, err
	}

	if err = f.Database.Ping(); err != nil {
		f.Database = nil
		return nil, err
	}

	f.Database.SetMaxOpenConns(f.DBMaxConn)
	f.Database.SetMaxIdleConns(int(f.DBMaxConn / 2))

	log.Debug("database> setting statement_timeout %d on database", f.DBTimeout)
	if _, err := f.Database.Exec(fmt.Sprintf("SET statement_timeout = %d", f.DBTimeout)); err != nil {
		log.Error("unable to set statement_timeout with %d on database: %s", f.DBTimeout, err)
		return nil, sdk.WrapError(err, "unable to set statement_timeout with %d", f.DBTimeout)
	}

	// Set role if specified
	if role != "" {
		log.Debug("database> setting role %s on database", role)
		if _, err := f.Database.Exec("SET ROLE '" + role + "'"); err != nil {
			log.Error("unable to set role %s on database: %s", role, err)
			return nil, sdk.WrapError(err, "unable to set role %s", role)
		}
	}

	return f, nil
}

func (f *DBConnectionFactory) dsn() string {
	return fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%d sslmode=%s connect_timeout=%d", f.DBUser, f.DBPassword, f.DBName, f.DBHost, f.DBPort, f.DBSSLMode, f.DBConnectTimeout)
}

// Status returns database driver and status in a printable string
func (f *DBConnectionFactory) Status() sdk.MonitoringStatusLine {
	if f.Database == nil {
		return sdk.MonitoringStatusLine{Component: "Database Conns", Value: "No Connection", Status: sdk.MonitoringStatusAlert}
	}

	if err := f.Database.Ping(); err != nil {
		return sdk.MonitoringStatusLine{Component: "Database Conns", Value: "No Ping", Status: sdk.MonitoringStatusAlert}
	}

	return sdk.MonitoringStatusLine{Component: "Database Conns", Value: fmt.Sprintf("%d", f.Database.Stats().OpenConnections), Status: sdk.MonitoringStatusOK}
}

// Close closes the database, releasing any open resources.
func (f *DBConnectionFactory) Close() error {
	if f.Database != nil {
		return f.Database.Close()
	}
	return nil
}

// NewListener creates a new database connection dedicated to LISTEN / NOTIFY.
func (f *DBConnectionFactory) NewListener(minReconnectInterval time.Duration, maxReconnectInterval time.Duration, eventCallback pq.EventCallbackType) *pq.Listener {
	return pq.NewListener(f.dsn(), minReconnectInterval, maxReconnectInterval, eventCallback)
}
<|endoftext|>


<commit_before>package build

const client = `
"use strict";

exports.createClient = function(args) {
    var events = require('events');
    var channel = new events.EventEmitter();
	var http = require('http');
    var server = http.createServer(function (request, response) {
	  if (request.method!='POST') {
	    response.writeHead(404);
        response.end('');
		return;
	  }

	  var body = '';
	  request.on('data', function(chunk) { body += chunk.toString(); });
	  request.on('end', function() {
		switch (request.url) {
		case '/redirect':
		  channel.emit('redirect', body);
		  response.writeHead(204);
		  response.end('');
		  break;
		case '/error':
		  channel.emit('error', body);
		  response.writeHead(204);
		  response.end('');
		  break;
		default:
		  response.writeHead(404);
		  response.end('');
		 };
	  });
    });

    server.listen(0, '127.0.0.1', 1, function() {
        var nodeWebkitAddr = 'http://127.0.0.1:'+server.address().port;
        console.log('Listening for golang-nw on '+nodeWebkitAddr);
        startClient(channel, nodeWebkitAddr, args);
    });

	return channel;
};

function startClient(channel, nodeWebkitAddr, args) {
    var path = require('path');
    var exe = '.'+path.sep+'{{ .Bin }}';
    console.log('Using client: ' + exe);

    // Now start the client process
    var childProcess = require('child_process');

	var env = process.env;
	env['{{ .EnvVar }}'] = nodeWebkitAddr;
    var p = childProcess.spawn(exe, args, {env: env});

    p.stdout.on('data', function(data) {
        console.log(data.toString());
    });

    p.stderr.on('data', function(data) {
        console.error(data.toString());
    });

    p.on('error', function(err) {
        console.error('child error: ' + err);
        channel.emit('error', err);
    });

    p.on('close', function(code) {
        console.log('child process closed with code ' + code);
        channel.emit('close', code);
    });

    p.on('exit', function(code) {
        console.log('child process exited with code ' + code);
        channel.emit('exit', code);
    });

    channel.kill = function() {
        p.kill();
    }
};
`
<commit_msg>workaround to fix EACCES in linux<commit_after>package build

const client = `
"use strict";

exports.createClient = function(args) {
    var events = require('events');
    var channel = new events.EventEmitter();
	var http = require('http');
    var server = http.createServer(function (request, response) {
	  if (request.method!='POST') {
	    response.writeHead(404);
        response.end('');
		return;
	  }

	  var body = '';
	  request.on('data', function(chunk) { body += chunk.toString(); });
	  request.on('end', function() {
		switch (request.url) {
		case '/redirect':
		  channel.emit('redirect', body);
		  response.writeHead(204);
		  response.end('');
		  break;
		case '/error':
		  channel.emit('error', body);
		  response.writeHead(204);
		  response.end('');
		  break;
		default:
		  response.writeHead(404);
		  response.end('');
		 };
	  });
    });

    server.listen(0, '127.0.0.1', 1, function() {
        var nodeWebkitAddr = 'http://127.0.0.1:'+server.address().port;
        console.log('Listening for golang-nw on '+nodeWebkitAddr);
        startClient(channel, nodeWebkitAddr, args);
    });

	return channel;
};

function startClient(channel, nodeWebkitAddr, args) {
    var path = require('path');
    var exe = '.'+path.sep+'{{ .Bin }}';
    console.log('Using client: ' + exe);

    // Make the exe executable
    var fs = require('fs');
    fs.chmodSync(exe, '755');

    // Now start the client process
    var childProcess = require('child_process');

	var env = process.env;
	env['{{ .EnvVar }}'] = nodeWebkitAddr;
    var p = childProcess.spawn(exe, args, {env: env});

    p.stdout.on('data', function(data) {
        console.log(data.toString());
    });

    p.stderr.on('data', function(data) {
        console.error(data.toString());
    });

    p.on('error', function(err) {
        console.error('child error: ' + err);
        channel.emit('error', err);
    });

    p.on('close', function(code) {
        console.log('child process closed with code ' + code);
        channel.emit('close', code);
    });

    p.on('exit', function(code) {
        console.log('child process exited with code ' + code);
        channel.emit('exit', code);
    });

    channel.kill = function() {
        p.kill();
    }
};
`
<|endoftext|>