<commit_before>package main

import (
	"./helpers"
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"github.com/garyburd/redigo/redis"
	"github.com/googollee/go-socket.io"
	"strings"
)

type Space struct {
	Channel string
	SpaceID string
	Space   []Player
}

type Player struct {
	LocalIP  string
	UserName string
}

func Adduser(msg string) {
	helpers.TRACE.Println("socket.io: adduser", msg)

}

func Logon(so socketio.Socket, msg string) {

	var space Space
	var known bool = false

	ipNumbers := strings.Split(msg, " ")
	helpers.TRACE.Println("socket.io->Logon: IP", ipNumbers)

	localIP := ipNumbers[0]
	spaceID := ipNumbers[1]
	helpers.TRACE.Println("socket.io->Logon: SpaceID", spaceID)

	redisDB := RedisPool.Get()
	defer redisDB.Close()

	jsonSpace, err := redis.Bytes(redisDB.Do("GET", spaceID))
	if err != nil {
		// so the user is in a new space we add him
		known = true
		TRACE.Println("socket.io->Logon: newSpace", err)
		space = Space{
			Channel: uuid.New(),
			SpaceID: spaceID,
			Space: []Player{
				{
					LocalIP:  localIP,
					UserName: "JonDoe",
				},
			},
		}
		jsonSpace, err := json.Marshal(space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Marshal error: ", err)
		}
		_, err = redisDB.Do("SET", spaceID, jsonSpace)
		if err != nil {
			ERROR.Println("socket.io->Logon RedisDB SET error: ", err)
		}

	} else {
		// else unmarshal the json object
		err = json.Unmarshal(jsonSpace, &space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Unmarshal error: ", err)
		}
	}

	// check if the user is known
	for _, element := range space.Space {
		if element.LocalIP == localIP {
			known = true
			TRACE.Println("socket.io->Logon known LocalIP", element.LocalIP, "in Space", spaceID)
		}
	}

	// if ip is unknow add it to the space
	if !known {
		TRACE.Println("socket.io->Logon unknown LocalIP", localIP, "is added")

		player := Player{
			LocalIP:  localIP,
			UserName: "JonDoe",
		}

		space.Space = append(space.Space, player)
		jsonSpace, err := json.Marshal(space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Marshal error: ", err)
		}
		_, err = redisDB.Do("SET", spaceID, jsonSpace)
		if err != nil {
			ERROR.Println("socket.io->Logon RedisDB SET error: ", err)
		}

		TRACE.Println("socket.io->Logon added", space)
	}

	TRACE.Println("socket.io->Logon Emit Answer with Id", so.Id(), space)
	so.Emit("space", space)
	//	so.BroadcastTo(so.Id(), "space", space)
}

func JoinGame(so socketio.Socket, msg string) {

	helpers.TRACE.Println("socket.io: Join", msg)

	so.Emit("channel", "abcde")
}
<commit_msg>websocket debug<commit_after>package main

import (
	"./helpers"
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"github.com/garyburd/redigo/redis"
	"github.com/googollee/go-socket.io"
	"strings"
)

type Space struct {
	Channel string
	SpaceID string
	Space   []Player
}

type Player struct {
	LocalIP  string
	UserName string
}

func Adduser(msg string) {
	helpers.TRACE.Println("socket.io: adduser", msg)

}

func Logon(so socketio.Socket, msg string) {

	var space Space
	var known bool = false

	ipNumbers := strings.Split(msg, " ")
	helpers.TRACE.Println("socket.io->Logon: IP", ipNumbers)

	localIP := ipNumbers[0]
	spaceID := ipNumbers[1]
	helpers.TRACE.Println("socket.io->Logon: SpaceID", spaceID)

	redisDB := RedisPool.Get()
	defer redisDB.Close()

	jsonSpace, err := redis.Bytes(redisDB.Do("GET", spaceID))
	if err != nil {
		// so the user is in a new space we add him
		known = true
		TRACE.Println("socket.io->Logon: newSpace", err)
		space = Space{
			Channel: uuid.New(),
			SpaceID: spaceID,
			Space: []Player{
				{
					LocalIP:  localIP,
					UserName: "JonDoe",
				},
			},
		}
		jsonSpace, err := json.Marshal(space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Marshal error: ", err)
		}
		_, err = redisDB.Do("SET", spaceID, jsonSpace)
		if err != nil {
			ERROR.Println("socket.io->Logon RedisDB SET error: ", err)
		}

	} else {
		// else unmarshal the json object
		err = json.Unmarshal(jsonSpace, &space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Unmarshal error: ", err)
		}
	}

	// check if the user is known
	for _, element := range space.Space {
		if element.LocalIP == localIP {
			known = true
			TRACE.Println("socket.io->Logon known LocalIP", element.LocalIP, "in Space", spaceID)
		}
	}

	// if ip is unknow add it to the space
	if !known {
		TRACE.Println("socket.io->Logon unknown LocalIP", localIP, "is added")

		player := Player{
			LocalIP:  localIP,
			UserName: "JonDoe",
		}

		space.Space = append(space.Space, player)
		jsonSpace, err := json.Marshal(space)
		if err != nil {
			ERROR.Println("socket.io->Logon json.Marshal error: ", err)
		}
		_, err = redisDB.Do("SET", spaceID, jsonSpace)
		if err != nil {
			ERROR.Println("socket.io->Logon RedisDB SET error: ", err)
		}

		TRACE.Println("socket.io->Logon added", space)
	}

	TRACE.Println("socket.io->Logon Emit Answer with Id", so.Id(), space)
	r := so.Emit("space", space)
	TRACE.Println("socket.io response:", r)
	TRACE.Println("socket.io->Logon Brodcast Answer with Id", so.Id(), space)
	r = so.BroadcastTo(so.Id(), "space", space)
	TRACE.Println("socket.io response:", r)
}

func JoinGame(so socketio.Socket, msg string) {

	helpers.TRACE.Println("socket.io: Join", msg)

	so.Emit("channel", "abcde")
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"golang.org/x/crypto/nacl/secretbox"

	"github.com/howeyc/gopass"
	"github.com/pkg/errors"
)

type EnvVar struct {
	Name  string `json:"name"`
	Value string `json:"value"`
	Path  string `json:"-"`
}

func ReadKey() (string, error) {
	if _, err := os.Stat(keyPath); os.IsNotExist(err) {
		key, err := PromptForKey()
		if err != nil {
			return "", errors.Wrap(err, "unable prompt for key")
		}

		err = StoreKey(key)
		if err != nil {
			return "", errors.Wrap(err, "unable to set key")
		}
	}

	data, err := ioutil.ReadFile(keyPath)
	if err != nil {
		return "", errors.Wrap(err, "unable to read keypath")
	}

	key := strings.TrimSpace(string(data))

	return key, nil
}

func StoreKey(key string) error {
	return ioutil.WriteFile(keyPath, []byte(key), 0600)
}

func PromptForKey() (string, error) {
	fmt.Printf("enter key: ")

	key, err := gopass.GetPasswdMasked()
	if err != nil {
		if err == gopass.ErrInterrupted {
			return "", fmt.Errorf("interrupted")
		} else {
			return "", errors.Wrap(err, "unable to prompt for key")
		}
	}

	// TODO: check that key is valid

	return string(key), nil
}

func PromptForValue() (string, error) {
	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
	if err != nil {
		return "", errors.Wrap(err, "failed to open /dev/tty")
	}

	fmt.Fprintf(tty, "value: ")
	value, err := bufio.NewReader(tty).ReadString('\n')
	if err != nil {
		return "", errors.Wrap(err, "unable to read value")
	}

	err = tty.Close()
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(value), nil
}

func AddVariable(key, name, value string) error {
	fmt.Printf("adding variable %s=%s (key: %s)\n", name, value, key)

	message, err := json.Marshal(EnvVar{Name: name, Value: value})
	if err != nil {
		return err
	}

	var keyBytes [32]byte
	copy(keyBytes[:], []byte(key)[:32])

	var nonce [24]byte
	if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
		panic(err)
	}

	out := make([]byte, 24)
	copy(out, nonce[:])

	out = secretbox.Seal(out, message, &nonce, &keyBytes)

	// fmt.Println(out)

	var fname [24]byte
	if _, err := io.ReadFull(rand.Reader, fname[:]); err != nil {
		return errors.Wrap(err, "unable to read random")
	}

	return ioutil.WriteFile(fmt.Sprintf("%s.envenc", hex.EncodeToString(fname[:])), out, 0600)
}

func RemoveVariable(key, name string) error {
	fmt.Printf("removing variable %s (key: %s)\n", name, key)

	vars, err := LoadEnvVars(key)
	if err != nil {
		return errors.Wrap(err, "unable to load env vars")
	}

	if envVar, ok := vars[name]; ok {
		err = os.Remove(envVar.Path)
		if err != nil {
			return errors.Wrap(err, "unable to remove file")
		}
	} else {
		return fmt.Errorf("variable %s not found", name)
	}
	return nil
}

