<commit_before>package snap

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/intelsdi-x/snap/core/ctypes"
	"github.com/intelsdi-x/snap/mgmt/rest/client"
	"github.com/intelsdi-x/snap/mgmt/rest/rbody"
	"github.com/intelsdi-x/snap/scheduler/wmap"
	"github.com/raintank/raintank-apps/task-server/model"
)

type Client struct {
	NodeName    string
	TsdbAddr    string
	ApiKey      string
	c           *client.Client
	url         *url.URL
	connected   bool
	ConnectChan chan struct{}
}

func NewClient(nodeName, tsdbAddr, apiKey string, u *url.URL) (*Client, error) {
	addr := strings.TrimSuffix(u.String(), "/")
	c, err := client.New(addr, "v1", false)
	if err != nil {
		return nil, err
	}
	return &Client{
		NodeName:    nodeName,
		TsdbAddr:    tsdbAddr,
		ApiKey:      apiKey,
		c:           c,
		url:         u,
		connected:   false,
		ConnectChan: make(chan struct{}),
	}, nil
}

func (c *Client) Run() {
	log.Info("running SnapClient supervisor.")
	ticker := time.NewTicker(time.Second)
	for range ticker.C {
		conf, err := c.GetSnapGlobalConfig()
		if err != nil {
			log.Debug("Snap server is unreachable. %s", err.Error())
			if c.connected {
				log.Error(3, "Snap server unreachable. %s", err.Error())
				c.connected = false
			}
			continue
		}
		if _, ok := conf.Table()["raintank_agent_name"]; !ok {
			err := c.SetSnapGlobalConfig()
			if err != nil {
				continue
			}
		}
		if !c.connected {
			log.Info("connected to snap server.")
			c.connected = true
			c.ConnectChan <- struct{}{}
		}
	}
}

func (c *Client) GetSnapMetrics() ([]*rbody.Metric, error) {
	resp := c.c.GetMetricCatalog()
	return resp.Catalog, resp.Err
}

func (c *Client) GetSnapTasks() ([]*rbody.ScheduledTask, error) {
	resp := c.c.GetTasks()
	var tasks []*rbody.ScheduledTask
	if resp.Err == nil {
		tasks = make([]*rbody.ScheduledTask, len(resp.ScheduledTasks))
		for i, t := range resp.ScheduledTasks {
			tasks[i] = &t
		}
	}
	return tasks, resp.Err
}

func (c *Client) RemoveSnapTask(task *rbody.ScheduledTask) error {
	stopResp := c.c.StopTask(task.ID)
	if stopResp.Err != nil {
		return stopResp.Err
	}
	removeResp := c.c.RemoveTask(task.ID)
	return removeResp.Err
}

func (c *Client) CreateSnapTask(t *model.TaskDTO, name string) (*rbody.ScheduledTask, error) {
	s := &client.Schedule{
		Type:     "simple",
		Interval: fmt.Sprintf("%ds", t.Interval),
	}
	wf := wmap.NewWorkflowMap()
	for ns, ver := range t.Metrics {
		if err := wf.CollectNode.AddMetric(ns, int(ver)); err != nil {
			return nil, err
		}
	}
	token := ""
	for ns, conf := range t.Config {
		for key, value := range conf {
			wf.CollectNode.AddConfigItem(ns, key, value)
			if key == "token" {
				token = value.(string)
			}
		}
	}
	publisher := getPublisher(
		1, //TODO: replace with actual orgId
		t.Interval,
		token,
	)
	if err := wf.CollectNode.Add(publisher); err != nil {
		return nil, err
	}

	resp := c.c.CreateTask(s, wf, name, "10s", true)
	log.Debug("%v", resp)
	var newTask rbody.ScheduledTask
	if resp.Err == nil {
		newTask = rbody.ScheduledTask(*resp.AddScheduledTask)
	}
	return &newTask, resp.Err
}

func getPublisher(orgId, interval int64, token string) *wmap.PublishWorkflowMapNode {
	return &wmap.PublishWorkflowMapNode{
		Name: "rt-hostedtsdb",
		Config: map[string]interface{}{
			"interval": interval,
			"orgId":    orgId,
		},
	}
}

func (c *Client) GetSnapGlobalConfig() (*rbody.PluginConfigItem, error) {
	resp := c.c.GetPluginConfig("", "", "")
	return resp.PluginConfigItem, resp.Err

}

func (c *Client) SetSnapGlobalConfig() error {
	agentName := ctypes.ConfigValueStr{
		Value: c.NodeName,
	}
	resp := c.c.SetPluginConfig("", "", "", "raintank_agent_name", agentName)
	if resp.Err != nil {
		return resp.Err
	}

	url, err := url.Parse(c.TsdbAddr)
	if err != nil {
		return err
	}
	tsdbUrl := ctypes.ConfigValueStr{
		Value: url.String(),
	}
	resp = c.c.SetPluginConfig("", "", "", "raintank_tsdb_url", tsdbUrl)
	if resp.Err != nil {
		return resp.Err
	}

	key := ctypes.ConfigValueStr{
		Value: c.ApiKey,
	}
	resp = c.c.SetPluginConfig("", "", "", "raintank_api_key", key)
	if resp.Err != nil {
		return resp.Err
	}
	return nil
}
<commit_msg>correct set OrgId of task sent to Snap.<commit_after>package snap

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/intelsdi-x/snap/core/ctypes"
	"github.com/intelsdi-x/snap/mgmt/rest/client"
	"github.com/intelsdi-x/snap/mgmt/rest/rbody"
	"github.com/intelsdi-x/snap/scheduler/wmap"
	"github.com/raintank/raintank-apps/task-server/model"
)

type Client struct {
	NodeName    string
	TsdbAddr    string
	ApiKey      string
	c           *client.Client
	url         *url.URL
	connected   bool
	ConnectChan chan struct{}
}

func NewClient(nodeName, tsdbAddr, apiKey string, u *url.URL) (*Client, error) {
	addr := strings.TrimSuffix(u.String(), "/")
	c, err := client.New(addr, "v1", false)
	if err != nil {
		return nil, err
	}
	return &Client{
		NodeName:    nodeName,
		TsdbAddr:    tsdbAddr,
		ApiKey:      apiKey,
		c:           c,
		url:         u,
		connected:   false,
		ConnectChan: make(chan struct{}),
	}, nil
}

func (c *Client) Run() {
	log.Info("running SnapClient supervisor.")
	ticker := time.NewTicker(time.Second)
	for range ticker.C {
		conf, err := c.GetSnapGlobalConfig()
		if err != nil {
			log.Debug("Snap server is unreachable. %s", err.Error())
			if c.connected {
				log.Error(3, "Snap server unreachable. %s", err.Error())
				c.connected = false
			}
			continue
		}
		if _, ok := conf.Table()["raintank_agent_name"]; !ok {
			err := c.SetSnapGlobalConfig()
			if err != nil {
				continue
			}
		}
		if !c.connected {
			log.Info("connected to snap server.")
			c.connected = true
			c.ConnectChan <- struct{}{}
		}
	}
}

func (c *Client) GetSnapMetrics() ([]*rbody.Metric, error) {
	resp := c.c.GetMetricCatalog()
	return resp.Catalog, resp.Err
}

func (c *Client) GetSnapTasks() ([]*rbody.ScheduledTask, error) {
	resp := c.c.GetTasks()
	var tasks []*rbody.ScheduledTask
	if resp.Err == nil {
		tasks = make([]*rbody.ScheduledTask, len(resp.ScheduledTasks))
		for i, t := range resp.ScheduledTasks {
			tasks[i] = &t
		}
	}
	return tasks, resp.Err
}

func (c *Client) RemoveSnapTask(task *rbody.ScheduledTask) error {
	stopResp := c.c.StopTask(task.ID)
	if stopResp.Err != nil {
		return stopResp.Err
	}
	removeResp := c.c.RemoveTask(task.ID)
	return removeResp.Err
}

func (c *Client) CreateSnapTask(t *model.TaskDTO, name string) (*rbody.ScheduledTask, error) {
	s := &client.Schedule{
		Type:     "simple",
		Interval: fmt.Sprintf("%ds", t.Interval),
	}
	wf := wmap.NewWorkflowMap()
	for ns, ver := range t.Metrics {
		if err := wf.CollectNode.AddMetric(ns, int(ver)); err != nil {
			return nil, err
		}
	}
	token := ""
	for ns, conf := range t.Config {
		for key, value := range conf {
			wf.CollectNode.AddConfigItem(ns, key, value)
			if key == "token" {
				token = value.(string)
			}
		}
	}
	publisher := getPublisher(
		t.OrgId,
		t.Interval,
		token,
	)
	if err := wf.CollectNode.Add(publisher); err != nil {
		return nil, err
	}

	resp := c.c.CreateTask(s, wf, name, "10s", true)
	log.Debug("%v", resp)
	var newTask rbody.ScheduledTask
	if resp.Err == nil {
		newTask = rbody.ScheduledTask(*resp.AddScheduledTask)
	}
	return &newTask, resp.Err
}

func getPublisher(orgId, interval int64, token string) *wmap.PublishWorkflowMapNode {
	return &wmap.PublishWorkflowMapNode{
		Name: "rt-hostedtsdb",
		Config: map[string]interface{}{
			"interval": interval,
			"orgId":    orgId,
		},
	}
}

func (c *Client) GetSnapGlobalConfig() (*rbody.PluginConfigItem, error) {
	resp := c.c.GetPluginConfig("", "", "")
	return resp.PluginConfigItem, resp.Err

}

func (c *Client) SetSnapGlobalConfig() error {
	agentName := ctypes.ConfigValueStr{
		Value: c.NodeName,
	}
	resp := c.c.SetPluginConfig("", "", "", "raintank_agent_name", agentName)
	if resp.Err != nil {
		return resp.Err
	}

	url, err := url.Parse(c.TsdbAddr)
	if err != nil {
		return err
	}
	tsdbUrl := ctypes.ConfigValueStr{
		Value: url.String(),
	}
	resp = c.c.SetPluginConfig("", "", "", "raintank_tsdb_url", tsdbUrl)
	if resp.Err != nil {
		return resp.Err
	}

	key := ctypes.ConfigValueStr{
		Value: c.ApiKey,
	}
	resp = c.c.SetPluginConfig("", "", "", "raintank_api_key", key)
	if resp.Err != nil {
		return resp.Err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type cipher map[string]string

var encoder cipher = map[string]string{
	"a": "u",
	"b": "q",
	"c": "z",
	"d": "n",
	"e": "o",
	"f": "b",
	"g": "s",
	"h": "x",
	"i": "a",
	"j": "d",
	"k": "y",
	"l": "p",
	"m": "r",
	"n": "h",
	"o": "e",
	"p": "w",
	"q": "v",
	"r": "c",
	"s": "t",
	"t": "l",
	"u": "i",
	"v": "f",
	"w": "g",
	"x": "j",
	"y": "m",
	"z": "k",
}

var decoder cipher = map[string]string{
	"u": "a",
	"q": "b",
	"z": "c",
	"n": "d",
	"o": "e",
	"b": "f",
	"s": "g",
	"x": "h",
	"a": "i",
	"d": "j",
	"y": "k",
	"p": "l",
	"r": "m",
	"h": "n",
	"e": "o",
	"w": "p",
	"v": "q",
	"c": "r",
	"t": "s",
	"l": "t",
	"i": "u",
	"f": "v",
	"g": "w",
	"j": "x",
	"m": "y",
	"k": "z",
}

var debug bool

func main() {
	args := os.Args

	if len(args) < 2 {
		fail()
	}

	if args[1] != "e" && args[1] != "d" {
		fail()
	}

	debug = checkFlag(args, "--debug")
	full := checkFlag(args, "--full")

	if full {
		fullDirStructure(args[1])
	} else {
		files, err := ioutil.ReadDir(".")
		if err != nil {
			fmt.Println("ERROR:", err)
			fail()
		}
		ciph := decoder
		if args[1] == "e" {
			ciph = encoder
		}

		for _, file := range files {
			printPath(file.Name(), file, ciph)
		}
	}

}

func fail() {
	fmt.Println("Usage: tis e|d [--full]")
	os.Exit(1)
}

func fullDirStructure(action string) {
	var err error = nil
	if action == "e" {
		err = filepath.Walk(".", walkEncode)
	} else {
		err = filepath.Walk(".", walkDecode)
	}

	if err != nil {
		fmt.Println("encode/decode err: ", err.Error())
	}
}

func isHidden(filename string) bool {
	if len(filename) > 1 && string(filename[0]) == "." {
		return true
	}

	return false
}

func walkDecode(path string, info os.FileInfo, err error) error {
	if err != nil {
		fmt.Printf("Error on path: %s, %s\n", path, err.Error())
		return err
	}

	return printPath(path, info, decoder)
}

func walkEncode(path string, info os.FileInfo, err error) error {
	if err != nil {
		fmt.Printf("Error on path: %s, %s\n", path, err.Error())
		return err
	}

	return printPath(path, info, encoder)
}

func printPath(path string, info os.FileInfo, c cipher) error {
	// check if this is a hidden file/directory, if so we want to skip it
	if isHidden(info.Name()) {
		if debug {
			fmt.Printf("Skipping hidden path: %s\n", path)
		}
		if info.IsDir() {
			return filepath.SkipDir
		}

		return nil
	} else {
		// translate the encoded/decoded representation of this file/dir
		// but, do not translate the file's extension (does not apply to dirs)
		translatedPath := ""
		if info.IsDir() {
			translatedPath = translate(path, c)
		} else {
			p, ext := splitExtension(path)

			translatedPath = translate(p, c)
			translatedPath += ext
		}
		fmt.Printf("%s => %s\n", path, translatedPath)
	}

	return nil
}

func splitExtension(path string) (string, string) {
	ext := filepath.Ext(path)
	if ext == "" {
		return path, ""
	}

	return strings.TrimSuffix(path, ext), ext
}

func translate(in string, mapper cipher) string {
	ret := ""

	for _, letter := range in {
		l := string(letter)
		r, ok := mapper[l]

		if ok {
			ret += r
		} else {
			ret += l
		}
	}

	return ret
}

func checkFlag(args []string, matchTerm string) bool {
	for _, arg := range args {
		if arg == matchTerm {
			return true
		}
	}

	return false
}
<commit_msg>using Go standard flag lib instead of rolling my own<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type cipher map[string]string

var encoder cipher = map[string]string{
	"a": "u",
	"b": "q",
	"c": "z",
	"d": "n",
	"e": "o",
	"f": "b",
	"g": "s",
	"h": "x",
	"i": "a",
	"j": "d",
	"k": "y",
	"l": "p",
	"m": "r",
	"n": "h",
	"o": "e",
	"p": "w",
	"q": "v",
	"r": "c",
	"s": "t",
	"t": "l",
	"u": "i",
	"v": "f",
	"w": "g",
	"x": "j",
	"y": "m",
	"z": "k",
}

var decoder cipher = map[string]string{
	"u": "a",
	"q": "b",
	"z": "c",
	"n": "d",
	"o": "e",
	"b": "f",
	"s": "g",
	"x": "h",
	"a": "i",
	"d": "j",
	"y": "k",
	"p": "l",
	"r": "m",
	"h": "n",
	"e": "o",
	"w": "p",
	"v": "q",
	"c": "r",
	"t": "s",
	"l": "t",
	"i": "u",
	"f": "v",
	"g": "w",
	"j": "x",
	"m": "y",
	"k": "z",
}

var debug = flag.Bool("debug", false, "enable debug mode")
var encode = flag.String("e", "", "encode given string")
var full = flag.String("full", "", "show full directory structure (pass e or d)")
var help = flag.Bool("h", false, "display this message")

func main() {
	flag.Parse()

	if *help {
		flag.PrintDefaults()
		os.Exit(0)
	}

	if *full != "" {
		fullDirStructure(*full)
	} else if *encode != "" {
		p, ext := splitExtension(*encode)

		translatedPath := translate(p, encoder)
		translatedPath += ext
		fmt.Println(translatedPath)
	} else {
		files, err := ioutil.ReadDir(".")
		if err != nil {
			fmt.Println("ERROR:", err)
			os.Exit(1)
		}
		ciph := decoder

		for _, file := range files {
			printPath(file.Name(), file, ciph)
		}
	}
}

func fullDirStructure(action string) {
	var err error = nil
	if action == "e" {
		err = filepath.Walk(".", walkEncode)
	} else if action == "d" {
		err = filepath.Walk(".", walkDecode)
	} else {
		fmt.Println("Please pass either e or d for --full flag")
	}

	if err != nil {
		fmt.Println("encode/decode err: ", err.Error())
	}
}

func isHidden(filename string) bool {
	if len(filename) > 1 && string(filename[0]) == "." {
		return true
	}

	return false
}

func walkDecode(path string, info os.FileInfo, err error) error {
	if err != nil {
		fmt.Printf("Error on path: %s, %s\n", path, err.Error())
		return err
	}

	return printPath(path, info, decoder)
}

func walkEncode(path string, info os.FileInfo, err error) error {
	if err != nil {
		fmt.Printf("Error on path: %s, %s\n", path, err.Error())
		return err
	}

	return printPath(path, info, encoder)
}

func printPath(path string, info os.FileInfo, c cipher) error {
	// check if this is a hidden file/directory, if so we want to skip it
	if isHidden(info.Name()) {
		if *debug {
			fmt.Printf("Skipping hidden path: %s\n", path)
		}
		if info.IsDir() {
			return filepath.SkipDir
		}

		return nil
	} else {
		// translate the encoded/decoded representation of this file/dir
		// but, do not translate the file's extension (does not apply to dirs)
		translatedPath := ""
		if info.IsDir() {
			translatedPath = translate(path, c)
		} else {
			p, ext := splitExtension(path)

			translatedPath = translate(p, c)
			translatedPath += ext
		}
		fmt.Printf("%s => %s\n", path, translatedPath)
	}

	return nil
}

func splitExtension(path string) (string, string) {
	ext := filepath.Ext(path)
	if ext == "" {
		return path, ""
	}

	return strings.TrimSuffix(path, ext), ext
}

func translate(in string, mapper cipher) string {
	ret := ""

	for _, letter := range in {
		l := string(letter)
		r, ok := mapper[l]

		if ok {
			ret += r
		} else {
			ret += l
		}
	}

	return ret
}

func checkFlag(args []string, matchTerm string) bool {
	for _, arg := range args {
		if arg == matchTerm {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package query

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
)

const (
	googleURI = "https://www.googleapis.com/customsearch/v1?%s"
)

var (
	rgxTags = regexp.MustCompile(`<[^>]*>`)
)

// GoogleSearch is used to parse the response from Google.
type GoogleSearch struct {
	Items   []GoogleSearchItem      `json:"items"`
	Info    GoogleSearchInformation `json:"searchInformation"`
	Queries GoogleQueries           `json:"queries"`
}

// GoogleSearchItem is a search result item from a google search
type GoogleSearchItem struct {
	Title        string `json:"title"`
	Snippet      string `json:"snippet"`
	Link         string `json:"link"`
	DisplayLink  string `json:"displayLink"`
	FormattedURL string `json:"formattedUrl"`

	HTMLTitle        string `json:"htmlTitle"`
	HTMLSnippet      string `json:"htmlSnippet"`
	HTMLFormattedURL string `json:"htmlFormattedUrl"`

	CacheID string `json:"cacheId"`
	Kind    string `json:"kind"`
	// pagemap ignored
}

// GoogleSearchInformation is meta about the search
type GoogleSearchInformation struct {
	TotalResults          string  `json:"totalResults"`
	SearchTime            float64 `json:"searchTime"`
	FormattedTotalResults string  `json:"formattedTotalResults"`
	FormattedSearchTime   string  `json:"formattedSearchTime"`
}

// GoogleQueries a set of queries involved in the current search query
type GoogleQueries struct {
	NextPage []GoogleQuery `json:"nextPage"`
	Request  []GoogleQuery `json:"request"`
}

// GoogleQuery is a description of a search query
type GoogleQuery struct {
	CX             string `json:"cx"`
	Title          string `json:"title"`
	TotalResults   string `json:"totalResults"`
	SearchTerms    string `json:"searchTerms"`
	Count          int    `json:"count"`
	StartIndex     int    `json:"startIndex"`
	InputEncoding  string `json:"inputEncoding"`
	OutputEncoding string `json:"outputEncoding"`
	Safe           string `json:"safe"`
}

// Google performs a query and returns a formatted result.
func Google(query string, conf *Config) (output string, err error) {
	if len(conf.GoogleSearchCXID) == 0 || len(conf.GoogleSearchAPIKey) == 0 {
		return output, errors.New("cannot use google search without google_search_api_key and google_search_cx_id")
	}

	params := make(url.Values)
	params.Set("cx", conf.GoogleSearchCXID)
	params.Set("key", conf.GoogleSearchAPIKey)
	params.Set("q", query)
	params.Set("num", "1")
	u := fmt.Sprintf(googleURI, params.Encode())

	fmt.Println(u)

	var resp *http.Response
	resp, err = http.Get(u)
	if err != nil {
		return "", err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Sprintf("\x02Google: Query returned %d", resp.StatusCode), nil
	}

	defer resp.Body.Close()

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

	var results GoogleSearch
	if err = json.Unmarshal(b, &results); err != nil {
		return "", err
	}

	if len(results.Items) == 0 {
		return "\x02Google: No results found.\x02", nil
	}

	output = fmt.Sprintf(
		"\x02Google (\x02%s results\x02):\x02 %s - %s",
		results.Info.FormattedTotalResults,
		results.Items[0].Link,
		results.Items[0].Snippet,
	)

	return output, nil
}
<commit_msg>Fix debug output<commit_after>package query

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
)

const (
	googleURI = "https://www.googleapis.com/customsearch/v1?%s"
)

var (
	rgxTags = regexp.MustCompile(`<[^>]*>`)
)

// GoogleSearch is used to parse the response from Google.
type GoogleSearch struct {
	Items   []GoogleSearchItem      `json:"items"`
	Info    GoogleSearchInformation `json:"searchInformation"`
	Queries GoogleQueries           `json:"queries"`
}

// GoogleSearchItem is a search result item from a google search
type GoogleSearchItem struct {
	Title        string `json:"title"`
	Snippet      string `json:"snippet"`
	Link         string `json:"link"`
	DisplayLink  string `json:"displayLink"`
	FormattedURL string `json:"formattedUrl"`

	HTMLTitle        string `json:"htmlTitle"`
	HTMLSnippet      string `json:"htmlSnippet"`
	HTMLFormattedURL string `json:"htmlFormattedUrl"`

	CacheID string `json:"cacheId"`
	Kind    string `json:"kind"`
	// pagemap ignored
}

// GoogleSearchInformation is meta about the search
type GoogleSearchInformation struct {
	TotalResults          string  `json:"totalResults"`
	SearchTime            float64 `json:"searchTime"`
	FormattedTotalResults string  `json:"formattedTotalResults"`
	FormattedSearchTime   string  `json:"formattedSearchTime"`
}

// GoogleQueries a set of queries involved in the current search query
type GoogleQueries struct {
	NextPage []GoogleQuery `json:"nextPage"`
	Request  []GoogleQuery `json:"request"`
}

// GoogleQuery is a description of a search query
type GoogleQuery struct {
	CX             string `json:"cx"`
	Title          string `json:"title"`
	TotalResults   string `json:"totalResults"`
	SearchTerms    string `json:"searchTerms"`
	Count          int    `json:"count"`
	StartIndex     int    `json:"startIndex"`
	InputEncoding  string `json:"inputEncoding"`
	OutputEncoding string `json:"outputEncoding"`
	Safe           string `json:"safe"`
}

// Google performs a query and returns a formatted result.
func Google(query string, conf *Config) (output string, err error) {
	if len(conf.GoogleSearchCXID) == 0 || len(conf.GoogleSearchAPIKey) == 0 {
		return output, errors.New("cannot use google search without google_search_api_key and google_search_cx_id")
	}

	params := make(url.Values)
	params.Set("cx", conf.GoogleSearchCXID)
	params.Set("key", conf.GoogleSearchAPIKey)
	params.Set("q", query)
	params.Set("num", "1")
	u := fmt.Sprintf(googleURI, params.Encode())

	var resp *http.Response
	resp, err = http.Get(u)
	if err != nil {
		return "", err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Sprintf("\x02Google: Query returned %d", resp.StatusCode), nil
	}

	defer resp.Body.Close()

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

	var results GoogleSearch
	if err = json.Unmarshal(b, &results); err != nil {
		return "", err
	}

	if len(results.Items) == 0 {
		return "\x02Google: No results found.\x02", nil
	}

	output = fmt.Sprintf(
		"\x02Google (\x02%s results\x02):\x02 %s - %s",
		results.Info.FormattedTotalResults,
		results.Items[0].Link,
		results.Items[0].Snippet,
	)

	return output, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/goauth2/oauth"
	"crypto"
	"crypto/rsa"
	"crypto/x509"
	"database/sql"
	"encoding/json"
	"encoding/pem"
	"flag"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/gorilla/mux"
	"github.com/kylelemons/go-gypsy/yaml"
	_ "github.com/mattn/go-sqlite3"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path"
	"strings"
	"sync"
	"time"
)

var (
	port       = flag.String("p", "8000", "Port number (default 8000)")
	sshPort    = "22"
	configFile = "config.yml"
	keyPath    = ".ssh/id_rsa" // The path to your private SSH key. Home directory will be prepended
)

type Host struct {
	URI             string
	LatestCommit    string
	GitHubCommitURL string
	GitHubDiffURL   *string
	ShortCommitHash string
}

type Environment struct {
	Name               string
	Deploy             string
	RepoPath           string
	Hosts              []Host
	Branch             string
	LatestGitHubCommit string
	IsDeployable       bool
}

type Project struct {
	Name         string
	GitHubURL    string
	RepoName     string
	RepoOwner    string
	Environments []Environment
}

func (h *Host) GetGitHubCommitURL(p Project) string {
	return fmt.Sprintf("%s/commit/%s", p.GitHubURL, h.LatestCommit)
}

func (h *Host) GetGitHubDiffURL(p Project, e Environment) *string {
	if h.LatestCommit != e.LatestGitHubCommit {
		s := fmt.Sprintf("%s/compare/%s...%s", p.GitHubURL, h.LatestCommit, e.LatestGitHubCommit)
		return &s
	}
	return nil
}

func (e *Environment) Deployable() bool {
	for _, h := range e.Hosts {
		if e.LatestGitHubCommit != h.LatestCommit {
			return true
		}
	}
	return false
}

func (h *Host) GetShortCommitHash() string {
	if len(h.LatestCommit) == 0 {
		return ""
	}
	return h.LatestCommit[:7]
}

func getPrivateKey(filename string) []byte {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Panic("Failed to open private key file: " + err.Error())
	}
	return content
}

type keychain struct {
	key *rsa.PrivateKey
}

func (k *keychain) Key(i int) (ssh.PublicKey, error) {
	if i != 0 {
		return nil, nil
	}
	pubkey, err := ssh.NewPublicKey(&k.key.PublicKey)
	if err != nil {
		log.Panic(err)
	}
	return pubkey, nil
}

func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
	hashFunc := crypto.SHA1
	h := hashFunc.New()
	h.Write(data)
	digest := h.Sum(nil)
	return rsa.SignPKCS1v15(rand, k.key, hashFunc, digest)
}

func remoteCmdOutput(username, hostname, privateKey, cmd string) []byte {
	block, _ := pem.Decode([]byte(privateKey))
	rsakey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
	clientKey := &keychain{rsakey}
	clientConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.ClientAuth{
			ssh.ClientAuthKeyring(clientKey),
		},
	}
	client, err := ssh.Dial("tcp", hostname, clientConfig)
	if err != nil {
		log.Println("ERROR: Failed to dial: " + err.Error())
		return []byte{}
	}
	session, err := client.NewSession()
	if err != nil {
		log.Println("ERROR: Failed to create session: " + err.Error())
		return []byte{}
	}
	defer session.Close()
	output, err := session.Output(cmd)
	if err != nil {
		log.Printf("ERROR: Failed to run cmd on host %s: %s", hostname, err.Error())
		return []byte{}
	}
	return output
}