func RunCommandWithEnv(key string, varNames, command []string) error {

	fmt.Printf("running %v with vars %v (key: %s)\n", command, varNames, key)

	cmd := exec.Command(command[0], command[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	hostEnv := os.Environ()
	vars, err := LoadEnvVars(key)
	if err != nil {
		return errors.Wrap(err, "unable to load env vars")
	}
	for _, varName := range varNames {
		if envVar, ok := vars[varName]; ok {
			hostEnv = append(hostEnv, fmt.Sprintf("%s=%s", varName, envVar.Value))
		} else {
			fmt.Fprintf(os.Stdout, "unable to find %s\n", varName)
		}
	}
	cmd.Env = hostEnv

	return cmd.Run()
}

func LoadEnvVars(key string) (map[string]EnvVar, error) {
	vars := make(map[string]EnvVar)

	files, err := ioutil.ReadDir(secretPath)
	if err != nil {
		return vars, errors.Wrap(err, "unable to read directory")
	}

	var keyBytes [32]byte
	copy(keyBytes[:], []byte(key)[:32])

	for _, info := range files {
		if !info.IsDir() && strings.HasSuffix(info.Name(), ".envenc") {
			fileName := filepath.Join(secretPath, info.Name())
			// fmt.Println("Loading file", fileName)

			data, err := ioutil.ReadFile(fileName)
			if err != nil {
				return vars, errors.Wrap(err, "unable to read file")
			}

			nonce := new([24]byte)
			copy(nonce[:], data[:24])

			if message, ok := secretbox.Open(nil, data[24:], nonce, &keyBytes); ok {
				// fmt.Println(string(message))

				var envVar EnvVar
				err := json.Unmarshal(message, &envVar)
				if err != nil {
					// ignore
				}
				envVar.Path = fileName

				vars[envVar.Name] = envVar
			} else {
				// ignore
			}

		}
	}

	return vars, nil
}

func GenerateNewKey() (string, error) {
	var pass [32]byte
	if _, err := io.ReadFull(rand.Reader, pass[:]); err != nil {
		return "", errors.Wrap(err, "unable to read random")
	}

	return hex.EncodeToString(pass[:]), nil
}
<commit_msg>comment out extra prints<commit_after>package main

import (
	"bufio"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"golang.org/x/crypto/nacl/secretbox"

	"github.com/howeyc/gopass"
	"github.com/pkg/errors"
)

type EnvVar struct {
	Name  string `json:"name"`
	Value string `json:"value"`
	Path  string `json:"-"`
}

func ReadKey() (string, error) {
	if _, err := os.Stat(keyPath); os.IsNotExist(err) {
		key, err := PromptForKey()
		if err != nil {
			return "", errors.Wrap(err, "unable prompt for key")
		}

		err = StoreKey(key)
		if err != nil {
			return "", errors.Wrap(err, "unable to set key")
		}
	}

	data, err := ioutil.ReadFile(keyPath)
	if err != nil {
		return "", errors.Wrap(err, "unable to read keypath")
	}

	key := strings.TrimSpace(string(data))

	return key, nil
}

func StoreKey(key string) error {
	return ioutil.WriteFile(keyPath, []byte(key), 0600)
}

func PromptForKey() (string, error) {
	fmt.Printf("enter key: ")

	key, err := gopass.GetPasswdMasked()
	if err != nil {
		if err == gopass.ErrInterrupted {
			return "", fmt.Errorf("interrupted")
		} else {
			return "", errors.Wrap(err, "unable to prompt for key")
		}
	}

	// TODO: check that key is valid

	return string(key), nil
}

func PromptForValue() (string, error) {
	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
	if err != nil {
		return "", errors.Wrap(err, "failed to open /dev/tty")
	}

	fmt.Fprintf(tty, "value: ")
	value, err := bufio.NewReader(tty).ReadString('\n')
	if err != nil {
		return "", errors.Wrap(err, "unable to read value")
	}

	err = tty.Close()
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(value), nil
}

func AddVariable(key, name, value string) error {
	// fmt.Printf("adding variable %s=%s (key: %s)\n", name, value, key)

	message, err := json.Marshal(EnvVar{Name: name, Value: value})
	if err != nil {
		return err
	}

	var keyBytes [32]byte
	copy(keyBytes[:], []byte(key)[:32])

	var nonce [24]byte
	if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
		panic(err)
	}

	out := make([]byte, 24)
	copy(out, nonce[:])

	out = secretbox.Seal(out, message, &nonce, &keyBytes)

	// fmt.Println(out)

	var fname [24]byte
	if _, err := io.ReadFull(rand.Reader, fname[:]); err != nil {
		return errors.Wrap(err, "unable to read random")
	}

	return ioutil.WriteFile(fmt.Sprintf("%s.envenc", hex.EncodeToString(fname[:])), out, 0600)
}

func RemoveVariable(key, name string) error {
	// fmt.Printf("removing variable %s (key: %s)\n", name, key)

	vars, err := LoadEnvVars(key)
	if err != nil {
		return errors.Wrap(err, "unable to load env vars")
	}

	if envVar, ok := vars[name]; ok {
		err = os.Remove(envVar.Path)
		if err != nil {
			return errors.Wrap(err, "unable to remove file")
		}
	} else {
		return fmt.Errorf("variable %s not found", name)
	}
	return nil
}

func RunCommandWithEnv(key string, varNames, command []string) error {
	// fmt.Printf("running %v with vars %v (key: %s)\n", command, varNames, key)

	cmd := exec.Command(command[0], command[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	hostEnv := os.Environ()
	vars, err := LoadEnvVars(key)
	if err != nil {
		return errors.Wrap(err, "unable to load env vars")
	}
	for _, varName := range varNames {
		if envVar, ok := vars[varName]; ok {
			hostEnv = append(hostEnv, fmt.Sprintf("%s=%s", varName, envVar.Value))
		} else {
			fmt.Fprintf(os.Stdout, "unable to find %s\n", varName)
		}
	}
	cmd.Env = hostEnv

	return cmd.Run()
}

func LoadEnvVars(key string) (map[string]EnvVar, error) {
	vars := make(map[string]EnvVar)

	files, err := ioutil.ReadDir(secretPath)
	if err != nil {
		return vars, errors.Wrap(err, "unable to read directory")
	}

	var keyBytes [32]byte
	copy(keyBytes[:], []byte(key)[:32])

	for _, info := range files {
		if !info.IsDir() && strings.HasSuffix(info.Name(), ".envenc") {
			fileName := filepath.Join(secretPath, info.Name())
			// fmt.Println("Loading file", fileName)

			data, err := ioutil.ReadFile(fileName)
			if err != nil {
				return vars, errors.Wrap(err, "unable to read file")
			}

			nonce := new([24]byte)
			copy(nonce[:], data[:24])

			if message, ok := secretbox.Open(nil, data[24:], nonce, &keyBytes); ok {
				// fmt.Println(string(message))

				var envVar EnvVar
				err := json.Unmarshal(message, &envVar)
				if err != nil {
					// ignore
				}
				envVar.Path = fileName

				vars[envVar.Name] = envVar
			} else {
				// ignore
			}

		}
	}

	return vars, nil
}

func GenerateNewKey() (string, error) {
	var pass [32]byte
	if _, err := io.ReadFull(rand.Reader, pass[:]); err != nil {
		return "", errors.Wrap(err, "unable to read random")
	}

	return hex.EncodeToString(pass[:]), nil
}
<|endoftext|>


<commit_before>package algoliasearch

import (
	"bytes"
	_ "crypto/sha512" // Fix certificates
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const (
	version = "1.4.0"
)

const (
	search = 1 << iota
	write
	read
)

// Transport defines low level functions to trade with Algolia servers.
type Transport struct {
	apiKey        string
	appID         string
	headers       map[string]string
	hosts         []string
	hostsProvided bool
	httpClient    *http.Client
}

// newHTTPClient creates and initializes an http.Client with sane defaults.
func newHTTPClient() *http.Client {
	return &http.Client{
		Timeout: time.Second * 30,
		Transport: &http.Transport{
			Dial: (&net.Dialer{
				Timeout:   2 * time.Second,
				KeepAlive: 180 * time.Second,
			}).Dial,
			DisableKeepAlives:   false,
			MaxIdleConnsPerHost: 2,
			TLSHandshakeTimeout: 2 * time.Second,
		},
	}
}

// NewTransport creates and initializes a new Transport targeting the Algolia
// application `appID` using the API key `apiKey`. The hosts are deduced
// from `appID`.
func NewTransport(appID, apiKey string) *Transport {
	hosts := []string{
		appID + "-1.algolianet.com",
		appID + "-2.algolianet.com",
		appID + "-3.algolianet.com",
	}

	randHosts := make([]string, len(hosts))
	for i, v := range rand.Perm(len(hosts)) {
		randHosts[i] = hosts[v]
	}

	return &Transport{
		apiKey:        apiKey,
		appID:         appID,
		headers:       make(map[string]string),
		hosts:         randHosts,
		hostsProvided: false,
		httpClient:    newHTTPClient(),
	}
}

// NewTransportWithHosts creates and initializes a new Transport targeting the
// Algolia application `appID` using the API key `apiKey` via the
// specified `hosts`.
func NewTransportWithHosts(appID, apiKey string, hosts []string) *Transport {
	return &Transport{
		apiKey:        apiKey,
		appID:         appID,
		headers:       make(map[string]string),
		hosts:         hosts,
		hostsProvided: true,
		httpClient:    newHTTPClient(),
	}
}

// setTimeout changes the timeouts used by the underlying HTTP client.
func (t *Transport) setTimeout(connectTimeout time.Duration, readTimeout time.Duration) {
	t.httpClient.Transport.(*http.Transport).TLSHandshakeTimeout = connectTimeout
	t.httpClient.Transport.(*http.Transport).ResponseHeaderTimeout = readTimeout
}

// setExtraHeader adds a custom header to be used when exchanging with Algolia
// servers.
func (t *Transport) setExtraHeader(key string, value string) {
	t.headers[key] = value
}

// request performs a `method` HTTP request at `path` sending `body`.
// `typeCall` represents the operation intended on the Algolia servers and can
// be one of the following constants: `search`, `write` or `read`.
func (t *Transport) request(method, path string, body interface{}, typeCall int) ([]byte, error) {
	var host string
	errorMsg := ""
	if typeCall == write {
		host = t.appID + ".algolia.net"
	} else {
		host = t.appID + "-dsn.algolia.net"
	}

	if !t.hostsProvided {
		req, err := t.buildRequest(method, host, path, body)
		if err != nil {
			return nil, err
		}

		req = t.addHeaders(req)
		resp, err := t.httpClient.Do(req)

		if err != nil {
			if len(errorMsg) > 0 {
				errorMsg = fmt.Sprintf("%s, %s:%s", errorMsg, host, err)
			} else {
				errorMsg = fmt.Sprintf("%s:%s", host, err)
			}
		} else if (resp.StatusCode/100) == 2 || (resp.StatusCode/100) == 4 { // Bad request, not found, forbidden
			return t.handleResponse(resp)
		} else {
			io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}

	for _, host := range t.hosts {
		req, err := t.buildRequest(method, host, path, body)
		if err != nil {
			return nil, err
		}

		req = t.addHeaders(req)
		resp, err := t.httpClient.Do(req)

		if err != nil {
			if len(errorMsg) > 0 {
				errorMsg = fmt.Sprintf("%s, %s:%s", errorMsg, host, err)
			} else {
				errorMsg = fmt.Sprintf("%s:%s", host, err)
			}
			continue
		}

		if (resp.StatusCode/100) == 2 || (resp.StatusCode/100) == 4 { // Bad request, not found, forbidden
			return t.handleResponse(resp)
		} else {
			io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}

	return nil, errors.New(fmt.Sprintf("Cannot reach any host. (%s)", errorMsg))
}

// buildRequest builds an http.Request object. The built request uses `method`,
// tries to reach `path` at `host`, sending `body`.
func (t *Transport) buildRequest(method, host, path string, body interface{}) (*http.Request, error) {
	var req *http.Request
	var err error

	if body != nil {
		bodyBytes, err := json.Marshal(body)
		if err != nil {
			return nil, errors.New("Invalid JSON in the query")
		}

		reader := bytes.NewReader(bodyBytes)
		req, err = http.NewRequest(method, "https://"+host+path, reader)
		req.Header.Add("Content-Length", strconv.Itoa(len(string(bodyBytes))))
		req.Header.Add("Content-Type", "application/json; charset=utf-8")
	} else {
		req, err = http.NewRequest(method, "https://"+host+path, nil)
	}

	if strings.Contains(path, "/*/") {
		req.URL = &url.URL{
			Scheme: "https",
			Host:   host,
			Opaque: "//" + host + path, //Remove url encoding
		}
	}

	return req, err
}

// addHeaders adds the mandatory Algolia headers and the custom headers of `t`
// to `req`.
func (t *Transport) addHeaders(req *http.Request) *http.Request {
	req.Header.Add("X-Algolia-API-Key", t.apiKey)
	req.Header.Add("X-Algolia-Application-Id", t.appID)
	req.Header.Add("Connection", "keep-alive")
	req.Header.Add("User-Agent", "Algolia for go "+version)

	for key := range t.headers {
		req.Header.Add(key, t.headers[key])
	}

	return req
}

// handleResponse takes care of reading a response as JSON, and returns the
// parsed object. If the status code of the response indicates a failed request,
// or if the body of the response is not a valid JSON object, an error is
// returned.
func (t *Transport) handleResponse(resp *http.Response) ([]byte, error) {
	res, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, err
	}

	var jsonResp interface{}
	if err = json.Unmarshal(res, &jsonResp); err != nil {
		return nil, errors.New("Invalid JSON in the response")
	}

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return res, nil
	} else {
		return nil, errors.New(string(res))
	}
}
<commit_msg>Refactor transport comments<commit_after>package algoliasearch

import (
	"bytes"
	_ "crypto/sha512" // Fix certificates
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const (
	version = "1.4.0"
)

const (
	search = 1 << iota
	write
	read
)

// Transport defines low level functions to trade with Algolia servers.
type Transport struct {
	apiKey        string
	appID         string
	headers       map[string]string
	hosts         []string
	hostsProvided bool
	httpClient    *http.Client
}

// newHTTPClient creates and initializes an http.Client with sane defaults.
func newHTTPClient() *http.Client {
	return &http.Client{
		Timeout: time.Second * 30,
		Transport: &http.Transport{
			Dial: (&net.Dialer{
				Timeout:   2 * time.Second,
				KeepAlive: 180 * time.Second,
			}).Dial,
			DisableKeepAlives:   false,
			MaxIdleConnsPerHost: 2,
			TLSHandshakeTimeout: 2 * time.Second,
		},
	}
}

// NewTransport creates and initializes a new Transport targeting the Algolia
// application `appID` using the API key `apiKey`. The hosts are deduced from
// `appID`.
func NewTransport(appID, apiKey string) *Transport {
	hosts := []string{
		appID + "-1.algolianet.com",
		appID + "-2.algolianet.com",
		appID + "-3.algolianet.com",
	}

	// Randomize the hosts order
	randHosts := make([]string, len(hosts))
	for i, v := range rand.Perm(len(hosts)) {
		randHosts[i] = hosts[v]
	}

	return &Transport{
		apiKey:        apiKey,
		appID:         appID,
		headers:       make(map[string]string),
		hosts:         randHosts,
		hostsProvided: false,
		httpClient:    newHTTPClient(),
	}
}

// NewTransportWithHosts creates and initializes a new Transport targeting the
// Algolia application `appID` using the API key `apiKey` via the specified
// `hosts`.
func NewTransportWithHosts(appID, apiKey string, hosts []string) *Transport {
	return &Transport{
		apiKey:        apiKey,
		appID:         appID,
		headers:       make(map[string]string),
		hosts:         hosts,
		hostsProvided: true,
		httpClient:    newHTTPClient(),
	}
}

// setTimeout changes the timeouts used by the underlying HTTP client.
func (t *Transport) setTimeout(connectTimeout time.Duration, readTimeout time.Duration) {
	t.httpClient.Transport.(*http.Transport).TLSHandshakeTimeout = connectTimeout
	t.httpClient.Transport.(*http.Transport).ResponseHeaderTimeout = readTimeout
}

// setExtraHeader adds a custom header to be used when exchanging with Algolia
// servers.
func (t *Transport) setExtraHeader(key string, value string) {
	t.headers[key] = value
}

// request performs a `method` HTTP request at `path` sending `body`.
// `typeCall` represents the operation intended on the Algolia servers and can
// be one of the following constants: `search`, `write` or `read`.
func (t *Transport) request(method, path string, body interface{}, typeCall int) ([]byte, error) {
	var host string
	errorMsg := ""
	if typeCall == write {
		host = t.appID + ".algolia.net"
	} else {
		host = t.appID + "-dsn.algolia.net"
	}

	if !t.hostsProvided {
		req, err := t.buildRequest(method, host, path, body)
		if err != nil {
			return nil, err
		}

		req = t.addHeaders(req)
		resp, err := t.httpClient.Do(req)

		if err != nil {
			if len(errorMsg) > 0 {
				errorMsg = fmt.Sprintf("%s, %s:%s", errorMsg, host, err)
			} else {
				errorMsg = fmt.Sprintf("%s:%s", host, err)
			}
		} else if (resp.StatusCode/100) == 2 || (resp.StatusCode/100) == 4 { // Bad request, not found, forbidden
			return t.handleResponse(resp)
		} else {
			io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}

	for _, host := range t.hosts {
		req, err := t.buildRequest(method, host, path, body)
		if err != nil {
			return nil, err
		}

		req = t.addHeaders(req)
		resp, err := t.httpClient.Do(req)

		if err != nil {
			if len(errorMsg) > 0 {
				errorMsg = fmt.Sprintf("%s, %s:%s", errorMsg, host, err)
			} else {
				errorMsg = fmt.Sprintf("%s:%s", host, err)
			}
			continue
		}

		if (resp.StatusCode/100) == 2 || (resp.StatusCode/100) == 4 { // Bad request, not found, forbidden
			return t.handleResponse(resp)
		} else {
			io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}

	return nil, errors.New(fmt.Sprintf("Cannot reach any host. (%s)", errorMsg))
}

// buildRequest builds an http.Request object. The built request uses `method`,
// tries to reach `path` at `host`, sending `body`.
func (t *Transport) buildRequest(method, host, path string, body interface{}) (*http.Request, error) {
	var req *http.Request
	var err error

	if body != nil {
		bodyBytes, err := json.Marshal(body)
		if err != nil {
			return nil, errors.New("Invalid JSON in the query")
		}

		reader := bytes.NewReader(bodyBytes)
		req, err = http.NewRequest(method, "https://"+host+path, reader)
		req.Header.Add("Content-Length", strconv.Itoa(len(string(bodyBytes))))
		req.Header.Add("Content-Type", "application/json; charset=utf-8")
	} else {
		req, err = http.NewRequest(method, "https://"+host+path, nil)
	}

	if strings.Contains(path, "/*/") {
		req.URL = &url.URL{
			Scheme: "https",
			Host:   host,
			Opaque: "//" + host + path, //Remove url encoding
		}
	}

	return req, err
}

// addHeaders adds the mandatory Algolia headers and the custom headers of `t`
// to `req`.
func (t *Transport) addHeaders(req *http.Request) *http.Request {
	req.Header.Add("X-Algolia-API-Key", t.apiKey)
	req.Header.Add("X-Algolia-Application-Id", t.appID)
	req.Header.Add("Connection", "keep-alive")
	req.Header.Add("User-Agent", "Algolia for go "+version)

	for k, v := range t.headers {
		req.Header.Add(k, v)
	}

	return req
}

// handleResponse takes care of reading a response as JSON, and returns the
// parsed object. If the status code of the response indicates a failed
// request, or if the body of the response is not a valid JSON object, an error
// is returned.
func (t *Transport) handleResponse(resp *http.Response) ([]byte, error) {
	res, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, err
	}

	var jsonResp interface{}
	if err = json.Unmarshal(res, &jsonResp); err != nil {
		return nil, errors.New("Invalid JSON in the response")
	}

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return res, nil
	} else {
		return nil, errors.New(string(res))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"math/rand"
	"net/http"
	"strconv"
	"strings"
)

// Return the data in JSON format. This is the default return method.
func returnJson(obj interface{}, w http.ResponseWriter, h *http.Request) {
	// Don't cache json returns. This is to work around ie's weird caching behavior
	w.Header().Set("Cache-Control", "no-cache")
	// Set the content type to json
	w.Header().Set("Content-Type", "application/json")

	j, err := json.Marshal(obj)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	fmt.Fprint(w, string(j))
}

// Return all memories
func allMemoryHandler(w http.ResponseWriter, h *http.Request) {
	returnJson(brain, w, h)
}

// Return a random memory. This should only consider active memories
func randomMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var active_memories []Memory
	var i int

	for k, v := range brain.Memories {
		if v.Active == true {
			active_memories = append(active_memories, brain.Memories[k])
			i++
		}
	}

	random_id := rand.Intn(i)
	m := active_memories[random_id]
	returnJson(m, w, h)
}

// Return a specific memory
func getMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	id_string := vars["id"]

	id, err := strconv.Atoi(id_string)
	if err != nil {
		fmt.Fprint(w, "Could not parse Id")
	}

	for _, v := range brain.Memories {
		if v.Id == id && v.Active == true {
			returnJson(v, w, h)
		}
	}

	var blank Memory
	returnJson(blank, w, h)
}

// Add a memory
func addMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var m Memory
	b := json.NewDecoder(h.Body)
	b.Decode(&m)

	// Default a new memory to active
	m.Active = true
	memory := brain.Add(m)
	returnJson(memory, w, h)
}

func searchMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	term := vars["term"]

	var results []Memory

	for _, v := range brain.Memories {
		if strings.Contains(v.Text, term) {
			results = append(results, v)
		}
	}

	returnJson(results, w, h)
}

// Change a memory
func changeMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var m Memory
	b := json.NewDecoder(h.Body)
	b.Decode(&m)

	// The ID should come from the URL route, not the memory object that was posted
	vars := mux.Vars(h)
	mem_id_str := vars["id"]

	mem_id, err := strconv.Atoi(mem_id_str)
	if err != nil {
		panic("ID was not valid")
	}
	m.Id = mem_id

	memory := brain.Update(m)

	returnJson(memory, w, h)
}

// Remove a memory
func removeMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	id_str := vars["id"]
	id, err := strconv.Atoi(id_str)

	if err != nil {
		panic("ID was not an integer")
	}

	// Find the item to be deleted
	var memory Memory
	for k, v := range brain.Memories {
		if v.Id == id {
			v.Active = false
			memory = brain.Memories[k]
		}
	}

	returnJson(memory, w, h)
}
<commit_msg>Woops, was double returning from getMemoryHandler<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"math/rand"
	"net/http"
	"strconv"
	"strings"
)

// Return the data in JSON format. This is the default return method.
func returnJson(obj interface{}, w http.ResponseWriter, h *http.Request) {
	// Don't cache json returns. This is to work around ie's weird caching behavior
	w.Header().Set("Cache-Control", "no-cache")
	// Set the content type to json
	w.Header().Set("Content-Type", "application/json")

	j, err := json.Marshal(obj)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	fmt.Fprint(w, string(j))
}

// Return all memories
func allMemoryHandler(w http.ResponseWriter, h *http.Request) {
	returnJson(brain, w, h)
}

// Return a random memory. This should only consider active memories
func randomMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var active_memories []Memory
	var i int

	for k, v := range brain.Memories {
		if v.Active == true {
			active_memories = append(active_memories, brain.Memories[k])
			i++
		}
	}

	random_id := rand.Intn(i)
	m := active_memories[random_id]
	returnJson(m, w, h)
}

// Return a specific memory
func getMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	id_string := vars["id"]

	id, err := strconv.Atoi(id_string)
	if err != nil {
		fmt.Fprint(w, "Could not parse Id")
	}

	for _, v := range brain.Memories {
		if v.Id == id && v.Active == true {
			returnJson(v, w, h)
			return
		}
	}

	var blank Memory
	returnJson(blank, w, h)
}