func latestDeployedCommit(username, hostname string, e Environment) []byte {
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	privateKey := string(getPrivateKey(path.Join(usr.HomeDir, keyPath)))
	output := remoteCmdOutput(username, hostname, privateKey, fmt.Sprintf("git --git-dir=%s rev-parse HEAD", e.RepoPath))

	return output
}

func getYAMLString(n yaml.Node, key string) string {
	return strings.TrimSpace(n.(yaml.Map)[key].(yaml.Scalar).String())
}

func parseYAMLEnvironment(m yaml.Node) Environment {
	e := Environment{}
	for k, v := range m.(yaml.Map) {
		e.Name = k
		e.Branch = getYAMLString(v, "branch")
		e.RepoPath = getYAMLString(v, "repo_path")
		e.Deploy = getYAMLString(v, "deploy")
		for _, v := range v.(yaml.Map)["hosts"].(yaml.List) {
			h := Host{URI: v.(yaml.Scalar).String()}
			e.Hosts = append(e.Hosts, h)
		}
	}
	return e
}

func parseYAML() (allProjects []Project, deployUser string) {
	config, err := yaml.ReadFile(configFile)
	if err != nil {
		log.Fatal(err)
	}
	deployUser, err = config.Get("deploy_user")
	if err != nil {
		log.Fatal("config.yml is missing deploy_user: " + err.Error())
	}
	configRoot, _ := config.Root.(yaml.Map)
	projects, _ := configRoot["projects"].(yaml.List)
	allProjects = []Project{}
	for _, p := range projects {
		for _, v := range p.(yaml.Map) {
			name := getYAMLString(v, "project_name")
			repoOwner := getYAMLString(v, "repo_owner")
			repoName := getYAMLString(v, "repo_name")
			githubUrl := fmt.Sprintf("https://github.com/%s/%s", repoOwner, repoName)
			proj := Project{Name: name, GitHubURL: githubUrl, RepoName: repoName, RepoOwner: repoOwner}
			for _, v := range v.(yaml.Map)["environments"].(yaml.List) {
				proj.Environments = append(proj.Environments, parseYAMLEnvironment(v))
			}
			allProjects = append(allProjects, proj)
		}
	}
	return allProjects, deployUser
}

func getCommit(wg *sync.WaitGroup, project Project, env Environment, host Host, deployUser string, i, j int) {
	defer wg.Done()
	lc := string(latestDeployedCommit(deployUser, host.URI+":"+sshPort, env))
	host.LatestCommit = strings.TrimSpace(lc)
	project.Environments[i].Hosts[j] = host
}

//  Get the most recent commit hash on a given branch from GitHub
func getLatestGitHubCommit(wg *sync.WaitGroup, project Project, environment Environment, c *github.Client, repoOwner, repoName string, i int) {
	defer wg.Done()
	opts := &github.CommitsListOptions{SHA: environment.Branch}
	commits, _, err := c.Repositories.ListCommits(repoOwner, repoName, opts)
	if err != nil {
		log.Panic(err)
	}
	environment.LatestGitHubCommit = *commits[0].SHA
	project.Environments[i] = environment
}

func retrieveCommits(project Project, deployUser string) Project {
	// define a wait group to wait for all goroutines to finish
	var wg sync.WaitGroup
	githubToken := os.Getenv("GITHUB_API_TOKEN")
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: githubToken},
	}
	client := github.NewClient(t.Client())
	for i, environment := range project.Environments {
		for j, host := range environment.Hosts {
			// start a goroutine for SSHing on to the machine
			wg.Add(1)
			go getCommit(&wg, project, environment, host, deployUser, i, j)
		}
		wg.Add(1)
		go getLatestGitHubCommit(&wg, project, environment, client, project.RepoOwner, project.RepoName, i)
	}
	// wait for goroutines to finish
	wg.Wait()
	for i, e := range project.Environments {
		if e.Deployable() {
			e.IsDeployable = true
			project.Environments[i] = e
		}
		for j, host := range e.Hosts {
			host.GitHubCommitURL = host.GetGitHubCommitURL(project)
			host.GitHubDiffURL = host.GetGitHubDiffURL(project, e)
			host.ShortCommitHash = host.GetShortCommitHash()
			project.Environments[i].Hosts[j] = host
		}
	}
	return project
}

func insertDeployLogEntry(db sql.DB, environment, diffUrl, user string, success bool) {
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	stmt, err := tx.Prepare("insert into logs(environment, diff_url, user, success) values(?, ?, ?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	_, err = stmt.Exec(environment, diffUrl, user, success)
	if err != nil {
		log.Fatal(err)
	}
	tx.Commit()
}

func getProjectFromName(projects []Project, projectName string) *Project {
	for _, project := range projects {
		if project.Name == projectName {
			return &project
		}
	}
	return nil
}

func getEnvironmentFromName(projects []Project, projectName, environmentName string) *Environment {
	p := getProjectFromName(projects, projectName)
	for _, environment := range p.Environments {
		if environment.Name == environmentName {
			return &environment
		}
	}
	return nil
}

func getDeployCommand(projects []Project, projectName, environmentName string) []string {
	var command []string
	e := getEnvironmentFromName(projects, projectName, environmentName)
	command = strings.Split(e.Deploy, " ")
	return command
}

func createDb() {
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening or creating deploy_log.db: " + err.Error())
	}
	defer db.Close()
	sql := `create table if not exists logs (id integer not null primary key autoincrement, environment text, diff_url text, user text, timestamp datetime default current_timestamp, success boolean);`
	_, err = db.Exec(sql)
	if err != nil {
		log.Fatal("Error creating logs table: " + err.Error())
	}
}

func DeployLogHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	environment := vars["environment"]
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening sqlite db to write to deploy log: " + err.Error())
	}
	defer db.Close()
	q := fmt.Sprintf("select diff_url, user, timestamp, success from logs where environment = \"%s\"", environment)
	rows, err := db.Query(q)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		var success bool
		var diffUrl, user string
		var timestamp time.Time
		rows.Scan(&diffUrl, &user, &timestamp, &success)
	}
}

func ProjCommitsHandler(w http.ResponseWriter, r *http.Request) {
	projects, deployUser := parseYAML()
	vars := mux.Vars(r)
	projName := vars["project"]
	proj := getProjectFromName(projects, projName)

	p := retrieveCommits(*proj, deployUser)

	// Render the template
	j, err := json.Marshal(p)
	if err != nil {
		log.Panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(j)
	if err != nil {
		log.Panic(err)
	}
}

func DeployHandler(w http.ResponseWriter, r *http.Request) {
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening sqlite db to write to deploy log: " + err.Error())
	}
	defer db.Close()
	projects, _ := parseYAML()
	p := r.FormValue("project")
	env := r.FormValue("environment")
	user := r.FormValue("user")
	diffUrl := r.FormValue("diffUrl")
	success := true
	command := getDeployCommand(projects, p, env)
	var out bytes.Buffer
	cmd := exec.Command(command[0], command[1:]...)
	cmd.Stdout = &out
	err = cmd.Run()
	if err != nil {
		success = false
		log.Println("Deployment failed: " + err.Error())
	}
	insertDeployLogEntry(*db, fmt.Sprintf("%s-%s", p, env), diffUrl, user, success)
	t, err := template.New("deploy.html").ParseFiles("templates/deploy.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.Execute(w, out.String())
	if err != nil {
		log.Panic(err)
	}
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	//projects, deployUser := parseYAML()
	projects, _ := parseYAML()
	// Create and parse Template
	t, err := template.New("index.html").ParseFiles("templates/index.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.Execute(w, map[string]interface{}{"Projects": projects})
	if err != nil {
		log.Panic(err)
	}
}

func main() {
	createDb()
	flag.Parse()
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/deploy", DeployHandler)
	r.HandleFunc("/deployLog/{environment}", DeployLogHandler)
	r.HandleFunc("/commits/{project}", ProjCommitsHandler)
	fmt.Println("Running on localhost:" + *port)
	log.Fatal(http.ListenAndServe(":"+*port, r))
}
<commit_msg>remove comment<commit_after>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/goauth2/oauth"
	"crypto"
	"crypto/rsa"
	"crypto/x509"
	"database/sql"
	"encoding/json"
	"encoding/pem"
	"flag"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/gorilla/mux"
	"github.com/kylelemons/go-gypsy/yaml"
	_ "github.com/mattn/go-sqlite3"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path"
	"strings"
	"sync"
	"time"
)

var (
	port       = flag.String("p", "8000", "Port number (default 8000)")
	sshPort    = "22"
	configFile = "config.yml"
	keyPath    = ".ssh/id_rsa" // The path to your private SSH key. Home directory will be prepended
)

type Host struct {
	URI             string
	LatestCommit    string
	GitHubCommitURL string
	GitHubDiffURL   *string
	ShortCommitHash string
}

type Environment struct {
	Name               string
	Deploy             string
	RepoPath           string
	Hosts              []Host
	Branch             string
	LatestGitHubCommit string
	IsDeployable       bool
}

type Project struct {
	Name         string
	GitHubURL    string
	RepoName     string
	RepoOwner    string
	Environments []Environment
}

func (h *Host) GetGitHubCommitURL(p Project) string {
	return fmt.Sprintf("%s/commit/%s", p.GitHubURL, h.LatestCommit)
}

func (h *Host) GetGitHubDiffURL(p Project, e Environment) *string {
	if h.LatestCommit != e.LatestGitHubCommit {
		s := fmt.Sprintf("%s/compare/%s...%s", p.GitHubURL, h.LatestCommit, e.LatestGitHubCommit)
		return &s
	}
	return nil
}

func (e *Environment) Deployable() bool {
	for _, h := range e.Hosts {
		if e.LatestGitHubCommit != h.LatestCommit {
			return true
		}
	}
	return false
}

func (h *Host) GetShortCommitHash() string {
	if len(h.LatestCommit) == 0 {
		return ""
	}
	return h.LatestCommit[:7]
}

func getPrivateKey(filename string) []byte {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Panic("Failed to open private key file: " + err.Error())
	}
	return content
}