// Add a memory
func addMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var m Memory
	b := json.NewDecoder(h.Body)
	b.Decode(&m)

	// Default a new memory to active
	m.Active = true
	memory := brain.Add(m)
	returnJson(memory, w, h)
}

func searchMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	term := vars["term"]

	var results []Memory

	for _, v := range brain.Memories {
		if strings.Contains(v.Text, term) {
			results = append(results, v)
		}
	}

	returnJson(results, w, h)
}

// Change a memory
func changeMemoryHandler(w http.ResponseWriter, h *http.Request) {
	var m Memory
	b := json.NewDecoder(h.Body)
	b.Decode(&m)

	// The ID should come from the URL route, not the memory object that was posted
	vars := mux.Vars(h)
	mem_id_str := vars["id"]

	mem_id, err := strconv.Atoi(mem_id_str)
	if err != nil {
		panic("ID was not valid")
	}
	m.Id = mem_id

	memory := brain.Update(m)

	returnJson(memory, w, h)
}

// Remove a memory
func removeMemoryHandler(w http.ResponseWriter, h *http.Request) {
	vars := mux.Vars(h)
	id_str := vars["id"]
	id, err := strconv.Atoi(id_str)

	if err != nil {
		panic("ID was not an integer")
	}

	// Find the item to be deleted
	var memory Memory
	for k, v := range brain.Memories {
		if v.Id == id {
			v.Active = false
			memory = brain.Memories[k]
		}
	}

	returnJson(memory, w, h)
}
<|endoftext|>


<commit_before>package amazonebsmock

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"time"

	awscommon "github.com/hashicorp/packer/builder/amazon/common"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

const BuilderId = "horgix.amazonebsmock"

// Hello Go, we can't even declare const slices...
var regions = []string{
	"us-east-2",
	"us-east-1",
	"us-west-1",
	"us-west-2",
	"ca-central-1",
	"ap-south-1",
	"ap-northeast-2",
	"ap-southeast-1",
	"ap-southeast-2",
	"ap-northeast-1",
	"eu-central-1",
	"eu-west-1",
	"eu-west-2",
	"sa-east-1",
}

// TODO : ideally, the Config and initialization should be the same than the
// official Amazon EBS Builder
type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	Amount int    `mapstructure:"amount"`
	Region string `mapstructure:"region"`

	ctx interpolate.Context
}

type Builder struct {
	Config Config
	// The testMsg field used to get some feedback during tests from method
	// which don't return anything like Cancel()
	TestMsg string
}

func (b *Builder) LoadDefaultConfig() {
	log.Println("LoadDefaultConfig(): Initializing builder's configuration")
	b.Config = Config{}
	log.Println(b.Config)
	log.Println("LoadDefaultConfig(): Setting default: Amount = 1")
	b.Config.Amount = 1
	log.Println("LoadDefaultConfig(): Setting default: Region = \"\"")
	b.Config.Region = ""
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	log.Println("Hello I'm a custom builder and this is the Prepare step")

	b.LoadDefaultConfig()
	log.Println("Prepare(): initial configuration:")
	log.Println("  - Amount: ", b.Config.Amount)
	log.Println("  - Region: \"" + b.Config.Region + "\"")
	log.Println("Prepare(): parsing configuration")
	err := config.Decode(&b.Config, &config.DecodeOpts{Interpolate: false}, raws...)
	if err != nil {
		return nil, err
	}
	log.Println("Prepare(): parsed configuration with success")
	log.Println("Prepare(): current configuration:")
	log.Println("  - Amount: ", b.Config.Amount)
	log.Println("  - Region: \"" + b.Config.Region + "\"")

	log.Println("Prepare(): checking for incorrect parameters")
	if b.Config.Amount != 1 && b.Config.Region != "" {
		// TODO : Improve this error, maybe use Packer's types?
		return nil, errors.New("FAIL")
	}

	log.Println("Prepare(): Initializing random generator...")
	rand.Seed(time.Now().Unix())
	b.TestMsg = "Rand seeded"

	return nil, nil
}

func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	log.Println("Run(): Hello I'm a custom builder")

	amis := make(map[string]string)

	ui.Say(fmt.Sprintf("Generating mock Artifact (%d AMI IDs)...", b.Config.Amount))
	for i := 0; i < b.Config.Amount; i++ {
		amiId := fmt.Sprintf("ami-%06d", i+1)
		if b.Config.Region == "" {
			// Packer is not able to build 2 AMIs in the same
			// region in the same Builder, so:
			// - We take a random region
			// - We remove it from the pool

			// Take a random region
			idx := rand.Intn(len(regions))
			region := regions[idx]

			// Remove it from the pool
			regions[idx] = regions[len(regions)-1]
			regions = regions[:len(regions)-1]

			amis[region] = amiId
		} else {
			amis["eu-west-1"] = amiId
		}
	}

	log.Println("Run(): tranforming into official module artifact type...")
	artifact := &awscommon.Artifact{
		Amis:           amis,
		BuilderIdValue: BuilderId,
	}

	ui.Say("Generated mock Artifact with success :)")
	return artifact, nil
}

func (b *Builder) Cancel() {
	b.TestMsg = "This method is doing nothing"
}
<commit_msg>lint: rename BuilderId and amiId into BuilderID and amiID<commit_after>package amazonebsmock

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"time"

	awscommon "github.com/hashicorp/packer/builder/amazon/common"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

const BuilderID = "horgix.amazonebsmock"

// Hello Go, we can't even declare const slices...
var regions = []string{
	"us-east-2",
	"us-east-1",
	"us-west-1",
	"us-west-2",
	"ca-central-1",
	"ap-south-1",
	"ap-northeast-2",
	"ap-southeast-1",
	"ap-southeast-2",
	"ap-northeast-1",
	"eu-central-1",
	"eu-west-1",
	"eu-west-2",
	"sa-east-1",
}

// TODO : ideally, the Config and initialization should be the same than the
// official Amazon EBS Builder
type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	Amount int    `mapstructure:"amount"`
	Region string `mapstructure:"region"`

	ctx interpolate.Context
}

type Builder struct {
	Config Config
	// The testMsg field used to get some feedback during tests from method
	// which don't return anything like Cancel()
	TestMsg string
}

func (b *Builder) LoadDefaultConfig() {
	log.Println("LoadDefaultConfig(): Initializing builder's configuration")
	b.Config = Config{}
	log.Println(b.Config)
	log.Println("LoadDefaultConfig(): Setting default: Amount = 1")
	b.Config.Amount = 1
	log.Println("LoadDefaultConfig(): Setting default: Region = \"\"")
	b.Config.Region = ""
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	log.Println("Hello I'm a custom builder and this is the Prepare step")

	b.LoadDefaultConfig()
	log.Println("Prepare(): initial configuration:")
	log.Println("  - Amount: ", b.Config.Amount)
	log.Println("  - Region: \"" + b.Config.Region + "\"")
	log.Println("Prepare(): parsing configuration")
	err := config.Decode(&b.Config, &config.DecodeOpts{Interpolate: false}, raws...)
	if err != nil {
		return nil, err
	}
	log.Println("Prepare(): parsed configuration with success")
	log.Println("Prepare(): current configuration:")
	log.Println("  - Amount: ", b.Config.Amount)
	log.Println("  - Region: \"" + b.Config.Region + "\"")

	log.Println("Prepare(): checking for incorrect parameters")
	if b.Config.Amount != 1 && b.Config.Region != "" {
		// TODO : Improve this error, maybe use Packer's types?
		return nil, errors.New("FAIL")
	}

	log.Println("Prepare(): Initializing random generator...")
	rand.Seed(time.Now().Unix())
	b.TestMsg = "Rand seeded"

	return nil, nil
}

func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	log.Println("Run(): Hello I'm a custom builder")

	amis := make(map[string]string)

	ui.Say(fmt.Sprintf("Generating mock Artifact (%d AMI IDs)...", b.Config.Amount))
	for i := 0; i < b.Config.Amount; i++ {
		amiID := fmt.Sprintf("ami-%06d", i+1)
		if b.Config.Region == "" {
			// Packer is not able to build 2 AMIs in the same
			// region in the same Builder, so:
			// - We take a random region
			// - We remove it from the pool

			// Take a random region
			idx := rand.Intn(len(regions))
			region := regions[idx]

			// Remove it from the pool
			regions[idx] = regions[len(regions)-1]
			regions = regions[:len(regions)-1]

			amis[region] = amiID
		} else {
			amis["eu-west-1"] = amiID
		}
	}

	log.Println("Run(): tranforming into official module artifact type...")
	artifact := &awscommon.Artifact{
		Amis:           amis,
		BuilderIDValue: BuilderID,
	}

	ui.Say("Generated mock Artifact with success :)")
	return artifact, nil
}

func (b *Builder) Cancel() {
	b.TestMsg = "This method is doing nothing"
}
<|endoftext|>


<commit_before>package healthcheck

import (
	"errors"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

func init() {
	registerHealthcheck("tcp", TcpConstructor)
}

type TcpHealthCheck struct {
	Destination string
	Port        string
	Send        string
	Expect      string
}

func (h TcpHealthCheck) Healthcheck() bool {
	//func (TcpPlugin) Perform(req *api.StatusRequest, ch chan bool) {
	log.Println("Probing TCP port " + h.Destination + ":" + h.Port)
	// Connect to the remote TCP port
	//
	c, err := net.Dial("tcp", h.Destination+":"+h.Port)
	if err != nil {
		log.Println("net.Dial: %s", err)
		return false
	}
	defer c.Close()
	c.SetDeadline(time.Now().Add(time.Second * 10))

	fmt.Fprintf(c, h.Send)
	// Read 1 byte from the TCP connection.
	//
	b := make([]byte, 1024)
	n, err := c.Read(b)
	if err != nil {
		log.Println(err)
		return false
	}
	answer := string(b[:n])
	if h.Expect == "" {
		return true
	} else {
		if strings.Contains(answer, h.Expect) {
			return true
		}
	}
	return false
}

func TcpConstructor(h Healthcheck) (HealthChecker, error) {
	if _, ok := h.Config["port"]; !ok {
		return TcpHealthCheck{}, errors.New("'port' not defined in tcp healthcheck config to " + h.Destination)
	}
	return TcpHealthCheck{
		Destination: h.Destination,
		Send:        "HEAD / HTTP/1.0\r\n\r\n",
		Expect:      "200 OK",
		Port:        h.Config["port"],
	}, nil
}
<commit_msg>Make that test pass<commit_after>package healthcheck

import (
	"errors"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

func init() {
	registerHealthcheck("tcp", TcpConstructor)
}

type TcpHealthCheck struct {
	Destination string
	Port        string
	Send        string
	Expect      string
}

func (h TcpHealthCheck) Healthcheck() bool {
	//func (TcpPlugin) Perform(req *api.StatusRequest, ch chan bool) {
	log.Println("Probing TCP port " + h.Destination + ":" + h.Port)
	// Connect to the remote TCP port
	//
	c, err := net.Dial("tcp", h.Destination+":"+h.Port)
	if err != nil {
		log.Println("net.Dial: %s", err.Error())
		return false
	}
	defer c.Close()
	c.SetDeadline(time.Now().Add(time.Second * 10))

	_, err = fmt.Fprintf(c, h.Send)
	if err != nil {
		log.Println("TCP send: %s", err.Error())
	}

	if h.Expect == "" {
		return true
	}

	b := make([]byte, 1024)
	n, err := c.Read(b)
	if err != nil {
		log.Println(err)
		return false
	}
	answer := string(b[:n])
	if strings.Contains(answer, h.Expect) {
		return true
	}
	return false
}

func TcpConstructor(h Healthcheck) (HealthChecker, error) {
	if _, ok := h.Config["port"]; !ok {
		return TcpHealthCheck{}, errors.New("'port' not defined in tcp healthcheck config to " + h.Destination)
	}
	hc := TcpHealthCheck{
		Destination: h.Destination,
		Send:        "HEAD / HTTP/1.0\r\n\r\n",
		Port:        h.Config["port"],
	}
	if v, ok := h.Config["expect"]; ok {
		hc.Expect = v
	}
	return hc, nil
}
<|endoftext|>


<commit_before>package permissions

import (
	"errors"
	"math/rand"
	"strings"
)

const (
	USERNAME_ALLOWED_LETTERS = "abcdefghijklmnopqrstuvwxyzæøåABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ_0123456789"
)

// Converts "true" or "false" to a bool
func TruthValue(val string) bool {
	return "true" == val
}

// Split a string at the colon into two strings
// If there's no colon, return the string and an empty string
func ColonSplit(s string) (string, string) {
	if strings.Contains(s, ":") {
		sl := strings.SplitN(s, ":", 2)
		return sl[0], sl[1]
	}
	return s, ""
}

func Min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func TableCell(b bool) string {
	if b {
		return "yes	"
	}
	return "no	"
}

func RandomString(length int) string {
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		b[i] = byte(rand.Int63() & 0xff)
	}
	return string(b)
}

func RandomHumanFriendlyString(length int) string {
	const (
		vowels     = "aeiouy" // email+browsers didn't like "æøå" too much
		consonants = "bcdfghjklmnpqrstvwxz"
	)
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		if i%2 == 0 {
			b[i] = vowels[rand.Intn(len(vowels))]
		} else {
			b[i] = consonants[rand.Intn(len(consonants))]
		}
	}
	return string(b)
}

func RandomCookieFriendlyString(length int) string {
	const ALLOWED = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		b[i] = ALLOWED[rand.Intn(len(ALLOWED))]
	}
	return string(b)
}

func CleanUserInput(val string) string {
	return strings.Replace(val, "<", "<", -1)
}

func Check(username, password, email string) error {
NEXT:
	for _, letter := range username {
		for _, allowedLetter := range USERNAME_ALLOWED_LETTERS {
			if letter == allowedLetter {
				continue NEXT
			}
		}
		return errors.New("Only a-å, A-Å, 0-9 and _ are allowed in usernames.")
	}
	if username == password {
		return errors.New("Username and password must be different, try another password.")
	}
	return nil
}
<commit_msg>Removed the Min function<commit_after>package permissions

import (
	"errors"
	"math/rand"
	"strings"
)

const (
	USERNAME_ALLOWED_LETTERS = "abcdefghijklmnopqrstuvwxyzæøåABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ_0123456789"
)

// Converts "true" or "false" to a bool
func TruthValue(val string) bool {
	return "true" == val
}

// Split a string at the colon into two strings
// If there's no colon, return the string and an empty string
func ColonSplit(s string) (string, string) {
	if strings.Contains(s, ":") {
		sl := strings.SplitN(s, ":", 2)
		return sl[0], sl[1]
	}
	return s, ""
}

func TableCell(b bool) string {
	if b {
		return "yes	"
	}
	return "no	"
}

func RandomString(length int) string {
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		b[i] = byte(rand.Int63() & 0xff)
	}
	return string(b)
}

func RandomHumanFriendlyString(length int) string {
	const (
		vowels     = "aeiouy" // email+browsers didn't like "æøå" too much
		consonants = "bcdfghjklmnpqrstvwxz"
	)
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		if i%2 == 0 {
			b[i] = vowels[rand.Intn(len(vowels))]
		} else {
			b[i] = consonants[rand.Intn(len(consonants))]
		}
	}
	return string(b)
}

func RandomCookieFriendlyString(length int) string {
	const ALLOWED = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := 0; i < length; i++ {
		b[i] = ALLOWED[rand.Intn(len(ALLOWED))]
	}
	return string(b)
}

func CleanUserInput(val string) string {
	return strings.Replace(val, "<", "<", -1)
}

func Check(username, password, email string) error {
NEXT:
	for _, letter := range username {
		for _, allowedLetter := range USERNAME_ALLOWED_LETTERS {
			if letter == allowedLetter {
				continue NEXT
			}
		}
		return errors.New("Only a-å, A-Å, 0-9 and _ are allowed in usernames.")
	}
	if username == password {
		return errors.New("Username and password must be different, try another password.")
	}
	return nil
}
<|endoftext|>


<commit_before>package hermes

import (
	"fmt"
	"crypto/sha1"
)

type HermesFile struct {
	name string
	contents string
}

func (file *HermesFile) generateFileName(file_ID int, file_checksum string) {
	file_name :=  fmt.Sprintf("Hermes_%02d%v", file_ID, file_checksum)
	file.name = file_name
}
func (file *HermesFile) generateFileContents(file_ID int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}
func (file HermesFile) generateFileChecksum() string {

	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	checksum := fmt.Sprintf("%s%x","_", hash)
	return checksum;
}
func GenerateFile (id int) HermesFile {
	file := HermesFile{}
	file.generateFileContents(id)
	checksum := file.generateFileChecksum()
	file.generateFileName(id, checksum)
	return file
}
<commit_msg>Update hermes/file_gen.go<commit_after>package hermes

import (
	"fmt"
	"crypto/sha1"
)

type HermesFile struct {
	name string
	contents string
}

func (file *HermesFile) generateFileName(file_id int, file_checksum string) {
	file_name :=  fmt.Sprintf("Hermes_%02d%v", file_ID, file_checksum)
	file.name = file_name
}
func (file *HermesFile) generateFileContents(file_ID int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}
func (file HermesFile) generateFileChecksum() string {

	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	checksum := fmt.Sprintf("%s%x","_", hash)
	return checksum;
}
func GenerateFile (id int) HermesFile {
	file := HermesFile{}
	file.generateFileContents(id)
	checksum := file.generateFileChecksum()
	file.generateFileName(id, checksum)
	return file
}
<|endoftext|>


<commit_before>// 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.

// Author: Alicja Kwiecinska (kwiecinskaa@google.com) github: alicjakwie

// File generation for Hermes
package hermes

import (
	"fmt"
	"crypto/sha1"
)

type HermesFile struct {
	Name string
	Contents string
}

// method of HermesFile generates HermesFile.name of the form Hermes_id_checksum where id is an integer & id <= 50
func (file *HermesFile) generateFileName(file_id int, file_checksum string) {
	file.name :=  fmt.Sprintf("Hermes_%02d_%v", file_id, file_checksum)
}

// method of HermesFile generates HermesFile.contents now a string without any significance in the future a pseudo random byte generator will be used
func (file *HermesFile) generateFileContents(file_id int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}

// method of HermesFile generates the checksum of the file contents
func (file HermesFile) generateFileChecksum() string {
	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	return fmt.Sprintf("%x", hash)
}

// method of HermesFile generates the file takes id as a parameter
func GenerateHermesFile (id int) HermesFile {
	file := HermesFile{}
	file.generateFileContents(id)
	checksum := file.generateFileChecksum()
	file.generateFileName(id, checksum)
	return file
}
<commit_msg>Update file_gen.go<commit_after>// 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.

// Author: Alicja Kwiecinska (kwiecinskaa@google.com) github: alicjakwie

// File generation for Hermes
package hermes

import (
	"fmt"
	"crypto/sha1"
)

type HermesFile struct {
	Name string
	Contents string
}

// method of HermesFile generates HermesFile.name of the form Hermes_id_checksum where id is an integer & id <= 50
func (file *HermesFile) generateFileName(file_id int, file_checksum string) {
	file.name =  fmt.Sprintf("Hermes_%02d_%v", file_id, file_checksum)
}

// method of HermesFile generates HermesFile.contents now a string without any significance in the future a pseudo random byte generator will be used
func (file *HermesFile) generateFileContents(file_id int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}

// method of HermesFile generates the checksum of the file contents
func (file HermesFile) generateFileChecksum() string {
	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	return fmt.Sprintf("%x", hash)
}