type keychain struct {
	key *rsa.PrivateKey
}

func (k *keychain) Key(i int) (ssh.PublicKey, error) {
	if i != 0 {
		return nil, nil
	}
	pubkey, err := ssh.NewPublicKey(&k.key.PublicKey)
	if err != nil {
		log.Panic(err)
	}
	return pubkey, nil
}

func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
	hashFunc := crypto.SHA1
	h := hashFunc.New()
	h.Write(data)
	digest := h.Sum(nil)
	return rsa.SignPKCS1v15(rand, k.key, hashFunc, digest)
}

func remoteCmdOutput(username, hostname, privateKey, cmd string) []byte {
	block, _ := pem.Decode([]byte(privateKey))
	rsakey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
	clientKey := &keychain{rsakey}
	clientConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.ClientAuth{
			ssh.ClientAuthKeyring(clientKey),
		},
	}
	client, err := ssh.Dial("tcp", hostname, clientConfig)
	if err != nil {
		log.Println("ERROR: Failed to dial: " + err.Error())
		return []byte{}
	}
	session, err := client.NewSession()
	if err != nil {
		log.Println("ERROR: Failed to create session: " + err.Error())
		return []byte{}
	}
	defer session.Close()
	output, err := session.Output(cmd)
	if err != nil {
		log.Printf("ERROR: Failed to run cmd on host %s: %s", hostname, err.Error())
		return []byte{}
	}
	return output
}

func latestDeployedCommit(username, hostname string, e Environment) []byte {
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	privateKey := string(getPrivateKey(path.Join(usr.HomeDir, keyPath)))
	output := remoteCmdOutput(username, hostname, privateKey, fmt.Sprintf("git --git-dir=%s rev-parse HEAD", e.RepoPath))

	return output
}

func getYAMLString(n yaml.Node, key string) string {
	return strings.TrimSpace(n.(yaml.Map)[key].(yaml.Scalar).String())
}

func parseYAMLEnvironment(m yaml.Node) Environment {
	e := Environment{}
	for k, v := range m.(yaml.Map) {
		e.Name = k
		e.Branch = getYAMLString(v, "branch")
		e.RepoPath = getYAMLString(v, "repo_path")
		e.Deploy = getYAMLString(v, "deploy")
		for _, v := range v.(yaml.Map)["hosts"].(yaml.List) {
			h := Host{URI: v.(yaml.Scalar).String()}
			e.Hosts = append(e.Hosts, h)
		}
	}
	return e
}

func parseYAML() (allProjects []Project, deployUser string) {
	config, err := yaml.ReadFile(configFile)
	if err != nil {
		log.Fatal(err)
	}
	deployUser, err = config.Get("deploy_user")
	if err != nil {
		log.Fatal("config.yml is missing deploy_user: " + err.Error())
	}
	configRoot, _ := config.Root.(yaml.Map)
	projects, _ := configRoot["projects"].(yaml.List)
	allProjects = []Project{}
	for _, p := range projects {
		for _, v := range p.(yaml.Map) {
			name := getYAMLString(v, "project_name")
			repoOwner := getYAMLString(v, "repo_owner")
			repoName := getYAMLString(v, "repo_name")
			githubUrl := fmt.Sprintf("https://github.com/%s/%s", repoOwner, repoName)
			proj := Project{Name: name, GitHubURL: githubUrl, RepoName: repoName, RepoOwner: repoOwner}
			for _, v := range v.(yaml.Map)["environments"].(yaml.List) {
				proj.Environments = append(proj.Environments, parseYAMLEnvironment(v))
			}
			allProjects = append(allProjects, proj)
		}
	}
	return allProjects, deployUser
}

func getCommit(wg *sync.WaitGroup, project Project, env Environment, host Host, deployUser string, i, j int) {
	defer wg.Done()
	lc := string(latestDeployedCommit(deployUser, host.URI+":"+sshPort, env))
	host.LatestCommit = strings.TrimSpace(lc)
	project.Environments[i].Hosts[j] = host
}

//  Get the most recent commit hash on a given branch from GitHub
func getLatestGitHubCommit(wg *sync.WaitGroup, project Project, environment Environment, c *github.Client, repoOwner, repoName string, i int) {
	defer wg.Done()
	opts := &github.CommitsListOptions{SHA: environment.Branch}
	commits, _, err := c.Repositories.ListCommits(repoOwner, repoName, opts)
	if err != nil {
		log.Panic(err)
	}
	environment.LatestGitHubCommit = *commits[0].SHA
	project.Environments[i] = environment
}

func retrieveCommits(project Project, deployUser string) Project {
	// define a wait group to wait for all goroutines to finish
	var wg sync.WaitGroup
	githubToken := os.Getenv("GITHUB_API_TOKEN")
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: githubToken},
	}
	client := github.NewClient(t.Client())
	for i, environment := range project.Environments {
		for j, host := range environment.Hosts {
			// start a goroutine for SSHing on to the machine
			wg.Add(1)
			go getCommit(&wg, project, environment, host, deployUser, i, j)
		}
		wg.Add(1)
		go getLatestGitHubCommit(&wg, project, environment, client, project.RepoOwner, project.RepoName, i)
	}
	// wait for goroutines to finish
	wg.Wait()
	for i, e := range project.Environments {
		if e.Deployable() {
			e.IsDeployable = true
			project.Environments[i] = e
		}
		for j, host := range e.Hosts {
			host.GitHubCommitURL = host.GetGitHubCommitURL(project)
			host.GitHubDiffURL = host.GetGitHubDiffURL(project, e)
			host.ShortCommitHash = host.GetShortCommitHash()
			project.Environments[i].Hosts[j] = host
		}
	}
	return project
}

func insertDeployLogEntry(db sql.DB, environment, diffUrl, user string, success bool) {
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	stmt, err := tx.Prepare("insert into logs(environment, diff_url, user, success) values(?, ?, ?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	_, err = stmt.Exec(environment, diffUrl, user, success)
	if err != nil {
		log.Fatal(err)
	}
	tx.Commit()
}

func getProjectFromName(projects []Project, projectName string) *Project {
	for _, project := range projects {
		if project.Name == projectName {
			return &project
		}
	}
	return nil
}

func getEnvironmentFromName(projects []Project, projectName, environmentName string) *Environment {
	p := getProjectFromName(projects, projectName)
	for _, environment := range p.Environments {
		if environment.Name == environmentName {
			return &environment
		}
	}
	return nil
}

func getDeployCommand(projects []Project, projectName, environmentName string) []string {
	var command []string
	e := getEnvironmentFromName(projects, projectName, environmentName)
	command = strings.Split(e.Deploy, " ")
	return command
}

func createDb() {
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening or creating deploy_log.db: " + err.Error())
	}
	defer db.Close()
	sql := `create table if not exists logs (id integer not null primary key autoincrement, environment text, diff_url text, user text, timestamp datetime default current_timestamp, success boolean);`
	_, err = db.Exec(sql)
	if err != nil {
		log.Fatal("Error creating logs table: " + err.Error())
	}
}

func DeployLogHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	environment := vars["environment"]
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening sqlite db to write to deploy log: " + err.Error())
	}
	defer db.Close()
	q := fmt.Sprintf("select diff_url, user, timestamp, success from logs where environment = \"%s\"", environment)
	rows, err := db.Query(q)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		var success bool
		var diffUrl, user string
		var timestamp time.Time
		rows.Scan(&diffUrl, &user, &timestamp, &success)
	}
}