// method of HermesFile generates the file takes id as a parameter
func GenerateHermesFile (id int) HermesFile {
	file := HermesFile{}
	file.generateFileContents(id)
	checksum := file.generateFileChecksum()
	file.generateFileName(id, checksum)
	return file
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/nutrun/lentil"
	"log"
	"net/smtp"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type Listener struct {
	q        *lentil.Beanstalkd
	stopped  bool
	verbose  bool
	jobqueue *JobQueue
}

func NewListener(verbose, inclusive bool, filter []string) (*Listener, error) {
	this := new(Listener)
	q, err := lentil.Dial(Config.QueueAddr)

	if err != nil {
		return nil, err
	}

	this.q = q
	this.verbose = verbose
	this.jobqueue = NewJobQueue(this.q, inclusive, filter)
	return this, nil
}

func (this *Listener) execute(msg map[string]string) {
	workdir := msg["workdir"]
	e := os.Chdir(workdir)
	if e != nil {
		this.catch(msg, e)
	}
	messagetokens := strings.Split(msg["cmd"], " ")
	command := messagetokens[0]
	args := messagetokens[1:len(messagetokens)]
	cmd := exec.Command(command, args...)
	f, e := os.Create(msg["out"])
	if e != nil {
		this.catch(msg, e)
	}
	cmd.Stderr = f
	cmd.Stdout = f
	e = cmd.Run()
	if e != nil {
		this.catch(msg, e)
	}
	f.Close()
}

func (this *Listener) run() {
	go this.trap()

listenerloop:
	for {
		if this.stopped {
			os.Exit(0)
		}
		job, e := this.jobqueue.Next()
		if e != nil {
			if strings.Contains(e.Error(), "TIMED_OUT") {
				time.Sleep(time.Second)
				goto listenerloop
			}
			log.Fatal(e)
		}
		if this.verbose {
			log.Printf("RUNNING: %s", job.Body)
		}
		msg := make(map[string]string)
		json.Unmarshal([]byte(job.Body), &msg)
		this.execute(msg)
		e = this.jobqueue.Delete(job.Id)
		if e != nil {
			this.catch(msg, e)
		}
	}
}

// Log and email errors
func (this *Listener) catch(msg map[string]string, e error) {
	log.Printf("ERROR: %s\n", e.Error())
	if Config.SmtpServerAddr == "" {
		return
	}
	if len(msg["mailto"]) < 1 { //no email addresses
		return
	}
	to := strings.Split(msg["mailto"], ",")
	subject := fmt.Sprintf("Subject: FAILED: %s\r\n\r\n", msg["cmd"])
	hostname, _ := os.Hostname()
	mail := fmt.Sprintf("%s%s", subject, fmt.Sprintf("Ran on [%s]\n%s", hostname, e))
	e = smtp.SendMail(Config.SmtpServerAddr, nil, Config.MailFrom, to, []byte(mail))
	if e != nil {
		log.Printf("ERROR: %s\n", e)
	}
}

// Wait for currently running job to finish before exiting on SIGTERM and SIGINT
func (this *Listener) trap() {
	receivedSignal := make(chan os.Signal)
	signal.Notify(receivedSignal, syscall.SIGTERM, syscall.SIGINT)

	for {
		sig := <-receivedSignal
		log.Printf("Got signal %d. Waiting for current job to complete.", sig)
		this.stopped = true
	}
}
<commit_msg>added log content to e-mail<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/nutrun/lentil"
	"io/ioutil"
	"log"
	"net/smtp"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type Listener struct {
	q        *lentil.Beanstalkd
	stopped  bool
	verbose  bool
	jobqueue *JobQueue
}

func NewListener(verbose, inclusive bool, filter []string) (*Listener, error) {
	this := new(Listener)
	q, err := lentil.Dial(Config.QueueAddr)

	if err != nil {
		return nil, err
	}

	this.q = q
	this.verbose = verbose
	this.jobqueue = NewJobQueue(this.q, inclusive, filter)
	return this, nil
}

func (this *Listener) execute(msg map[string]string) {
	workdir := msg["workdir"]
	e := os.Chdir(workdir)
	if e != nil {
		this.catch(msg, e)
	}
	messagetokens := strings.Split(msg["cmd"], " ")
	command := messagetokens[0]
	args := messagetokens[1:len(messagetokens)]
	cmd := exec.Command(command, args...)
	f, e := os.Create(msg["out"])
	if e != nil {
		this.catch(msg, e)
	}
	cmd.Stderr = f
	cmd.Stdout = f
	e = cmd.Run()
	if e != nil {
		this.catch(msg, e)
	}
	f.Close()
}

func (this *Listener) run() {
	go this.trap()

listenerloop:
	for {
		if this.stopped {
			os.Exit(0)
		}
		job, e := this.jobqueue.Next()
		if e != nil {
			if strings.Contains(e.Error(), "TIMED_OUT") {
				time.Sleep(time.Second)
				goto listenerloop
			}
			log.Fatal(e)
		}
		if this.verbose {
			log.Printf("RUNNING: %s", job.Body)
		}
		msg := make(map[string]string)
		json.Unmarshal([]byte(job.Body), &msg)
		this.execute(msg)
		e = this.jobqueue.Delete(job.Id)
		if e != nil {
			this.catch(msg, e)
		}
	}
}

// Log and email errors
func (this *Listener) catch(msg map[string]string, e error) {
	log.Printf("ERROR: %s\n", e.Error())
	if Config.SmtpServerAddr == "" {
		return
	}
	if len(msg["mailto"]) < 1 { //no email addresses
		return
	}
	to := strings.Split(msg["mailto"], ",")
	subject := fmt.Sprintf("Subject: FAILED: %s\r\n\r\n", msg["cmd"])
	hostname, _ := os.Hostname()
	content, e := ioutil.ReadFile(msg["out"])
	if e != nil {
		content = []byte(fmt.Sprintf("Could not read job log from [%s]", msg["out"]))
	}
	mail := fmt.Sprintf("%s%s", subject, fmt.Sprintf("Ran on [%s]\n%s\n%s", hostname, e, content))
	e = smtp.SendMail(Config.SmtpServerAddr, nil, Config.MailFrom, to, []byte(mail))
	if e != nil {
		log.Printf("ERROR: %s\n", e)
	}
}

// Wait for currently running job to finish before exiting on SIGTERM and SIGINT
func (this *Listener) trap() {
	receivedSignal := make(chan os.Signal)
	signal.Notify(receivedSignal, syscall.SIGTERM, syscall.SIGINT)

	for {
		sig := <-receivedSignal
		log.Printf("Got signal %d. Waiting for current job to complete.", sig)
		this.stopped = true
	}
}
<|endoftext|>


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

package thrift

import (
	"bytes"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

type THttpClient struct {
	response           *http.Response
	url                *url.URL
	requestBuffer      *bytes.Buffer
	header             http.Header
	nsecConnectTimeout int64
	nsecReadTimeout    int64
}

type THttpClientTransportFactory struct {
	url    string
	isPost bool
}

func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport {
	if trans != nil {
		t, ok := trans.(*THttpClient)
		if ok && t.url != nil {
			if t.requestBuffer != nil {
				t2, _ := NewTHttpPostClient(t.url.String())
				return t2
			}
			t2, _ := NewTHttpClient(t.url.String())
			return t2
		}
	}
	if p.isPost {
		s, _ := NewTHttpPostClient(p.url)
		return s
	}
	s, _ := NewTHttpClient(p.url)
	return s
}

func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory {
	return &THttpClientTransportFactory{url: url, isPost: false}
}

func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory {
	return &THttpClientTransportFactory{url: url, isPost: true}
}

func NewTHttpClient(urlstr string) (TTransport, error) {
	parsedURL, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	response, err := http.Get(urlstr)
	if err != nil {
		return nil, err
	}
	return &THttpClient{response: response, url: parsedURL}, nil
}

func NewTHttpPostClient(urlstr string) (TTransport, error) {
	parsedURL, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 0, 1024)
	return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: http.Header{}}, nil
}

// Set the HTTP Header for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// httpTrans.SetHeader("User-Agent","Thrift Client 1.0")
func (p *THttpClient) SetHeader(key string, value string) {
	p.header.Add(key, value)
}

// Get the HTTP Header represented by the supplied Header Key for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// hdrValue := httpTrans.GetHeader("User-Agent")
func (p *THttpClient) GetHeader(key string) string {
	return p.header.Get(key)
}

// Deletes the HTTP Header given a Header Key for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// httpTrans.DelHeader("User-Agent")
func (p *THttpClient) DelHeader(key string) {
	p.header.Del(key)
}

func (p *THttpClient) Open() error {
	// do nothing
	return nil
}

func (p *THttpClient) IsOpen() bool {
	return p.response != nil || p.requestBuffer != nil
}

func (p *THttpClient) Close() error {
	if p.response != nil && p.response.Body != nil {
		err := p.response.Body.Close()
		p.response = nil
		return err
	}
	if p.requestBuffer != nil {
		p.requestBuffer.Reset()
		p.requestBuffer = nil
	}
	return nil
}

func (p *THttpClient) Read(buf []byte) (int, error) {
	if p.response == nil {
		return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.")
	}
	n, err := p.response.Body.Read(buf)
	if n > 0 && (err == nil || err == io.EOF) {
		return n, nil
	}
	return n, NewTTransportExceptionFromError(err)
}

func (p *THttpClient) ReadByte() (c byte, err error) {
	return readByte(p.response.Body)
}

func (p *THttpClient) Write(buf []byte) (int, error) {
	n, err := p.requestBuffer.Write(buf)
	return n, err
}

func (p *THttpClient) WriteByte(c byte) error {
	return p.requestBuffer.WriteByte(c)
}

func (p *THttpClient) WriteString(s string) (n int, err error) {
	return p.requestBuffer.WriteString(s)
}

func (p *THttpClient) Flush() error {
	client := &http.Client{}
	req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer)
	if err != nil {
		return NewTTransportExceptionFromError(err)
	}
	p.header.Add("Content-Type", "application/x-thrift")
	req.Header = p.header
	response, err := client.Do(req)
	if err != nil {
		return NewTTransportExceptionFromError(err)
	}
	if response.StatusCode != http.StatusOK {
		// Close the response to avoid leaking file descriptors.
		response.Body.Close()
		// TODO(pomack) log bad response
		return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode))
	}
	p.response = response
	return nil
}

func (p *THttpClient) RemainingBytes() (num_bytes uint64) {
	len := p.response.ContentLength
	if len >= 0 {
		return uint64(len)
	}

	const maxSize = ^uint64(0)
	return maxSize  // the thruth is, we just don't know unless framed is used
}

<commit_msg>THRIFT-3277 THttpClient leaks connections if it's used for multiple requests Client: Go Patch: Prashant Varanasi <prashant@uber.com><commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package thrift

import (
	"bytes"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

type THttpClient struct {
	response           *http.Response
	url                *url.URL
	requestBuffer      *bytes.Buffer
	header             http.Header
	nsecConnectTimeout int64
	nsecReadTimeout    int64
}

type THttpClientTransportFactory struct {
	url    string
	isPost bool
}

func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport {
	if trans != nil {
		t, ok := trans.(*THttpClient)
		if ok && t.url != nil {
			if t.requestBuffer != nil {
				t2, _ := NewTHttpPostClient(t.url.String())
				return t2
			}
			t2, _ := NewTHttpClient(t.url.String())
			return t2
		}
	}
	if p.isPost {
		s, _ := NewTHttpPostClient(p.url)
		return s
	}
	s, _ := NewTHttpClient(p.url)
	return s
}

func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory {
	return &THttpClientTransportFactory{url: url, isPost: false}
}

func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory {
	return &THttpClientTransportFactory{url: url, isPost: true}
}

func NewTHttpClient(urlstr string) (TTransport, error) {
	parsedURL, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	response, err := http.Get(urlstr)
	if err != nil {
		return nil, err
	}
	return &THttpClient{response: response, url: parsedURL}, nil
}

func NewTHttpPostClient(urlstr string) (TTransport, error) {
	parsedURL, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 0, 1024)
	return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: http.Header{}}, nil
}

// Set the HTTP Header for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// httpTrans.SetHeader("User-Agent","Thrift Client 1.0")
func (p *THttpClient) SetHeader(key string, value string) {
	p.header.Add(key, value)
}

// Get the HTTP Header represented by the supplied Header Key for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// hdrValue := httpTrans.GetHeader("User-Agent")
func (p *THttpClient) GetHeader(key string) string {
	return p.header.Get(key)
}

// Deletes the HTTP Header given a Header Key for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
//
// httpTrans := trans.(THttpClient)
// httpTrans.DelHeader("User-Agent")
func (p *THttpClient) DelHeader(key string) {
	p.header.Del(key)
}

func (p *THttpClient) Open() error {
	// do nothing
	return nil
}

func (p *THttpClient) IsOpen() bool {
	return p.response != nil || p.requestBuffer != nil
}

func (p *THttpClient) closeResponse() error {
	var err error
	if p.response != nil && p.response.Body != nil {
		err = p.response.Body.Close()
	}

	p.response = nil
	return err
}

func (p *THttpClient) Close() error {
	if p.requestBuffer != nil {
		p.requestBuffer.Reset()
		p.requestBuffer = nil
	}
	return p.closeResponse()
}

func (p *THttpClient) Read(buf []byte) (int, error) {
	if p.response == nil {
		return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.")
	}
	n, err := p.response.Body.Read(buf)
	if n > 0 && (err == nil || err == io.EOF) {
		return n, nil
	}
	return n, NewTTransportExceptionFromError(err)
}

func (p *THttpClient) ReadByte() (c byte, err error) {
	return readByte(p.response.Body)
}

func (p *THttpClient) Write(buf []byte) (int, error) {
	n, err := p.requestBuffer.Write(buf)
	return n, err
}

func (p *THttpClient) WriteByte(c byte) error {
	return p.requestBuffer.WriteByte(c)
}

func (p *THttpClient) WriteString(s string) (n int, err error) {
	return p.requestBuffer.WriteString(s)
}

func (p *THttpClient) Flush() error {
	// Close any previous response body to avoid leaking connections.
	p.closeResponse()

	client := &http.Client{}
	req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer)
	if err != nil {
		return NewTTransportExceptionFromError(err)
	}
	p.header.Add("Content-Type", "application/x-thrift")
	req.Header = p.header
	response, err := client.Do(req)
	if err != nil {
		return NewTTransportExceptionFromError(err)
	}
	if response.StatusCode != http.StatusOK {
		// Close the response to avoid leaking file descriptors.
		response.Body.Close()
		// TODO(pomack) log bad response
		return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode))
	}
	p.response = response
	return nil
}

func (p *THttpClient) RemainingBytes() (num_bytes uint64) {
	len := p.response.ContentLength
	if len >= 0 {
		return uint64(len)
	}

	const maxSize = ^uint64(0)
	return maxSize  // the thruth is, we just don't know unless framed is used
}

<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/mohae/benchutil"
)

const (
	Flat = "FlatBuffers"
	JSON = "JSON"
)

// flags
var (
	output         string
	format         string
	section        bool
	sectionHeaders bool
	nameSections   bool
)

func init() {
	flag.StringVar(&output, "output", "stdout", "output destination")
	flag.StringVar(&output, "o", "stdout", "output destination (short)")
	flag.StringVar(&format, "format", "txt", "format of output")
	flag.StringVar(&format, "f", "txt", "format of output")
	flag.BoolVar(&nameSections, "namesections", false, "use group as section name: some restrictions apply")
	flag.BoolVar(&nameSections, "n", false, "use group as section name: some restrictions apply")
	flag.BoolVar(&section, "sections", false, "don't separate groups of tests into sections")
	flag.BoolVar(&section, "s", false, "don't separate groups of tests into sections")
	flag.BoolVar(&sectionHeaders, "sectionheader", false, "if there are sections, add a section header row")
	flag.BoolVar(&sectionHeaders, "h", false, "if there are sections, add a section header row")
}

func main() {
	flag.Parse()
	done := make(chan struct{})
	go benchutil.Dot(done)

	// set the output
	var w io.Writer
	var err error
	switch output {
	case "stdout":
		w = os.Stdout
	default:
		w, err = os.OpenFile(output, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		defer w.(*os.File).Close()
	}
	// get the benchmark for the desired format
	// process the output
	var bench benchutil.Benchmarker
	switch format {
	case "csv":
		bench = benchutil.NewCSVBench(w)
	case "md":
		bench = benchutil.NewMDBench(w)
		bench.(*benchutil.MDBench).GroupAsSectionName = nameSections
	default:
		bench = benchutil.NewStringBench(w)
	}
	bench.SectionPerGroup(section)
	bench.SectionHeaders(sectionHeaders)
	// CPU
	runCPUBenchmarks(bench)

	// Disk
	runDiskBenchmarks(bench)

	fmt.Println("\ngenerating output...\n")
	err = bench.Out()
	if err != nil {
		fmt.Printf("error generating output: %s\n", err)
	}
}

func runCPUBenchmarks(bench benchutil.Benchmarker) {
	b := CPUGetFacts()
	bench.Add(b)

	b = CPUGetFactsFB()
	bench.Add(b)

	b = CPUFactsSerializeFB()
	bench.Add(b)

	b = CPUFactsDeserializeFB()
	bench.Add(b)

	b = CPUGetFactsJSON()
	bench.Add(b)

	b = CPUFactsSerializeJSON()
	bench.Add(b)

	b = CPUFactsDeserializeJSON()
	bench.Add(b)

	b = CPUGetStats()
	bench.Add(b)

	b = CPUGetStatsFB()
	bench.Add(b)

	b = CPUStatsSerializeFB()
	bench.Add(b)

	b = CPUStatsDeserializeFB()
	bench.Add(b)

	b = CPUGetStatsJSON()
	bench.Add(b)

	b = CPUStatsSerializeJSON()
	bench.Add(b)

	b = CPUStatsDeserializeJSON()
	bench.Add(b)

	b = CPUGetUtilization()
	bench.Add(b)

	b = CPUGetUtilizationFB()
	bench.Add(b)

	b = CPUUtilizationSerializeFB()
	bench.Add(b)

	b = CPUUtilizationDeserializeFB()
	bench.Add(b)

	b = CPUGetUtilizationJSON()
	bench.Add(b)

	b = CPUUtilizationSerializeJSON()
	bench.Add(b)

	b = CPUUtilizationDeserializeJSON()
	bench.Add(b)
}

func runDiskBenchmarks(bench benchutil.Benchmarker) {
	b := DiskGetStats()
	bench.Add(b)

	b = DiskGetStatsJSON()
	bench.Add(b)

	b = DiskStatsSerializeJSON()
	bench.Add(b)

	b = DiskStatsDeserializeJSON()
	bench.Add(b)

	b = DiskGetUsage()
	bench.Add(b)

	b = DiskGetUsageFB()
	bench.Add(b)

	b = DiskUsageSerializeFB()
	bench.Add(b)

	b = DiskUsageDeserializeFB()
	bench.Add(b)

	b = DiskGetUsageJSON()
	bench.Add(b)

	b = DiskUsageSerializeJSON()
	bench.Add(b)

	b = DiskUsageDeserializeJSON()
	bench.Add(b)
}
<commit_msg>add mem benchmark to bench app<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/mohae/benchutil"
)

const (
	Flat = "FlatBuffers"
	JSON = "JSON"
)

// flags
var (
	output         string
	format         string
	section        bool
	sectionHeaders bool
	nameSections   bool
)

func init() {
	flag.StringVar(&output, "output", "stdout", "output destination")
	flag.StringVar(&output, "o", "stdout", "output destination (short)")
	flag.StringVar(&format, "format", "txt", "format of output")
	flag.StringVar(&format, "f", "txt", "format of output")
	flag.BoolVar(&nameSections, "namesections", false, "use group as section name: some restrictions apply")
	flag.BoolVar(&nameSections, "n", false, "use group as section name: some restrictions apply")
	flag.BoolVar(&section, "sections", false, "don't separate groups of tests into sections")
	flag.BoolVar(&section, "s", false, "don't separate groups of tests into sections")
	flag.BoolVar(&sectionHeaders, "sectionheader", false, "if there are sections, add a section header row")
	flag.BoolVar(&sectionHeaders, "h", false, "if there are sections, add a section header row")
}