func ProjCommitsHandler(w http.ResponseWriter, r *http.Request) {
	projects, deployUser := parseYAML()
	vars := mux.Vars(r)
	projName := vars["project"]
	proj := getProjectFromName(projects, projName)

	p := retrieveCommits(*proj, deployUser)

	// Render the template
	j, err := json.Marshal(p)
	if err != nil {
		log.Panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(j)
	if err != nil {
		log.Panic(err)
	}
}

func DeployHandler(w http.ResponseWriter, r *http.Request) {
	db, err := sql.Open("sqlite3", "./deploy_log.db")
	if err != nil {
		log.Fatal("Error opening sqlite db to write to deploy log: " + err.Error())
	}
	defer db.Close()
	projects, _ := parseYAML()
	p := r.FormValue("project")
	env := r.FormValue("environment")
	user := r.FormValue("user")
	diffUrl := r.FormValue("diffUrl")
	success := true
	command := getDeployCommand(projects, p, env)
	var out bytes.Buffer
	cmd := exec.Command(command[0], command[1:]...)
	cmd.Stdout = &out
	err = cmd.Run()
	if err != nil {
		success = false
		log.Println("Deployment failed: " + err.Error())
	}
	insertDeployLogEntry(*db, fmt.Sprintf("%s-%s", p, env), diffUrl, user, success)
	t, err := template.New("deploy.html").ParseFiles("templates/deploy.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.Execute(w, out.String())
	if err != nil {
		log.Panic(err)
	}
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	projects, _ := parseYAML()
	// Create and parse Template
	t, err := template.New("index.html").ParseFiles("templates/index.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.Execute(w, map[string]interface{}{"Projects": projects})
	if err != nil {
		log.Panic(err)
	}
}

func main() {
	createDb()
	flag.Parse()
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/deploy", DeployHandler)
	r.HandleFunc("/deployLog/{environment}", DeployLogHandler)
	r.HandleFunc("/commits/{project}", ProjCommitsHandler)
	fmt.Println("Running on localhost:" + *port)
	log.Fatal(http.ListenAndServe(":"+*port, r))
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 The libusb developers. All rights reserved.
// Project site: https://github.com/gotmc/libusb
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.

package libusb

// #cgo pkg-config: libusb-1.0
// #include <libusb.h>
import "C"
import "unsafe"

// DeviceHandle represents the libusb device handle.
type DeviceHandle struct {
	libusbDeviceHandle *C.libusb_device_handle
}

func (dh *DeviceHandle) GetStringDescriptor(
	descIndex uint8,
	langID uint16,
) (string, error) {
	var cData *C.uchar
	length := 512
	usberr := C.libusb_get_string_descriptor(
		dh.libusbDeviceHandle,
		C.uint8_t(descIndex),
		C.uint16_t(langID),
		cData,
		C.int(length),
	)
	if usberr < 0 {
		return "", ErrorCode(usberr)
	}
	data := (*C.char)(unsafe.Pointer(cData))
	return C.GoString(data), nil
}

func (dh *DeviceHandle) GetStringDescriptorASCII(
	descIndex uint8,
) (string, error) {
	length := 256
	data := make([]byte, length)
	usberr := C.libusb_get_string_descriptor_ascii(
		dh.libusbDeviceHandle,
		C.uint8_t(descIndex),
		// Unsafe pointer -> http://stackoverflow.com/a/16376039/95592
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(length),
	)
	if usberr < 0 {
		return "", ErrorCode(usberr)
	}
	return string(data), nil
}

// Close implements libusb_close to close the device handle.
func (dh *DeviceHandle) Close() error {
	C.libusb_close(dh.libusbDeviceHandle)
	return nil
}

// GetDevice implements libusb_get_device to get the underlying device for a
// handle.
// TODO(mdr): Determine if I actually need this function.
// func (dh *DeviceHandle) GetDevice() (*Device, error) {
// }

// GetConfiguration implements the libusb_get_configuration function to
// determine the bConfigurationValue of the currently active configuration.
func (dh *DeviceHandle) GetConfiguration() (int, error) {
	var configuration *C.int
	err := C.libusb_get_configuration(dh.libusbDeviceHandle, configuration)
	if err != 0 {
		return 0, ErrorCode(err)
	}
	return int(*configuration), nil
}

// SetConfiguration implements libusb_set_configuration to set the active
// configuration for the device.
func (dh *DeviceHandle) SetConfiguration(configuration int) error {
	err := C.libusb_set_configuration(dh.libusbDeviceHandle,
		C.int(configuration))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// ClaimInterface implements libusb_claim_interface to claim an interface on a
// given device handle. You must claim the interface you wish to use before you
// can perform I/O on any of its endpoints.
func (dh *DeviceHandle) ClaimInterface(interfaceNum int) error {
	err := C.libusb_claim_interface(dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// ReleaseInterface implements libusb_release_interface to release an interface
// previously claimed with libusb_claim_interface() (i.e., ClaimInterface()).
func (dh *DeviceHandle) ReleaseInterface(interfaceNum int) error {
	err := C.libusb_release_interface(dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

func (dh *DeviceHandle) SetInterfaceAltSetting(
	interfaceNum int,
	alternateSetting int,
) error {
	err := C.libusb_set_interface_alt_setting(
		dh.libusbDeviceHandle,
		C.int(interfaceNum),
		C.int(alternateSetting),
	)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// FIXME(mdr): libusb_clear_halt takes an endpoint as an unsigned char. Need to
// determine, what I should pass into this function as the endpoint.
// func (dh *DeviceHandle) ClearHalt(endpoint int) error {
// return nil
// }

// ResetDevice implements libusb_reset_device to perform a USB port reset to
// reinitialize a device.
func (dh *DeviceHandle) ResetDevice() error {
	err := C.libusb_reset_device(dh.libusbDeviceHandle)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// KernelDriverActive implements libusb_kernel_driver_active to determine if a
// kernel driver is active on an interface.
func (dh *DeviceHandle) KernelDriverActive(interfaceNum int) error {
	err := C.libusb_kernel_driver_active(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// DetachKernelDriver implements libusb_detach_kernel_driver to detach a kernel
// driver from an interface.
func (dh *DeviceHandle) DetachKernelDriver(interfaceNum int) error {
	err := C.libusb_detach_kernel_driver(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// AttachKernelDriver implements libusb_attach_kernel_driver to re-attach an
// interface's kernel driver, which was previously detached using
// libusb_detach_kernel_driver().
func (dh *DeviceHandle) AttachKernelDriver(interfaceNum int) error {
	err := C.libusb_attach_kernel_driver(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// SetAutoDetachKernelDriver implements libusb_set_auto_detach_kernel_driver to
// enable/disable libusb's automatic kernel driver detachment.
func (dh *DeviceHandle) SetAutoDetachKernelDriver(enable bool) error {
	cEnable := C.int(0)
	if enable == true {
		cEnable = C.int(1)
	}
	err := C.libusb_set_auto_detach_kernel_driver(dh.libusbDeviceHandle, cEnable)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

func (dh *DeviceHandle) BulkTransferOut(
	endpoint endpointAddress,
	data []byte,
	timeout int,
) (int, error) {
	var transferred C.int
	err := C.libusb_bulk_transfer(
		dh.libusbDeviceHandle,
		C.uchar(endpoint),
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)),
		&transferred,
		C.uint(timeout),
	)
	if err != 0 {
		return 0, ErrorCode(err)
	}
	return int(transferred), nil
}

func (dh *DeviceHandle) BulkTransferIn(
	endpoint endpointAddress,
	maxReceiveBytes int,
	timeout int,
) ([]byte, int, error) {
	data := make([]byte, maxReceiveBytes)
	var transferred C.int
	err := C.libusb_bulk_transfer(
		dh.libusbDeviceHandle,
		C.uchar(endpoint),
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)),
		&transferred,
		C.uint(timeout),
	)
	if err != 0 {
		return nil, 0, ErrorCode(err)
	}
	return data, int(transferred), nil
}
<commit_msg>Add BulkTransfer() method<commit_after>// Copyright (c) 2015 The libusb developers. All rights reserved.
// Project site: https://github.com/gotmc/libusb
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.

package libusb

// #cgo pkg-config: libusb-1.0
// #include <libusb.h>
import "C"
import "unsafe"

// DeviceHandle represents the libusb device handle.
type DeviceHandle struct {
	libusbDeviceHandle *C.libusb_device_handle
}

func (dh *DeviceHandle) GetStringDescriptor(
	descIndex uint8,
	langID uint16,
) (string, error) {
	var cData *C.uchar
	length := 512
	usberr := C.libusb_get_string_descriptor(
		dh.libusbDeviceHandle,
		C.uint8_t(descIndex),
		C.uint16_t(langID),
		cData,
		C.int(length),
	)
	if usberr < 0 {
		return "", ErrorCode(usberr)
	}
	data := (*C.char)(unsafe.Pointer(cData))
	return C.GoString(data), nil
}

func (dh *DeviceHandle) GetStringDescriptorASCII(
	descIndex uint8,
) (string, error) {
	length := 256
	data := make([]byte, length)
	usberr := C.libusb_get_string_descriptor_ascii(
		dh.libusbDeviceHandle,
		C.uint8_t(descIndex),
		// Unsafe pointer -> http://stackoverflow.com/a/16376039/95592
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(length),
	)
	if usberr < 0 {
		return "", ErrorCode(usberr)
	}
	return string(data), nil
}

// Close implements libusb_close to close the device handle.
func (dh *DeviceHandle) Close() error {
	C.libusb_close(dh.libusbDeviceHandle)
	return nil
}

// GetDevice implements libusb_get_device to get the underlying device for a
// handle.
// TODO(mdr): Determine if I actually need this function.
// func (dh *DeviceHandle) GetDevice() (*Device, error) {
// }

// GetConfiguration implements the libusb_get_configuration function to
// determine the bConfigurationValue of the currently active configuration.
func (dh *DeviceHandle) GetConfiguration() (int, error) {
	var configuration *C.int
	err := C.libusb_get_configuration(dh.libusbDeviceHandle, configuration)
	if err != 0 {
		return 0, ErrorCode(err)
	}
	return int(*configuration), nil
}

// SetConfiguration implements libusb_set_configuration to set the active
// configuration for the device.
func (dh *DeviceHandle) SetConfiguration(configuration int) error {
	err := C.libusb_set_configuration(dh.libusbDeviceHandle,
		C.int(configuration))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// ClaimInterface implements libusb_claim_interface to claim an interface on a
// given device handle. You must claim the interface you wish to use before you
// can perform I/O on any of its endpoints.
func (dh *DeviceHandle) ClaimInterface(interfaceNum int) error {
	err := C.libusb_claim_interface(dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// ReleaseInterface implements libusb_release_interface to release an interface
// previously claimed with libusb_claim_interface() (i.e., ClaimInterface()).
func (dh *DeviceHandle) ReleaseInterface(interfaceNum int) error {
	err := C.libusb_release_interface(dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

func (dh *DeviceHandle) SetInterfaceAltSetting(
	interfaceNum int,
	alternateSetting int,
) error {
	err := C.libusb_set_interface_alt_setting(
		dh.libusbDeviceHandle,
		C.int(interfaceNum),
		C.int(alternateSetting),
	)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// FIXME(mdr): libusb_clear_halt takes an endpoint as an unsigned char. Need to
// determine, what I should pass into this function as the endpoint.
// func (dh *DeviceHandle) ClearHalt(endpoint int) error {
// return nil
// }

// ResetDevice implements libusb_reset_device to perform a USB port reset to
// reinitialize a device.
func (dh *DeviceHandle) ResetDevice() error {
	err := C.libusb_reset_device(dh.libusbDeviceHandle)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// KernelDriverActive implements libusb_kernel_driver_active to determine if a
// kernel driver is active on an interface.
func (dh *DeviceHandle) KernelDriverActive(interfaceNum int) error {
	err := C.libusb_kernel_driver_active(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// DetachKernelDriver implements libusb_detach_kernel_driver to detach a kernel
// driver from an interface.
func (dh *DeviceHandle) DetachKernelDriver(interfaceNum int) error {
	err := C.libusb_detach_kernel_driver(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// AttachKernelDriver implements libusb_attach_kernel_driver to re-attach an
// interface's kernel driver, which was previously detached using
// libusb_detach_kernel_driver().
func (dh *DeviceHandle) AttachKernelDriver(interfaceNum int) error {
	err := C.libusb_attach_kernel_driver(
		dh.libusbDeviceHandle, C.int(interfaceNum))
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

// SetAutoDetachKernelDriver implements libusb_set_auto_detach_kernel_driver to
// enable/disable libusb's automatic kernel driver detachment.
func (dh *DeviceHandle) SetAutoDetachKernelDriver(enable bool) error {
	cEnable := C.int(0)
	if enable == true {
		cEnable = C.int(1)
	}
	err := C.libusb_set_auto_detach_kernel_driver(dh.libusbDeviceHandle, cEnable)
	if err != 0 {
		return ErrorCode(err)
	}
	return nil
}

func (dh *DeviceHandle) BulkTransfer(
	endpoint endpointAddress,
	data []byte,
	length int,
	timeout int,
) (int, error) {
	var transferred C.int
	err := C.libusb_bulk_transfer(
		dh.libusbDeviceHandle,
		C.uchar(endpoint),
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(length),
		&transferred,
		C.uint(timeout),
	)
	if err != 0 {
		return 0, ErrorCode(err)
	}
	return int(transferred), nil
}

func (dh *DeviceHandle) BulkTransferOut(
	endpoint endpointAddress,
	data []byte,
	timeout int,
) (int, error) {
	var transferred C.int
	err := C.libusb_bulk_transfer(
		dh.libusbDeviceHandle,
		C.uchar(endpoint),
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)),
		&transferred,
		C.uint(timeout),
	)
	if err != 0 {
		return 0, ErrorCode(err)
	}
	return int(transferred), nil
}

func (dh *DeviceHandle) BulkTransferIn(
	endpoint endpointAddress,
	maxReceiveBytes int,
	timeout int,
) ([]byte, int, error) {
	data := make([]byte, maxReceiveBytes)
	var transferred C.int
	err := C.libusb_bulk_transfer(
		dh.libusbDeviceHandle,
		C.uchar(endpoint),
		(*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)),
		&transferred,
		C.uint(timeout),
	)
	if err != 0 {
		return nil, 0, ErrorCode(err)
	}
	return data, int(transferred), nil
}
<|endoftext|>


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

//go:generate bash -c "cd $GOPATH/src && protoc --proto_path=. --go_out=Mgithub.com/google/protobuf/src/google/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,plugins=grpc:. github.com/openconfig/reference/rpc/gnmi/gnmi.proto"
<commit_msg>Update gen.go<commit_after>//
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gnmi

//go:generate sh -c "cd $GOPATH/src && protoc --proto_path=. --go_out=Mgithub.com/google/protobuf/src/google/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,plugins=grpc:. github.com/openconfig/reference/rpc/gnmi/gnmi.proto"
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"encoding/gob"
	"encoding/json"
	"io"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	garden_api "github.com/cloudfoundry-incubator/garden/api"
	"github.com/codegangsta/cli"
	"github.com/concourse/atc/api/resources"
	"github.com/concourse/atc/api/routes"
	thijack "github.com/concourse/turbine/api/hijack"
	"github.com/kr/pty"
	"github.com/pkg/term"
	"github.com/tedsuo/rata"
)

func hijack(c *cli.Context) {
	atc := c.GlobalString("atcURL")
	insecure := c.GlobalBool("insecure")

	reqGenerator := rata.NewRequestGenerator(atc, routes.Routes)

	argv := c.Args()

	var path string
	var args []string

	switch len(argv) {
	case 0:
		path = "bash"
	case 1:
		path = argv[0]
	default:
		path = argv[0]
		args = argv[1:]
	}

	var ttySpec *garden_api.TTYSpec

	rows, cols, err := pty.Getsize(os.Stdin)
	if err == nil {
		ttySpec = &garden_api.TTYSpec{
			WindowSize: &garden_api.WindowSize{
				Columns: cols,
				Rows:    rows,
			},
		}
	}

	spec := garden_api.ProcessSpec{
		Path: path,
		Args: args,
		Env:  []string{"TERM=" + os.Getenv("TERM")},

		Privileged: true,
		TTY:        ttySpec,
	}

	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
	}

	client := &http.Client{Transport: transport}

	build := getBuild(c, client, reqGenerator)

	payload, err := json.Marshal(spec)
	if err != nil {
		log.Fatalln("failed to marshal build spec:", err)
	}

	hijackReq, err := reqGenerator.CreateRequest(
		routes.HijackBuild,
		rata.Params{"build_id": strconv.Itoa(build.ID)},
		bytes.NewBuffer(payload),
	)
	if err != nil {
		log.Fatalln("failed to create hijack request:", err)
	}

	if hijackReq.URL.User != nil {
		hijackReq.Header.Add("Authorization", basicAuth(hijackReq.URL.User))
		hijackReq.URL.User = nil
	}

	conn, err := net.Dial("tcp", hijackReq.URL.Host)
	if err != nil {
		log.Fatalln("failed to dial hijack endpoint:", err)
	}

	clientConn := httputil.NewClientConn(conn, nil)

	resp, err := clientConn.Do(hijackReq)
	if err != nil {
		log.Fatalln("failed to hijack:", err)
	}

	if resp.StatusCode != http.StatusOK {
		log.Println("bad response when hijacking:")
		resp.Body.Close()
		resp.Write(os.Stderr)
		os.Exit(1)
	}

	cconn, cbr := clientConn.Hijack()

	term, err := term.Open(os.Stdin.Name())
	if err != nil {
		log.Fatalln("failed to open terminal:", err)
	}

	err = term.SetRaw()
	if err != nil {
		log.Fatalln("failed to set raw:", term)
	}

	defer term.Restore()

	encoder := gob.NewEncoder(cconn)

	resized := make(chan os.Signal, 10)
	signal.Notify(resized, syscall.SIGWINCH)

	go func() {
		for {
			<-resized
			sendSize(encoder)
		}
	}()

	go io.Copy(&stdinWriter{encoder}, term)

	io.Copy(os.Stdout, cbr)
}

func getBuild(ctx *cli.Context, client *http.Client, reqGenerator *rata.RequestGenerator) resources.Build {
	jobName := ctx.String("job")
	buildName := ctx.String("build")

	if jobName != "" && buildName != "" {
		buildReq, err := reqGenerator.CreateRequest(
			routes.GetJobBuild,
			rata.Params{
				"job_name":   jobName,
				"build_name": buildName,
			},
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		buildResp, err := client.Do(buildReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if buildResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting build:")
			buildResp.Body.Close()
			buildResp.Write(os.Stderr)
			os.Exit(1)
		}

		var build resources.Build
		err = json.NewDecoder(buildResp.Body).Decode(&build)
		if err != nil {
			log.Fatalln("failed to decode job:", err)
		}

		return build
	} else if jobName != "" {
		jobReq, err := reqGenerator.CreateRequest(
			routes.GetJob,
			rata.Params{"job_name": ctx.String("job")},
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		jobResp, err := client.Do(jobReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if jobResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting job:")
			jobResp.Body.Close()
			jobResp.Write(os.Stderr)
			os.Exit(1)
		}

		var job resources.Job
		err = json.NewDecoder(jobResp.Body).Decode(&job)
		if err != nil {
			log.Fatalln("failed to decode job:", err)
		}

		if job.NextBuild != nil {
			return *job.NextBuild
		} else if job.FinishedBuild != nil {
			return *job.FinishedBuild
		} else {
			println("no job builds to hijack")
			os.Exit(1)
		}
	} else {
		buildsReq, err := reqGenerator.CreateRequest(
			routes.ListBuilds,
			nil,
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		buildsResp, err := client.Do(buildsReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if buildsResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting builds:")
			buildsResp.Body.Close()
			buildsResp.Write(os.Stderr)
			os.Exit(1)
		}

		var builds []resources.Build
		err = json.NewDecoder(buildsResp.Body).Decode(&builds)
		if err != nil {
			log.Fatalln("failed to decode builds:", err)
		}

		if len(builds) == 0 {
			println("no builds to hijack")
			os.Exit(1)
		}

		return builds[0]
	}

	panic("unreachable")
}

func sendSize(enc *gob.Encoder) {
	rows, cols, err := pty.Getsize(os.Stdin)
	if err == nil {
		enc.Encode(thijack.ProcessPayload{
			TTYSpec: &garden_api.TTYSpec{
				WindowSize: &garden_api.WindowSize{
					Columns: cols,
					Rows:    rows,
				},
			},
		})
	}
}

type stdinWriter struct {
	enc *gob.Encoder
}

func (w *stdinWriter) Write(d []byte) (int, error) {
	err := w.enc.Encode(thijack.ProcessPayload{
		Stdin: d,
	})
	if err != nil {
		return 0, err
	}

	return len(d), nil
}

func basicAuth(user *url.Userinfo) string {
	username := user.Username()
	password, _ := user.Password()
	return "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password))
}
<commit_msg>don't blow up if stdin is not a tty<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"encoding/gob"
	"encoding/json"
	"io"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	garden_api "github.com/cloudfoundry-incubator/garden/api"
	"github.com/codegangsta/cli"
	"github.com/concourse/atc/api/resources"
	"github.com/concourse/atc/api/routes"
	thijack "github.com/concourse/turbine/api/hijack"
	"github.com/kr/pty"
	"github.com/pkg/term"
	"github.com/tedsuo/rata"
)

func hijack(c *cli.Context) {
	atc := c.GlobalString("atcURL")
	insecure := c.GlobalBool("insecure")

	reqGenerator := rata.NewRequestGenerator(atc, routes.Routes)

	argv := c.Args()

	var path string
	var args []string

	switch len(argv) {
	case 0:
		path = "bash"
	case 1:
		path = argv[0]
	default:
		path = argv[0]
		args = argv[1:]
	}

	var ttySpec *garden_api.TTYSpec

	rows, cols, err := pty.Getsize(os.Stdin)
	if err == nil {
		ttySpec = &garden_api.TTYSpec{
			WindowSize: &garden_api.WindowSize{
				Columns: cols,
				Rows:    rows,
			},
		}
	}

	spec := garden_api.ProcessSpec{
		Path: path,
		Args: args,
		Env:  []string{"TERM=" + os.Getenv("TERM")},

		Privileged: true,
		TTY:        ttySpec,
	}

	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
	}

	client := &http.Client{Transport: transport}

	build := getBuild(c, client, reqGenerator)

	payload, err := json.Marshal(spec)
	if err != nil {
		log.Fatalln("failed to marshal build spec:", err)
	}

	hijackReq, err := reqGenerator.CreateRequest(
		routes.HijackBuild,
		rata.Params{"build_id": strconv.Itoa(build.ID)},
		bytes.NewBuffer(payload),
	)
	if err != nil {
		log.Fatalln("failed to create hijack request:", err)
	}

	if hijackReq.URL.User != nil {
		hijackReq.Header.Add("Authorization", basicAuth(hijackReq.URL.User))
		hijackReq.URL.User = nil
	}

	conn, err := net.Dial("tcp", hijackReq.URL.Host)
	if err != nil {
		log.Fatalln("failed to dial hijack endpoint:", err)
	}

	clientConn := httputil.NewClientConn(conn, nil)

	resp, err := clientConn.Do(hijackReq)
	if err != nil {
		log.Fatalln("failed to hijack:", err)
	}

	if resp.StatusCode != http.StatusOK {
		log.Println("bad response when hijacking:")
		resp.Body.Close()
		resp.Write(os.Stderr)
		os.Exit(1)
	}

	cconn, cbr := clientConn.Hijack()

	var in io.Reader

	term, err := term.Open(os.Stdin.Name())
	if err == nil {
		err = term.SetRaw()
		if err != nil {
			log.Fatalln("failed to set raw:", term)
		}

		defer term.Restore()

		in = term
	} else {
		in = os.Stdin
	}

	encoder := gob.NewEncoder(cconn)

	resized := make(chan os.Signal, 10)
	signal.Notify(resized, syscall.SIGWINCH)

	go func() {
		for {
			<-resized
			sendSize(encoder)
		}
	}()

	go io.Copy(&stdinWriter{encoder}, in)

	io.Copy(os.Stdout, cbr)
}

func getBuild(ctx *cli.Context, client *http.Client, reqGenerator *rata.RequestGenerator) resources.Build {
	jobName := ctx.String("job")
	buildName := ctx.String("build")

	if jobName != "" && buildName != "" {
		buildReq, err := reqGenerator.CreateRequest(
			routes.GetJobBuild,
			rata.Params{
				"job_name":   jobName,
				"build_name": buildName,
			},
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		buildResp, err := client.Do(buildReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if buildResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting build:")
			buildResp.Body.Close()
			buildResp.Write(os.Stderr)
			os.Exit(1)
		}

		var build resources.Build
		err = json.NewDecoder(buildResp.Body).Decode(&build)
		if err != nil {
			log.Fatalln("failed to decode job:", err)
		}

		return build
	} else if jobName != "" {
		jobReq, err := reqGenerator.CreateRequest(
			routes.GetJob,
			rata.Params{"job_name": ctx.String("job")},
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		jobResp, err := client.Do(jobReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if jobResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting job:")
			jobResp.Body.Close()
			jobResp.Write(os.Stderr)
			os.Exit(1)
		}

		var job resources.Job
		err = json.NewDecoder(jobResp.Body).Decode(&job)
		if err != nil {
			log.Fatalln("failed to decode job:", err)
		}

		if job.NextBuild != nil {
			return *job.NextBuild
		} else if job.FinishedBuild != nil {
			return *job.FinishedBuild
		} else {
			println("no job builds to hijack")
			os.Exit(1)
		}
	} else {
		buildsReq, err := reqGenerator.CreateRequest(
			routes.ListBuilds,
			nil,
			nil,
		)
		if err != nil {
			log.Fatalln("failed to create request", err)
		}

		buildsResp, err := client.Do(buildsReq)
		if err != nil {
			log.Fatalln("failed to get builds:", err)
		}

		if buildsResp.StatusCode != http.StatusOK {
			log.Println("bad response when getting builds:")
			buildsResp.Body.Close()
			buildsResp.Write(os.Stderr)
			os.Exit(1)
		}

		var builds []resources.Build
		err = json.NewDecoder(buildsResp.Body).Decode(&builds)
		if err != nil {
			log.Fatalln("failed to decode builds:", err)
		}

		if len(builds) == 0 {
			println("no builds to hijack")
			os.Exit(1)
		}

		return builds[0]
	}

	panic("unreachable")
}

func sendSize(enc *gob.Encoder) {
	rows, cols, err := pty.Getsize(os.Stdin)
	if err == nil {
		enc.Encode(thijack.ProcessPayload{
			TTYSpec: &garden_api.TTYSpec{
				WindowSize: &garden_api.WindowSize{
					Columns: cols,
					Rows:    rows,
				},
			},
		})
	}
}

type stdinWriter struct {
	enc *gob.Encoder
}

func (w *stdinWriter) Write(d []byte) (int, error) {
	err := w.enc.Encode(thijack.ProcessPayload{
		Stdin: d,
	})
	if err != nil {
		return 0, err
	}

	return len(d), nil
}

func basicAuth(user *url.Userinfo) string {
	username := user.Username()
	password, _ := user.Password()
	return "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password))
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"
	"strconv"

	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/terraform/config"
)

// EvalApply is an EvalNode implementation that writes the diff to
// the full diff.
type EvalApply struct {
	Info      *InstanceInfo
	State     **InstanceState
	Diff      **InstanceDiff
	Provider  *ResourceProvider
	Output    **InstanceState
	CreateNew *bool
	Error     *error
}

// TODO: test
func (n *EvalApply) Eval(ctx EvalContext) (interface{}, error) {
	diff := *n.Diff
	provider := *n.Provider
	state := *n.State

	// If we have no diff, we have nothing to do!
	if diff.Empty() {
		log.Printf(
			"[DEBUG] apply: %s: diff is empty, doing nothing.", n.Info.Id)
		return nil, nil
	}

	// Remove any output values from the diff
	for k, ad := range diff.CopyAttributes() {
		if ad.Type == DiffAttrOutput {
			diff.DelAttribute(k)
		}
	}

	// If the state is nil, make it non-nil
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	// Flag if we're creating a new instance
	if n.CreateNew != nil {
		*n.CreateNew = state.ID == "" && !diff.GetDestroy() || diff.RequiresNew()
	}

	// With the completed diff, apply!
	log.Printf("[DEBUG] apply: %s: executing Apply", n.Info.Id)
	state, err := provider.Apply(n.Info, state, diff)
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	// Force the "id" attribute to be our ID
	if state.ID != "" {
		state.Attributes["id"] = state.ID
	}

	// If the value is the unknown variable value, then it is an error.
	// In this case we record the error and remove it from the state
	for ak, av := range state.Attributes {
		if av == config.UnknownVariableValue {
			err = multierror.Append(err, fmt.Errorf(
				"Attribute with unknown value: %s", ak))
			delete(state.Attributes, ak)
		}
	}

	// Write the final state
	if n.Output != nil {
		*n.Output = state
	}

	// If there are no errors, then we append it to our output error
	// if we have one, otherwise we just output it.
	if err != nil {
		if n.Error != nil {
			helpfulErr := fmt.Errorf("%s: %s", n.Info.Id, err.Error())
			*n.Error = multierror.Append(*n.Error, helpfulErr)
		} else {
			return nil, err
		}
	}

	return nil, nil
}

// EvalApplyPre is an EvalNode implementation that does the pre-Apply work
type EvalApplyPre struct {
	Info  *InstanceInfo
	State **InstanceState
	Diff  **InstanceDiff
}

// TODO: test
func (n *EvalApplyPre) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State
	diff := *n.Diff

	// If the state is nil, make it non-nil
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	if resourceHasUserVisibleApply(n.Info) {
		// Call post-apply hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PreApply(n.Info, state, diff)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, nil
}

// EvalApplyPost is an EvalNode implementation that does the post-Apply work
type EvalApplyPost struct {
	Info  *InstanceInfo
	State **InstanceState
	Error *error
}

// TODO: test
func (n *EvalApplyPost) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	if resourceHasUserVisibleApply(n.Info) {
		// Call post-apply hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostApply(n.Info, state, *n.Error)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, *n.Error
}

// resourceHasUserVisibleApply returns true if the given resource is one where
// apply actions should be exposed to the user.
//
// Certain resources do apply actions only as an implementation detail, so
// these should not be advertised to code outside of this package.
func resourceHasUserVisibleApply(info *InstanceInfo) bool {
	addr := info.ResourceAddress()

	// Only managed resources have user-visible apply actions.
	// In particular, this excludes data resources since we "apply" these
	// only as an implementation detail of removing them from state when
	// they are destroyed. (When reading, they don't get here at all because
	// we present them as "Refresh" actions.)
	return addr.Mode == config.ManagedResourceMode
}

// EvalApplyProvisioners is an EvalNode implementation that executes
// the provisioners for a resource.
//
// TODO(mitchellh): This should probably be split up into a more fine-grained
// ApplyProvisioner (single) that is looped over.
type EvalApplyProvisioners struct {
	Info           *InstanceInfo
	State          **InstanceState
	Resource       *config.Resource
	InterpResource *Resource
	CreateNew      *bool
	Error          *error

	// When is the type of provisioner to run at this point
	When config.ProvisionerWhen
}

// TODO: test
func (n *EvalApplyProvisioners) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	if n.CreateNew != nil && !*n.CreateNew {
		// If we're not creating a new resource, then don't run provisioners
		return nil, nil
	}

	provs := n.filterProvisioners()
	if len(provs) == 0 {
		// We have no provisioners, so don't do anything
		return nil, nil
	}

	// taint tells us whether to enable tainting.
	taint := n.When == config.ProvisionerWhenCreate

	if n.Error != nil && *n.Error != nil {
		if taint {
			state.Tainted = true
		}

		// We're already tainted, so just return out
		return nil, nil
	}

	{
		// Call pre hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PreProvisionResource(n.Info, state)
		})
		if err != nil {
			return nil, err
		}
	}

	// If there are no errors, then we append it to our output error
	// if we have one, otherwise we just output it.
	err := n.apply(ctx, provs)
	if err != nil {
		if taint {
			state.Tainted = true
		}

		if n.Error != nil {
			*n.Error = multierror.Append(*n.Error, err)
		} else {
			return nil, err
		}
	}

	{
		// Call post hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostProvisionResource(n.Info, state)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, nil
}

// filterProvisioners filters the provisioners on the resource to only
// the provisioners specified by the "when" option.
func (n *EvalApplyProvisioners) filterProvisioners() []*config.Provisioner {
	// Fast path the zero case
	if n.Resource == nil {
		return nil
	}

	if len(n.Resource.Provisioners) == 0 {
		return nil
	}

	result := make([]*config.Provisioner, 0, len(n.Resource.Provisioners))
	for _, p := range n.Resource.Provisioners {
		if p.When == n.When {
			result = append(result, p)
		}
	}

	return result
}

func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*config.Provisioner) error {
	state := *n.State

	// Store the original connection info, restore later
	origConnInfo := state.Ephemeral.ConnInfo
	defer func() {
		state.Ephemeral.ConnInfo = origConnInfo
	}()

	for _, prov := range provs {
		// Get the provisioner
		provisioner := ctx.Provisioner(prov.Type)

		// Interpolate the provisioner config
		provConfig, err := ctx.Interpolate(prov.RawConfig.Copy(), n.InterpResource)
		if err != nil {
			return err
		}

		// Interpolate the conn info, since it may contain variables
		connInfo, err := ctx.Interpolate(prov.ConnInfo.Copy(), n.InterpResource)
		if err != nil {
			return err
		}

		// Merge the connection information
		overlay := make(map[string]string)
		if origConnInfo != nil {
			for k, v := range origConnInfo {
				overlay[k] = v
			}
		}
		for k, v := range connInfo.Config {
			switch vt := v.(type) {
			case string:
				overlay[k] = vt
			case int64:
				overlay[k] = strconv.FormatInt(vt, 10)
			case int32:
				overlay[k] = strconv.FormatInt(int64(vt), 10)
			case int:
				overlay[k] = strconv.FormatInt(int64(vt), 10)
			case float32:
				overlay[k] = strconv.FormatFloat(float64(vt), 'f', 3, 32)
			case float64:
				overlay[k] = strconv.FormatFloat(vt, 'f', 3, 64)
			case bool:
				overlay[k] = strconv.FormatBool(vt)
			default:
				overlay[k] = fmt.Sprintf("%v", vt)
			}
		}
		state.Ephemeral.ConnInfo = overlay

		{
			// Call pre hook
			err := ctx.Hook(func(h Hook) (HookAction, error) {
				return h.PreProvision(n.Info, prov.Type)
			})
			if err != nil {
				return err
			}
		}

		// The output function
		outputFn := func(msg string) {
			ctx.Hook(func(h Hook) (HookAction, error) {
				h.ProvisionOutput(n.Info, prov.Type, msg)
				return HookActionContinue, nil
			})
		}

		// Invoke the Provisioner
		output := CallbackUIOutput{OutputFn: outputFn}
		applyErr := provisioner.Apply(&output, state, provConfig)

		// Call post hook
		hookErr := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostProvision(n.Info, prov.Type, applyErr)
		})

		// Handle the error before we deal with the hook
		if applyErr != nil {
			// Determine failure behavior
			switch prov.OnFailure {
			case config.ProvisionerOnFailureContinue:
				log.Printf(
					"[INFO] apply: %s [%s]: error during provision, continue requested",
					n.Info.Id, prov.Type)

			case config.ProvisionerOnFailureFail:
				return applyErr
			}
		}

		// Deal with the hook
		if hookErr != nil {
			return hookErr
		}
	}

	return nil

}
<commit_msg>return provisioner Apply errors<commit_after>package terraform

import (
	"fmt"
	"log"
	"strconv"

	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/terraform/config"
)

// EvalApply is an EvalNode implementation that writes the diff to
// the full diff.
type EvalApply struct {
	Info      *InstanceInfo
	State     **InstanceState
	Diff      **InstanceDiff
	Provider  *ResourceProvider
	Output    **InstanceState
	CreateNew *bool
	Error     *error
}

// TODO: test
func (n *EvalApply) Eval(ctx EvalContext) (interface{}, error) {
	diff := *n.Diff
	provider := *n.Provider
	state := *n.State

	// If we have no diff, we have nothing to do!
	if diff.Empty() {
		log.Printf(
			"[DEBUG] apply: %s: diff is empty, doing nothing.", n.Info.Id)
		return nil, nil
	}

	// Remove any output values from the diff
	for k, ad := range diff.CopyAttributes() {
		if ad.Type == DiffAttrOutput {
			diff.DelAttribute(k)
		}
	}

	// If the state is nil, make it non-nil
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	// Flag if we're creating a new instance
	if n.CreateNew != nil {
		*n.CreateNew = state.ID == "" && !diff.GetDestroy() || diff.RequiresNew()
	}

	// With the completed diff, apply!
	log.Printf("[DEBUG] apply: %s: executing Apply", n.Info.Id)
	state, err := provider.Apply(n.Info, state, diff)
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	// Force the "id" attribute to be our ID
	if state.ID != "" {
		state.Attributes["id"] = state.ID
	}

	// If the value is the unknown variable value, then it is an error.
	// In this case we record the error and remove it from the state
	for ak, av := range state.Attributes {
		if av == config.UnknownVariableValue {
			err = multierror.Append(err, fmt.Errorf(
				"Attribute with unknown value: %s", ak))
			delete(state.Attributes, ak)
		}
	}

	// Write the final state
	if n.Output != nil {
		*n.Output = state
	}

	// If there are no errors, then we append it to our output error
	// if we have one, otherwise we just output it.
	if err != nil {
		if n.Error != nil {
			helpfulErr := fmt.Errorf("%s: %s", n.Info.Id, err.Error())
			*n.Error = multierror.Append(*n.Error, helpfulErr)
		} else {
			return nil, err
		}
	}

	return nil, nil
}

// EvalApplyPre is an EvalNode implementation that does the pre-Apply work
type EvalApplyPre struct {
	Info  *InstanceInfo
	State **InstanceState
	Diff  **InstanceDiff
}

// TODO: test
func (n *EvalApplyPre) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State
	diff := *n.Diff

	// If the state is nil, make it non-nil
	if state == nil {
		state = new(InstanceState)
	}
	state.init()

	if resourceHasUserVisibleApply(n.Info) {
		// Call post-apply hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PreApply(n.Info, state, diff)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, nil
}

// EvalApplyPost is an EvalNode implementation that does the post-Apply work
type EvalApplyPost struct {
	Info  *InstanceInfo
	State **InstanceState
	Error *error
}

// TODO: test
func (n *EvalApplyPost) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	if resourceHasUserVisibleApply(n.Info) {
		// Call post-apply hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostApply(n.Info, state, *n.Error)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, *n.Error
}

// resourceHasUserVisibleApply returns true if the given resource is one where
// apply actions should be exposed to the user.
//
// Certain resources do apply actions only as an implementation detail, so
// these should not be advertised to code outside of this package.
func resourceHasUserVisibleApply(info *InstanceInfo) bool {
	addr := info.ResourceAddress()

	// Only managed resources have user-visible apply actions.
	// In particular, this excludes data resources since we "apply" these
	// only as an implementation detail of removing them from state when
	// they are destroyed. (When reading, they don't get here at all because
	// we present them as "Refresh" actions.)
	return addr.Mode == config.ManagedResourceMode
}

// EvalApplyProvisioners is an EvalNode implementation that executes
// the provisioners for a resource.
//
// TODO(mitchellh): This should probably be split up into a more fine-grained
// ApplyProvisioner (single) that is looped over.
type EvalApplyProvisioners struct {
	Info           *InstanceInfo
	State          **InstanceState
	Resource       *config.Resource
	InterpResource *Resource
	CreateNew      *bool
	Error          *error

	// When is the type of provisioner to run at this point
	When config.ProvisionerWhen
}

// TODO: test
func (n *EvalApplyProvisioners) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	if n.CreateNew != nil && !*n.CreateNew {
		// If we're not creating a new resource, then don't run provisioners
		return nil, nil
	}

	provs := n.filterProvisioners()
	if len(provs) == 0 {
		// We have no provisioners, so don't do anything
		return nil, nil
	}

	// taint tells us whether to enable tainting.
	taint := n.When == config.ProvisionerWhenCreate

	if n.Error != nil && *n.Error != nil {
		if taint {
			state.Tainted = true
		}

		// We're already tainted, so just return out
		return nil, nil
	}

	{
		// Call pre hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PreProvisionResource(n.Info, state)
		})
		if err != nil {
			return nil, err
		}
	}

	// If there are no errors, then we append it to our output error
	// if we have one, otherwise we just output it.
	err := n.apply(ctx, provs)
	if err != nil {
		if taint {
			state.Tainted = true
		}

		*n.Error = multierror.Append(*n.Error, err)
		return nil, err
	}

	{
		// Call post hook
		err := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostProvisionResource(n.Info, state)
		})
		if err != nil {
			return nil, err
		}
	}

	return nil, nil
}

// filterProvisioners filters the provisioners on the resource to only
// the provisioners specified by the "when" option.
func (n *EvalApplyProvisioners) filterProvisioners() []*config.Provisioner {
	// Fast path the zero case
	if n.Resource == nil {
		return nil
	}

	if len(n.Resource.Provisioners) == 0 {
		return nil
	}

	result := make([]*config.Provisioner, 0, len(n.Resource.Provisioners))
	for _, p := range n.Resource.Provisioners {
		if p.When == n.When {
			result = append(result, p)
		}
	}

	return result
}

func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*config.Provisioner) error {
	state := *n.State

	// Store the original connection info, restore later
	origConnInfo := state.Ephemeral.ConnInfo
	defer func() {
		state.Ephemeral.ConnInfo = origConnInfo
	}()

	for _, prov := range provs {
		// Get the provisioner
		provisioner := ctx.Provisioner(prov.Type)

		// Interpolate the provisioner config
		provConfig, err := ctx.Interpolate(prov.RawConfig.Copy(), n.InterpResource)
		if err != nil {
			return err
		}

		// Interpolate the conn info, since it may contain variables
		connInfo, err := ctx.Interpolate(prov.ConnInfo.Copy(), n.InterpResource)
		if err != nil {
			return err
		}

		// Merge the connection information
		overlay := make(map[string]string)
		if origConnInfo != nil {
			for k, v := range origConnInfo {
				overlay[k] = v
			}
		}
		for k, v := range connInfo.Config {
			switch vt := v.(type) {
			case string:
				overlay[k] = vt
			case int64:
				overlay[k] = strconv.FormatInt(vt, 10)
			case int32:
				overlay[k] = strconv.FormatInt(int64(vt), 10)
			case int:
				overlay[k] = strconv.FormatInt(int64(vt), 10)
			case float32:
				overlay[k] = strconv.FormatFloat(float64(vt), 'f', 3, 32)
			case float64:
				overlay[k] = strconv.FormatFloat(vt, 'f', 3, 64)
			case bool:
				overlay[k] = strconv.FormatBool(vt)
			default:
				overlay[k] = fmt.Sprintf("%v", vt)
			}
		}
		state.Ephemeral.ConnInfo = overlay

		{
			// Call pre hook
			err := ctx.Hook(func(h Hook) (HookAction, error) {
				return h.PreProvision(n.Info, prov.Type)
			})
			if err != nil {
				return err
			}
		}

		// The output function
		outputFn := func(msg string) {
			ctx.Hook(func(h Hook) (HookAction, error) {
				h.ProvisionOutput(n.Info, prov.Type, msg)
				return HookActionContinue, nil
			})
		}

		// Invoke the Provisioner
		output := CallbackUIOutput{OutputFn: outputFn}
		applyErr := provisioner.Apply(&output, state, provConfig)

		// Call post hook
		hookErr := ctx.Hook(func(h Hook) (HookAction, error) {
			return h.PostProvision(n.Info, prov.Type, applyErr)
		})

		// Handle the error before we deal with the hook
		if applyErr != nil {
			// Determine failure behavior
			switch prov.OnFailure {
			case config.ProvisionerOnFailureContinue:
				log.Printf(
					"[INFO] apply: %s [%s]: error during provision, continue requested",
					n.Info.Id, prov.Type)

			case config.ProvisionerOnFailureFail:
				return applyErr
			}
		}

		// Deal with the hook
		if hookErr != nil {
			return hookErr
		}
	}

	return nil

}
<|endoftext|>


<commit_before>// Extremely simple console tool.
// Takes Long URL as a first argument.
// Returns Bitly short URL to console.
// That's It.
package main

import (
      "os"
      "log"
      "fmt"
      "regexp"
      "io/ioutil"
      "net/http"
      "net/url"
      "encoding/base64"
)

const(
      API_BASEURL = "https://api-ssl.bitly.com"
      TOKEN_DIR   = ".hobbit"
      TOKEN_FILE  = "token"

      API_AUTH    = "/oauth/access_token"
      API_SHORT   = "/v3/shorten"
)

var(
    HOME = os.Getenv("HOME")
)

// Config file will be created under given path with given filename
// Returns *os.File object and error
func InitConfig(path string, filename string) (*os.File, error) {
  if len(HOME) == 0 {
    log.Println("HOME environment variable is empty. I'll use current folder")
    config_file, err := os.Create(TOKEN_FILE)
    if err != nil {
      return nil, err
    } else {
      return config_file, nil
    }
  }

  // Define absolute path to config
  config_dir       := HOME + "/" + TOKEN_DIR
  config_file_path := config_dir + "/" + TOKEN_FILE

  // Create config directory if not exists
  if _, err := os.Stat(config_dir); os.IsNotExist(err) {
    err := os.Mkdir(config_dir, 0755)
    if err != nil {
      log.Println(err)
      log.Fatal("can't create directory: ", config_dir ," Check free space and permissions")
    }
  }

  // Create config file if not exists
  if _, err := os.Stat(config_file_path); os.IsNotExist(err) {
    config_file, err := os.Create(config_file_path)
    if err != nil {
      log.Println(err)
      log.Fatal("can't create config file: ", config_file_path, " Check free space and permissions")
    }
    return config_file, err
  }

  return os.Open(config_file_path)
}

// Save Token on a filesystem
func SaveToken(tk string, f *os.File) (int, error) {
  return f.WriteString(tk)
}

// Get access_token
func Auth() string {
  username := ""
  password := ""

  // Get username and password from user
  fmt.Println("Looks like access_token is not set. Let's do It!")
  fmt.Printf("%s: ","username")
  fmt.Scanln(&username)
  fmt.Printf("%s: ", "password")
  fmt.Scanln(&password)

  // Create request
  client := &http.Client{}
  urlStr := API_BASEURL + API_AUTH
  r, err := http.NewRequest("POST", urlStr, nil)
  if err != nil {
    log.Fatal(err)
  }
  // Set auth header
  msg := username + ":" + password
  auth_header := "Basic " + base64.StdEncoding.EncodeToString([]byte(msg))
  r.Header.Add("Authorization", auth_header)

  // Get response
  resp, err := client.Do(r)
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()

  // Get token
  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err)
  }

  // Check errors and return access_token
  response_string := string(body)
  _, err = regexp.MatchString("[a-zA-Z0-9]+", response_string)
  if err != nil {
    log.Fatal(response_string)
  }
  return response_string
}

// Shorten long URL
func Shorten(tk string ,longurl string) string {
  urlStr := API_BASEURL + API_SHORT

  Url, err := url.Parse(urlStr)
  if err != nil {
    log.Fatal(err)
  }

  // Set parameters
  parameters := url.Values{}
  parameters.Add("access_token", tk)
  parameters.Add("longUrl", longurl)
  parameters.Add("format", "txt")
  Url.RawQuery = parameters.Encode()

  // Call API endpoint
  resp, err := http.Get(Url.String())
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err)
  }

  return string(body)
}

func main() {
  var token, longUrl string

  f, _ := InitConfig(TOKEN_DIR, TOKEN_FILE)
  defer f.Close()

  // Read existing token from file or get a new one
  stat, _ := f.Stat()
  if stat.Size() > 0 {
    bs := make([]byte, stat.Size())
    f.Read(bs)
    token = string(bs)
  } else {
    token = Auth()
    SaveToken(token, f)
  }

  // Check if argument has been passed to the script
  if len(os.Args) < 2 {
    fmt.Println("USAGE:", os.Args[0], "http://example.com")
    fmt.Println("NOTE:  'http/https' part is obligatory")
    os.Exit(1)
  }

  longUrl = os.Args[1]
  fmt.Printf(Shorten(token, longUrl))
}
<commit_msg>Fixed issue with wrong path declaration on systems without HOME environment variable. Refactoring.<commit_after>// Extremely simple console tool. Takes Long URL as a first argument.
// Returns Bitly short URL to console. That's It.
package main

import (
    "os"
    "log"
    "fmt"
    "regexp"
    "io/ioutil"
    "net/http"
    "net/url"
    "encoding/base64"
)

const(
    API_BASEURL     = "https://api-ssl.bitly.com"
    API_AUTH        = "/oauth/access_token"
    API_SHORT       = "/v3/shorten"
    TOKEN_FILE      = ".hobbit_token"

    API_TOKEN_ERROR_INVALID = "INVALID_ARG_ACCESS_TOKEN"
    API_TOKEN_ERROR_MISSING = "MISSING_ARG_ACCESS_TOKEN"
)

// Create config file and write token to It
func SaveConfig(filename string, tk string) error {
    HOME := os.Getenv("HOME")
    var path string = ""

    // If HOME is empty
    if len(HOME) == 0 {
      log.Println("HOME environment variable is empty. I'll use current folder")
      path = filename
      config_file, err := os.Create(path)
      defer config_file.Close()
      if err != nil {
        log.Println(err)
        return err
      }

      _, err = config_file.WriteString(tk)
      if err != nil {
        log.Println(err)
        return err
      }

      return nil
  }

    // Set Path if HOME is not empty
    path = HOME + "/" + filename

    // Create config file and write token to It
    config_file, err := os.Create(path)
    defer config_file.Close()

    if err != nil {
      log.Println(err)
      log.Fatal("Can't create config file: ", path, " Check free space and permissions")
    }

    _, err = config_file.WriteString(tk)
    if err != nil {
      log.Println(err)
      return err
    }

    return nil
}

// Get Token from file
func ReadToken(filename string) string {
    HOME := os.Getenv("HOME")
    var path string = ""

    if len(HOME) == 0 {
      path = filename
    } else {
      path = HOME + "/" + filename
    }

    f, err := os.Open(path)
    defer f.Close()

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

    stat, _ := f.Stat()
    bs := make([]byte, stat.Size())
    f.Read(bs)

    return string(bs)
}

// Authenticate. Returns access_token
func Auth() string {
    username := ""
    password := ""

    // Get username and password from user
    fmt.Println("Bitly access_token is not set. Let's do It!")
    fmt.Printf("%s: ","username")
    fmt.Scanln(&username)
    fmt.Printf("%s: ", "password")
    fmt.Scanln(&password)

    // Create request
    client := &http.Client{}
    urlStr := API_BASEURL + API_AUTH
    r, err := http.NewRequest("POST", urlStr, nil)
    if err != nil {
      log.Fatal(err)
    }

    // Set auth header
    msg := username + ":" + password
    auth_header := "Basic " + base64.StdEncoding.EncodeToString([]byte(msg))
    r.Header.Add("Authorization", auth_header)

    // Get response
    resp, err := client.Do(r)
    if err != nil {
      log.Fatal(err)
    }
    defer resp.Body.Close()

    // Get token
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      log.Fatal(err)
    }

    // Check errors and return access_token
    response_string := string(body)
    _, err = regexp.MatchString("[a-zA-Z0-9]+", response_string)
    if err != nil {
      log.Fatal(response_string)
    }
    return response_string
}

// Shorten long URL
func Shorten(tk string ,longurl string) string {
    urlStr := API_BASEURL + API_SHORT

    Url, err := url.Parse(urlStr)
    if err != nil {
      log.Fatal(err)
    }

    // Set parameters
    parameters := url.Values{}
    parameters.Add("access_token", tk)
    parameters.Add("longUrl", longurl)
    parameters.Add("format", "txt")
    Url.RawQuery = parameters.Encode()

    // Call API endpoint
    resp, err := http.Get(Url.String())
    if err != nil {
      log.Fatal(err)
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      log.Fatal(err)
    }

    return string(body)
}

func main() {
    var shortUrl, longUrl string
    token := ReadToken(TOKEN_FILE)

    // Check argumets
    if len(os.Args) < 2 {
      fmt.Println("USAGE:", os.Args[0], "http://example.com")
      fmt.Println("NOTE:  'http/https' part is obligatory")
      os.Exit(1)
    }

    longUrl = os.Args[1]

    // Authenticate and save token. 3 attempts
    for i := 0; i < 3; i++ {
      shortUrl = Shorten(token, longUrl)
      if shortUrl == API_TOKEN_ERROR_INVALID || shortUrl == API_TOKEN_ERROR_MISSING {
        log.Println("Bitly access_token is not set/valid")
        token = Auth()
      } else {
        fmt.Printf(shortUrl)
        break
      }
    }

    SaveConfig(TOKEN_FILE, token)
}
<|endoftext|>