func main() {
	flag.Parse()
	done := make(chan struct{})
	go benchutil.Dot(done)

	// set the output
	var w io.Writer
	var err error
	switch output {
	case "stdout":
		w = os.Stdout
	default:
		w, err = os.OpenFile(output, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		defer w.(*os.File).Close()
	}
	// get the benchmark for the desired format
	// process the output
	var bench benchutil.Benchmarker
	switch format {
	case "csv":
		bench = benchutil.NewCSVBench(w)
	case "md":
		bench = benchutil.NewMDBench(w)
		bench.(*benchutil.MDBench).GroupAsSectionName = nameSections
	default:
		bench = benchutil.NewStringBench(w)
	}
	bench.SectionPerGroup(section)
	bench.SectionHeaders(sectionHeaders)
	// CPU
	runCPUBenchmarks(bench)

	// Disk
	runDiskBenchmarks(bench)

	// Memory
	runMemBenchmarks(bench)

	fmt.Println("\ngenerating output...\n")
	err = bench.Out()
	if err != nil {
		fmt.Printf("error generating output: %s\n", err)
	}
}

func runCPUBenchmarks(bench benchutil.Benchmarker) {
	b := CPUGetFacts()
	bench.Add(b)

	b = CPUGetFactsFB()
	bench.Add(b)

	b = CPUFactsSerializeFB()
	bench.Add(b)

	b = CPUFactsDeserializeFB()
	bench.Add(b)

	b = CPUGetFactsJSON()
	bench.Add(b)

	b = CPUFactsSerializeJSON()
	bench.Add(b)

	b = CPUFactsDeserializeJSON()
	bench.Add(b)

	b = CPUGetStats()
	bench.Add(b)

	b = CPUGetStatsFB()
	bench.Add(b)

	b = CPUStatsSerializeFB()
	bench.Add(b)

	b = CPUStatsDeserializeFB()
	bench.Add(b)

	b = CPUGetStatsJSON()
	bench.Add(b)

	b = CPUStatsSerializeJSON()
	bench.Add(b)

	b = CPUStatsDeserializeJSON()
	bench.Add(b)

	b = CPUGetUtilization()
	bench.Add(b)

	b = CPUGetUtilizationFB()
	bench.Add(b)

	b = CPUUtilizationSerializeFB()
	bench.Add(b)

	b = CPUUtilizationDeserializeFB()
	bench.Add(b)

	b = CPUGetUtilizationJSON()
	bench.Add(b)

	b = CPUUtilizationSerializeJSON()
	bench.Add(b)

	b = CPUUtilizationDeserializeJSON()
	bench.Add(b)
}

func runDiskBenchmarks(bench benchutil.Benchmarker) {
	b := DiskGetStats()
	bench.Add(b)

	b = DiskGetStatsJSON()
	bench.Add(b)

	b = DiskStatsSerializeJSON()
	bench.Add(b)

	b = DiskStatsDeserializeJSON()
	bench.Add(b)

	b = DiskGetUsage()
	bench.Add(b)

	b = DiskGetUsageFB()
	bench.Add(b)

	b = DiskUsageSerializeFB()
	bench.Add(b)

	b = DiskUsageDeserializeFB()
	bench.Add(b)

	b = DiskGetUsageJSON()
	bench.Add(b)

	b = DiskUsageSerializeJSON()
	bench.Add(b)

	b = DiskUsageDeserializeJSON()
	bench.Add(b)
}

func runMemBenchmarks(bench benchutil.Benchmarker) {
	b := MemInfoGet()
	bench.Add(b)

	b = MemInfoGetFB()
	bench.Add(b)

	b = MemInfoSerializeFB()
	bench.Add(b)

	b = MemInfoDeserializeFB()
	bench.Add(b)

	b = MemInfoGetSON()
	bench.Add(b)

	b = MemInfoSerializeJSON()
	bench.Add(b)

	b = MemInfoDeserializeJSON()
	bench.Add(b)
}
<|endoftext|>


<commit_before>package eval

import (
	"github.com/cirbo-lang/cirbo/cbty"
	"github.com/cirbo-lang/cirbo/source"
)

type device struct {
	name    string
	callSig *cbty.CallSignature
	attrs   StmtBlockAttrs
	block   StmtBlock
	instTy  cbty.Type
}

type deviceModelImpl struct {
	dev *device
}

func deviceValue(dev *device) cbty.Value {
	ty := cbty.Model(deviceModelImpl{dev})
	return cbty.ModelVal(ty, dev)
}

func (i deviceModelImpl) Name() string {
	return "Device"
}

func (i deviceModelImpl) SuitableValue(raw interface{}) bool {
	_, isDevice := raw.(*device)
	return isDevice
}

func (i deviceModelImpl) GetAttr(raw interface{}, name string) cbty.Value {
	return cbty.NilValue
}

func (i deviceModelImpl) CallSignature() *cbty.CallSignature {
	return i.dev.callSig
}

func (i deviceModelImpl) Call(callee interface{}, args cbty.CallArgs) (cbty.Value, source.Diags) {
	// TODO: implement
	panic("not callable yet")
}

type deviceInstance struct {
	device *device
	block  *StmtBlockResult
}

type deviceInstanceModelImpl struct {
	device *device
}

func deviceInstanceType(dev *device) cbty.Type {
	return cbty.Model(deviceInstanceModelImpl{dev})
}

func deviceInstanceValue(ty cbty.Type, di *deviceInstance) cbty.Value {
	return cbty.ModelVal(ty, di)
}

func (i deviceInstanceModelImpl) Name() string {
	return "Device"
}

func (i deviceInstanceModelImpl) SuitableValue(raw interface{}) bool {
	di, isInstance := raw.(*deviceInstance)
	if !isInstance {
		return false
	}
	return di.device == i.device
}

func (i deviceInstanceModelImpl) GetAttr(raw interface{}, name string) cbty.Value {
	return cbty.NilValue
}

func (i deviceInstanceModelImpl) CallSignature() *cbty.CallSignature {
	return nil
}

func (i deviceInstanceModelImpl) Call(callee interface{}, args cbty.CallArgs) (cbty.Value, source.Diags) {
	panic("not callable") // should never get here because CallSignature returns nil
}
<commit_msg>eval: a note for later about why we can't implement Call for device types<commit_after>package eval

import (
	"github.com/cirbo-lang/cirbo/cbty"
	"github.com/cirbo-lang/cirbo/source"
)

type device struct {
	name    string
	callSig *cbty.CallSignature
	attrs   StmtBlockAttrs
	block   StmtBlock
	instTy  cbty.Type
}

type deviceModelImpl struct {
	dev *device
}

func deviceValue(dev *device) cbty.Value {
	ty := cbty.Model(deviceModelImpl{dev})
	return cbty.ModelVal(ty, dev)
}

func (i deviceModelImpl) Name() string {
	return "Device"
}

func (i deviceModelImpl) SuitableValue(raw interface{}) bool {
	_, isDevice := raw.(*device)
	return isDevice
}

func (i deviceModelImpl) GetAttr(raw interface{}, name string) cbty.Value {
	return cbty.NilValue
}

func (i deviceModelImpl) CallSignature() *cbty.CallSignature {
	return i.dev.callSig
}

func (i deviceModelImpl) Call(callee interface{}, args cbty.CallArgs) (cbty.Value, source.Diags) {
	//dev := callee.(*device)

	// FIXME: need access to the eval context in here so we can
	// evaluate our block.

	panic("not callable yet")
}

type deviceInstance struct {
	device *device
	block  *StmtBlockResult
}

type deviceInstanceModelImpl struct {
	device *device
}

func deviceInstanceType(dev *device) cbty.Type {
	return cbty.Model(deviceInstanceModelImpl{dev})
}

func deviceInstanceValue(ty cbty.Type, di *deviceInstance) cbty.Value {
	return cbty.ModelVal(ty, di)
}

func (i deviceInstanceModelImpl) Name() string {
	return "Device"
}

func (i deviceInstanceModelImpl) SuitableValue(raw interface{}) bool {
	di, isInstance := raw.(*deviceInstance)
	if !isInstance {
		return false
	}
	return di.device == i.device
}

func (i deviceInstanceModelImpl) GetAttr(raw interface{}, name string) cbty.Value {
	return cbty.NilValue
}

func (i deviceInstanceModelImpl) CallSignature() *cbty.CallSignature {
	return nil
}

func (i deviceInstanceModelImpl) Call(callee interface{}, args cbty.CallArgs) (cbty.Value, source.Diags) {
	panic("not callable") // should never get here because CallSignature returns nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/yxpod/pbconf/conf"
)

var (
	msg = flag.String("msg", "PBConf", "pb top message name")
	pkg = flag.String("pkg", "pbconf", "pb package name")
	f   = flag.String("f", "pbconf.proto", ".proto output file")
	o   = flag.String("o", "pbconf.pb", "encoded tables output file")
	t   = flag.String("t", "pbconf.txt", "text output file")
)

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: pbconf [-msg msg] [-pkg pkg] [-f file] [-o file] table-path")
		flag.PrintDefaults()
	}
	flag.Parse()

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

	conf, err := conf.LoadPBConf(flag.Args()[0])
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	ff, err := os.OpenFile(*f, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer ff.Close()
	conf.WriteProto(ff, *pkg, *msg)

	of, err := os.OpenFile(*o, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer of.Close()
	conf.WriteData(of)

	tf, err := os.OpenFile(*t, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer tf.Close()
	conf.WriteText(tf)
}
<commit_msg>usage<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/yxpod/pbconf/conf"
)

var (
	msg = flag.String("msg", "PBConf", "pb top message name")
	pkg = flag.String("pkg", "pbconf", "pb package name")
	f   = flag.String("f", "pbconf.proto", ".proto output file")
	o   = flag.String("o", "pbconf.pb", "encoded tables output file")
	t   = flag.String("t", "pbconf.txt", "text output file")
)

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: pbconf [-msg msg] [-pkg pkg] [-f file] [-o file] [-t file] table-path")
		flag.PrintDefaults()
	}
	flag.Parse()

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

	conf, err := conf.LoadPBConf(flag.Args()[0])
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	ff, err := os.OpenFile(*f, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer ff.Close()
	conf.WriteProto(ff, *pkg, *msg)

	of, err := os.OpenFile(*o, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer of.Close()
	conf.WriteData(of)

	tf, err := os.OpenFile(*t, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer tf.Close()
	conf.WriteText(tf)
}
<|endoftext|>


<commit_before>package gomarathon

import (
	"fmt"
)

/*
* Application requests
 */

// ListApps is listing all apps
func (c *Client) ListApps() (*Response, error) {
	return c.ListAppsByCmd("")
}

// ListAppsByCmd list all apps by cmd filter
func (c *Client) ListAppsByCmd(filter string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps"),
		Params: &Parameters{
			Cmd: filter,
		},
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	return r, nil
}

// ListAppVersions list app versions from a define appid
func (c *Client) ListAppVersions(appID string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s/versions", appID),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	return r, nil
}

// GetApp gets a single app with production version
func (c *Client) GetApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s", appID),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	if r.Code != 200 {
		return nil, fmt.Errorf("request error")
	}
	return r, nil
}

// GetAppVersion get a single version from a single app
func (c *Client) GetAppVersion(appID string, version string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s/versions/%s", appID, version),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	if r.Code != 200 {
		return nil, fmt.Errorf("request error")
	}
	return r, nil
}

// CreateApp Create a new Application
func (c *Client) CreateApp(app *Application) (*Response, error) {
	// TODO : VALIDATE DATAS
	options := &RequestOptions{
		Path:   "apps",
		Datas:  app,
		Method: "POST",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 201 {
			return r, nil
		}
	}
	return nil, err
}

// UpdateApp update the app but thoses changes are made for the next running app and does
// not shut down the production applications
func (c *Client) UpdateApp(appID string, app *Application) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s", appID),
		Datas:  app,
		Method: "PUT",
	}
	r, err := c.request(options)
	if r != nil {
		if (r.Code == 204) || (r.Code == 200) {
			return r, nil
		}
	}
	return nil, err

}

// DeleteApp delete this app from the cluster
func (c *Client) DeleteApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s", appID),
		Method: "DELETE",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 204 {
			return r, nil
		}
	}
	return nil, err
}

func (c *Client) DeleteDeployment(deploymentID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("deployments/%s", deploymentID),
		Method: "DELETE",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 204 {
			return r, nil
		}
	}
	return nil, err
}

func (c *Client) RestartApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s/restart", appID),
		Method: "POST",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 204 {
			return r, nil
		}
	}
	return nil, err
}
<commit_msg>Delete deployment endpoint responds with either 200 OK or 202 Accepted. See https://mesosphere.github.io/marathon/docs/rest-api.html#delete-v2-deployments-deploymentid<commit_after>package gomarathon

import (
	"fmt"
)

/*
* Application requests
 */

// ListApps is listing all apps
func (c *Client) ListApps() (*Response, error) {
	return c.ListAppsByCmd("")
}

// ListAppsByCmd list all apps by cmd filter
func (c *Client) ListAppsByCmd(filter string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps"),
		Params: &Parameters{
			Cmd: filter,
		},
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	return r, nil
}

// ListAppVersions list app versions from a define appid
func (c *Client) ListAppVersions(appID string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s/versions", appID),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	return r, nil
}

// GetApp gets a single app with production version
func (c *Client) GetApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s", appID),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	if r.Code != 200 {
		return nil, fmt.Errorf("request error")
	}
	return r, nil
}

// GetAppVersion get a single version from a single app
func (c *Client) GetAppVersion(appID string, version string) (*Response, error) {
	options := &RequestOptions{
		Path: fmt.Sprintf("apps/%s/versions/%s", appID, version),
	}
	r, err := c.request(options)
	if err != nil {
		return nil, err
	}
	if r.Code != 200 {
		return nil, fmt.Errorf("request error")
	}
	return r, nil
}

// CreateApp Create a new Application
func (c *Client) CreateApp(app *Application) (*Response, error) {
	// TODO : VALIDATE DATAS
	options := &RequestOptions{
		Path:   "apps",
		Datas:  app,
		Method: "POST",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 201 {
			return r, nil
		}
	}
	return nil, err
}

// UpdateApp update the app but thoses changes are made for the next running app and does
// not shut down the production applications
func (c *Client) UpdateApp(appID string, app *Application) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s", appID),
		Datas:  app,
		Method: "PUT",
	}
	r, err := c.request(options)
	if r != nil {
		if (r.Code == 204) || (r.Code == 200) {
			return r, nil
		}
	}
	return nil, err

}

// DeleteApp delete this app from the cluster
func (c *Client) DeleteApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s", appID),
		Method: "DELETE",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 204 {
			return r, nil
		}
	}
	return nil, err
}

func (c *Client) DeleteDeployment(deploymentID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("deployments/%s", deploymentID),
		Method: "DELETE",
	}
	r, err := c.request(options)
	if r != nil {
		if (r.Code == 200) || (r.Code == 202) {
			return r, nil
		}
	}
	return nil, err
}

func (c *Client) RestartApp(appID string) (*Response, error) {
	options := &RequestOptions{
		Path:   fmt.Sprintf("apps/%s/restart", appID),
		Method: "POST",
	}
	r, err := c.request(options)
	if r != nil {
		if r.Code == 204 {
			return r, nil
		}
	}
	return nil, err
}
<|endoftext|>