<commit_before>// Copyright (c) 2013, Bartosz Kratochwil
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.

//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.

//     * Neither the name of Aaron France nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package hpcloud

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

/*
 ListDBInstances will list all the available database instances

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-database-instances.html
*/
func (a Access) ListDBInstances() (*DBInstances, error) {
	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	dbs := &DBInstances{}
	err = json.Unmarshal(body, dbs)
	return dbs, err
}

/*
 This function takes instance ID and deletes database instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/delete-instance.html
*/
func (a Access) DeleteDBInstance(instanceID string) error {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID,
		instanceID)
	_, err := a.baseRequest(url, "DELETE", nil)
	return err
}

/*
 This function takes instance ID and restarts DB instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/restart-instance.html
*/
func (a Access) RestartDBInstance(instanceID string) error {
	b := `{"restart":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, instanceID)
	_, err := a.baseRequest(url, "POST", strings.NewReader(b))
	return err
}

/*
 ListAllFlavors lists all available database flavors.
 This function implements interface as described in:-
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-flavors.html
*/
func (a Access) ListAllFlavors() (*DBFlavors, error) {
	url := fmt.Sprintf("%s%s/flavors", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavors{}
	err = json.Unmarshal(body, flv)
	return flv, err
}

/*
 This function returns flavor specs for given flavor.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-flavor.html
*/
func (a Access) GetDBFlavor(ID string) (*DBFlavor, error) {
	url := fmt.Sprintf("%s/flavors/%s", RDB_URL, ID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavor{}
	err = json.Unmarshal(body, flv)
	if err != nil {
		return nil, err
	}
	return flv, nil
}

/*
 CreateDBInstance creates new database instance in the HPCloud using
settings found in the DatabaseReq instance passed to this function

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/create-instance.html
*/
func (a Access) CreateDBInstance(db DatabaseReq) (*NewDBInstance, error) {
	b, err := db.MarshalJSON()
	if err != nil {
		return nil, err
	}

	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)

	body, err := a.baseRequest(url, "POST",
		strings.NewReader(string(b)))
	if err != nil {
		return nil, err
	}

	type respDB struct {
		Instance NewDBInstance `json:"instance"`
	}

	sr := &respDB{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.Instance, nil
}

/*
 This function retrieves details of the instance with provided ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-instance.html
*/
func (a Access) GetDBInstance(id string) (*InstDetails, error) {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID, id)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	det := &InstDetails{}
	err = json.Unmarshal(body, det)
	return det, err
}

/*
 This function takes instance ID and resets password for this instance. It
 returns a new instance password.

 This function implements the interface as decribed in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/reset-instance-password.html
*/
func (a Access) ResetDBPassword(id string) (*DBCredentials, error) {
	b := `{"reset-password":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, id)
	body, err := a.baseRequest(url, "POST", strings.NewReader(b))

	sr := &DBCredentials{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return sr, nil
}

type DBInstance struct {
	Created string `json:"created"`
	Id      string `json:"id"`
	Links   []Link `json:"links"`
	Name    string `json:"name"`
	Status  string `json:"name"`
	Flavor  struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

type DBInstances struct {
	Instances []DBInstance `json:"instances"`
}

type Database struct {
	Name      string `json:"name"`
	FlavorRef string `json:"flavorRef"`
	Port      int    `json:"port"`
	DBType    struct {
		Name    string `json:"name"`
		Version string `json:"version"`
	} `json:"dbtype"`
}

type DBFlavors struct {
	Flavors []DBFlavor `json:"flavors"`
}

/*
 Instance Details type that is returned by server
*/
type InstDetails struct {
	Created        string          `json:"created"`
	Hostname       string          `json:"hostname"`
	ID             string          `json:"id"`
	Links          []Link          `json:"links"`
	Name           string          `json:"name"`
	Port           int             `json:"port"`
	SecurityGroups []SecurityGroup `json:"security_groups"`
	Status         string          `json:"status"`
	Updated        string          `json:"updated"`
	Flavor         struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

/*
 Type describing database flavor
*/
type DBFlavor struct {
	Id    int    `json:"id"`
	Links []Link `json:"links"`
	Name  string `json:"name"`
	Ram   int    `json:"ram"`
	Vcpu  int    `json:"vcpu"`
}

/*
 This type describes the JSON data which should be sent to the
create database instance resource.
*/
type DatabaseReq struct {
	Instance Database `json:"instance"`
}

/*
 This type describes JSON response from a successful CreateDBInstance
 call.
*/
type NewDBInstance struct {
	Created    string        `json:"created"`
	Credential DBCredentials `json:"credential"`
	Flavor     struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
	Hostname       string        `json:"hostname"`
	Id             string        `json:"id"`
	Links          []Link        `json:"links"`
	Name           string        `json:"name"`
	SecurityGroups []DBSecGroups `json:"security_groups"`
	Status         string        `json:"status"`
}

/*
 This type describes Database Security groups
*/
type DBSecGroups struct {
	Id    string `json:"id"`
	Links []Link `json:"links"`
}

/*
 This type describes Database Credentials
*/
type DBCredentials struct {
	Password string `json:"password"`
	Username string `json:"username"`
}

func (f DBFlavors) GetFlavorRef(fn string) string {
	for _, val := range f.Flavors {
		if val.Name == fn {
			return val.Links[0].HREF
		}
	}
	panic("Flavor not found")
}

func (db DatabaseReq) MarshalJSON() ([]byte, error) {
	b := bytes.NewBufferString(`{"instance":{`)
	if db.Instance.Name == "" {
		return nil, errors.New("A name is required")
	}
	b.WriteString(fmt.Sprintf(`"name":"%s",`, db.Instance.Name))
	if db.Instance.FlavorRef == "" {
		return nil, errors.New("Flavor is required")
	}
	b.WriteString(fmt.Sprintf(`"flavorRef":"%s",`,
		db.Instance.FlavorRef))
	if db.Instance.Port == 0 {
		b.WriteString(`"port":"3306",`)
	} else {
		b.WriteString(fmt.Sprintf(`"port":"%s",`, db.Instance.Port))
	}
	b.WriteString(`"dbtype":{`)
	b.WriteString(`"name":"mysql",`)
	b.WriteString(`"version":"5.5"}}}`)

	return b.Bytes(), nil
}
<commit_msg>list security groups added<commit_after>// Copyright (c) 2013, Bartosz Kratochwil
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.

//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.

//     * Neither the name of Aaron France nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package hpcloud

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

/*
 ListDBInstances will list all the available database instances

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-database-instances.html
*/
func (a Access) ListDBInstances() (*DBInstances, error) {
	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	dbs := &DBInstances{}
	err = json.Unmarshal(body, dbs)
	return dbs, err
}

/*
 This function takes instance ID and deletes database instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/delete-instance.html
*/
func (a Access) DeleteDBInstance(instanceID string) error {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID,
		instanceID)
	_, err := a.baseRequest(url, "DELETE", nil)
	return err
}

/*
 This function takes instance ID and restarts DB instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/restart-instance.html
*/
func (a Access) RestartDBInstance(instanceID string) error {
	b := `{"restart":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, instanceID)
	_, err := a.baseRequest(url, "POST", strings.NewReader(b))
	return err
}

/*
 ListAllFlavors lists all available database flavors.
 This function implements interface as described in:-
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-flavors.html
*/
func (a Access) ListAllFlavors() (*DBFlavors, error) {
	url := fmt.Sprintf("%s%s/flavors", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavors{}
	err = json.Unmarshal(body, flv)
	return flv, err
}

/*
 This function returns flavor specs for given flavor.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-flavor.html
*/
func (a Access) GetDBFlavor(ID string) (*DBFlavor, error) {
	url := fmt.Sprintf("%s/flavors/%s", RDB_URL, ID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavor{}
	err = json.Unmarshal(body, flv)
	if err != nil {
		return nil, err
	}
	return flv, nil
}

/*
 CreateDBInstance creates new database instance in the HPCloud using
settings found in the DatabaseReq instance passed to this function

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/create-instance.html
*/
func (a Access) CreateDBInstance(db DatabaseReq) (*NewDBInstance, error) {
	b, err := db.MarshalJSON()
	if err != nil {
		return nil, err
	}

	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)

	body, err := a.baseRequest(url, "POST",
		strings.NewReader(string(b)))
	if err != nil {
		return nil, err
	}

	type respDB struct {
		Instance NewDBInstance `json:"instance"`
	}

	sr := &respDB{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.Instance, nil
}

/*
 This function retrieves details of the instance with provided ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-instance.html
*/
func (a Access) GetDBInstance(id string) (*InstDetails, error) {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID, id)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	det := &InstDetails{}
	err = json.Unmarshal(body, det)
	return det, err
}

/*
 This function takes instance ID and resets password for this instance. It
 returns a new instance password.

 This function implements the interface as decribed in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/reset-instance-password.html
*/
func (a Access) ResetDBPassword(id string) (*DBCredentials, error) {
	b := `{"reset-password":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, id)
	body, err := a.baseRequest(url, "POST", strings.NewReader(b))

	sr := &DBCredentials{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return sr, nil
}

/*
 This function lists all the security groups available for tenant.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-security-groups.html
*/
func (a Access) GetDBSecurityGroups(*SecurityGroup, error) {
	url := fmt.Sprintf("%s%s/security-groups", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)

	type resp struct {
		SecurityGroups SecurityGroup `json:"security-groups"`
	}
	sr = &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.SecurityGroups, nil
}

type DBInstance struct {
	Created string `json:"created"`
	Id      string `json:"id"`
	Links   []Link `json:"links"`
	Name    string `json:"name"`
	Status  string `json:"name"`
	Flavor  struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

type DBInstances struct {
	Instances []DBInstance `json:"instances"`
}

type Database struct {
	Name      string `json:"name"`
	FlavorRef string `json:"flavorRef"`
	Port      int    `json:"port"`
	DBType    struct {
		Name    string `json:"name"`
		Version string `json:"version"`
	} `json:"dbtype"`
}

type DBFlavors struct {
	Flavors []DBFlavor `json:"flavors"`
}

/*
 Instance Details type that is returned by server
*/
type InstDetails struct {
	Created        string          `json:"created"`
	Hostname       string          `json:"hostname"`
	ID             string          `json:"id"`
	Links          []Link          `json:"links"`
	Name           string          `json:"name"`
	Port           int             `json:"port"`
	SecurityGroups []SecurityGroup `json:"security_groups"`
	Status         string          `json:"status"`
	Updated        string          `json:"updated"`
	Flavor         struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

/*
 Type describing database flavor
*/
type DBFlavor struct {
	Id    int    `json:"id"`
	Links []Link `json:"links"`
	Name  string `json:"name"`
	Ram   int    `json:"ram"`
	Vcpu  int    `json:"vcpu"`
}

/*
 This type describes the JSON data which should be sent to the
create database instance resource.
*/
type DatabaseReq struct {
	Instance Database `json:"instance"`
}

/*
 This type describes JSON response from a successful CreateDBInstance
 call.
*/
type NewDBInstance struct {
	Created    string        `json:"created"`
	Credential DBCredentials `json:"credential"`
	Flavor     struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
	Hostname       string        `json:"hostname"`
	Id             string        `json:"id"`
	Links          []Link        `json:"links"`
	Name           string        `json:"name"`
	SecurityGroups []DBSecGroups `json:"security_groups"`
	Status         string        `json:"status"`
}

/*
 This type describes Database Security groups
*/
type DBSecGroups struct {
	Id    string `json:"id"`
	Links []Link `json:"links"`
}

/*
 This type describes Database Credentials
*/
type DBCredentials struct {
	Password string `json:"password"`
	Username string `json:"username"`
}

func (f DBFlavors) GetFlavorRef(fn string) string {
	for _, val := range f.Flavors {
		if val.Name == fn {
			return val.Links[0].HREF
		}
	}
	panic("Flavor not found")
}

func (db DatabaseReq) MarshalJSON() ([]byte, error) {
	b := bytes.NewBufferString(`{"instance":{`)
	if db.Instance.Name == "" {
		return nil, errors.New("A name is required")
	}
	b.WriteString(fmt.Sprintf(`"name":"%s",`, db.Instance.Name))
	if db.Instance.FlavorRef == "" {
		return nil, errors.New("Flavor is required")
	}
	b.WriteString(fmt.Sprintf(`"flavorRef":"%s",`,
		db.Instance.FlavorRef))
	if db.Instance.Port == 0 {
		b.WriteString(`"port":"3306",`)
	} else {
		b.WriteString(fmt.Sprintf(`"port":"%s",`, db.Instance.Port))
	}
	b.WriteString(`"dbtype":{`)
	b.WriteString(`"name":"mysql",`)
	b.WriteString(`"version":"5.5"}}}`)

	return b.Bytes(), nil
}
<|endoftext|>


<commit_before>package utils

import "github.com/Shopify/go-lua"

type Fm map[string]lua.Function

func TableWith(l *lua.State, fs ...Fm) int {
	l.CreateTable(0, len(fs))
	idx := l.Top()
	for _, x := range fs {
		for k := range x {
			l.PushGoFunction(x[k])
			l.SetField(idx, k)
		}
	}
	return 1
}
<commit_msg>More docs<commit_after>package utils

import "github.com/Shopify/go-lua"

// Fm is used as a blueprint for a Lua table,
// containing functions identified by strings.
type Fm map[string]lua.Function

// TableWith translates the given blueprint to
// a table, pushed to the top of the stack.
func TableWith(l *lua.State, fs ...Fm) int {
	l.CreateTable(0, len(fs))
	idx := l.Top()
	for _, x := range fs {
		for k := range x {
			l.PushGoFunction(x[k])
			l.SetField(idx, k)
		}
	}
	return 1
}
<|endoftext|>


<commit_before>// Package red implements server speaking redis serialization protocol.
package red

import (
	"bufio"
	"errors"
	"io"
	"net"
	"strings"
	"time"

	"github.com/artyom/resp"
)

// HandlerFunc is a type of command processing function. It should return value
// that's passed to resp.Encode function, so it's expected such function would
// return values of resp package types.
type HandlerFunc func(req Request) (interface{}, error)

// Request holds information about single redis command.
type Request struct {
	Name string   // lowercase command itself (first word)
	Args []string // command arguments
}

// NewServer returns initialized server.
func NewServer() *Server {
	return &Server{log: noopLogger{}}
}

// WithLogger configures server to use provided Logger.
func (s *Server) WithLogger(l Logger) {
	if l != nil {
		s.log = l
	}
}

// Handle registers handler for command with given name (case-insensitive)
func (s *Server) Handle(name string, h HandlerFunc) {
	if name == "" {
		panic("Handle called with empty name")
	}
	if h == nil {
		panic("Handle called with nil HandlerFunc")
	}
	if s.handlers == nil {
		s.handlers = make(map[string]HandlerFunc)
	}
	s.handlers[strings.ToLower(name)] = h
}

// Server implements server speaking RESP (REdis Serialization Protocol). Server
// automatically handles MULTI & EXEC commands for transactions, QUIT for
// client-initiated disconnect, other commands are expected to be implemented
// separately and registered with Handle method.
type Server struct {
	log      Logger
	handlers map[string]HandlerFunc
}

// HandleConn processes single client connection, automatically handling
// following commands MULTI/EXEC (transactions), QUIT (client disconnect). It
// calls user-provided handlers for registered commands.
func (s *Server) HandleConn(conn io.ReadWriteCloser) error {
	defer conn.Close()
	rd := bufio.NewReader(conn)
	var tx []Request
	var inTx bool  // if we're inside transaction
	var errTx bool // true if transaction seen error and should be discarded
	var err error
	for {
		if err != nil {
			return err
		}
		req, err := resp.DecodeRequest(rd)
		switch err {
		case nil:
		case resp.ErrInvalidRequest:
			err = resp.Encode(conn, resp.Error("ERR unknown command"))
			continue
		default:
			return err
		}
		cmd := strings.ToLower(req[0])
		s.log.Println("REQ:", req)
		switch cmd {
		case "quit":
			return nil
		case "multi":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if inTx {
				errTx = true
				err = resp.Encode(conn, resp.Error("ERR MULTI calls can not be nested"))
				continue
			}
			inTx, errTx = true, false
			err = resp.Encode(conn, resp.OK{})
			continue
		case "exec":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if !inTx {
				err = resp.Encode(conn, resp.Error("ERR EXEC without MULTI"))
				continue
			}
			if errTx {
				inTx, errTx = false, false
				tx = tx[:0]
				err = resp.Encode(conn, resp.Error("EXECABORT Transaction discarded because of previous errors."))
				continue
			}
		default:
			h, ok := s.handlers[cmd]
			if !ok {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errNoCmd(cmd))
				continue
			}
			if inTx {
				if !errTx {
					tx = append(tx, Request{Name: cmd, Args: req[1:]})
				}
				err = resp.Encode(conn, resp.SimpleString("QUEUED"))
				continue
			}
			err = resp.Encode(conn, singleVal(h, Request{Name: cmd, Args: req[1:]}))
			continue
		}

		txReplies := make(resp.Array, 0, len(tx))
		for _, r := range tx {
			h, ok := s.handlers[r.Name]
			if !ok {
				txReplies = append(txReplies, errNoCmd(r.Name))
				continue
			}
			txReplies = append(txReplies, singleVal(h, r))
		}
		inTx, errTx = false, false
		tx = tx[:0]
		err = resp.Encode(conn, txReplies)
	}
}

// ListenAndServe listens on TCP network address addr and then calls Serve to
// handle requests on incoming connections.
func (s *Server) ListenAndServe(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return s.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

// Serve accepts incoming connections on the Listener l, creating a new service
// goroutine for each.
func (s *Server) Serve(l net.Listener) error {
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		go func(c net.Conn) {
			switch err := s.HandleConn(c); err {
			case nil, io.EOF:
			default:
				if s.log != nil {
					s.log.Println(err)
				}
			}
		}(conn)
	}
}

// Logger is a set of methods used to log information. *log.Logger implements
// this interface.
type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

type noopLogger struct{}

func (noopLogger) Print(v ...interface{})                 {}
func (noopLogger) Printf(format string, v ...interface{}) {}
func (noopLogger) Println(v ...interface{})               {}

func errNoCmd(name string) resp.Error { return resp.Error("ERR unknown command '" + name + "'") }

// ErrWrongArgs are expected to be returned by HandlerFunc implementations when
// number of arguments are wrong. This error automatically to client with
// command name annotated.
var ErrWrongArgs = errors.New("wrong number of arguments")

func errWrongArgs(name string) resp.Error {
	return resp.Error("ERR wrong number of arguments for '" + name + "' command")
}

// silgleVal calls HandlerFunc h with given Request r and returns single value
// that is expected to be passed to resp.Encode.
//
// If h returns a non-nil error, then singleVal returns resp.Error type,
// otherwise it's an interface{} returned by h.
func singleVal(h HandlerFunc, r Request) interface{} {
	v, err := h(r)
	if err != nil {
		if err == ErrWrongArgs {
			return errWrongArgs(r.Name)
		}
		text := err.Error()
		if strings.ContainsAny(text, "\r\n") {
			text = strings.Replace(text, "\r", " ", -1)
			text = strings.Replace(text, "\n", " ", -1)
		}
		return resp.Error("ERR " + text)
	}
	return v
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}
<commit_msg>Fix ErrWrongArgs docs<commit_after>// Package red implements server speaking redis serialization protocol.
package red

import (
	"bufio"
	"errors"
	"io"
	"net"
	"strings"
	"time"

	"github.com/artyom/resp"
)

// HandlerFunc is a type of command processing function. It should return value
// that's passed to resp.Encode function, so it's expected such function would
// return values of resp package types.
type HandlerFunc func(req Request) (interface{}, error)

// Request holds information about single redis command.
type Request struct {
	Name string   // lowercase command itself (first word)
	Args []string // command arguments
}

// NewServer returns initialized server.
func NewServer() *Server {
	return &Server{log: noopLogger{}}
}

// WithLogger configures server to use provided Logger.
func (s *Server) WithLogger(l Logger) {
	if l != nil {
		s.log = l
	}
}

// Handle registers handler for command with given name (case-insensitive)
func (s *Server) Handle(name string, h HandlerFunc) {
	if name == "" {
		panic("Handle called with empty name")
	}
	if h == nil {
		panic("Handle called with nil HandlerFunc")
	}
	if s.handlers == nil {
		s.handlers = make(map[string]HandlerFunc)
	}
	s.handlers[strings.ToLower(name)] = h
}

// Server implements server speaking RESP (REdis Serialization Protocol). Server
// automatically handles MULTI & EXEC commands for transactions, QUIT for
// client-initiated disconnect, other commands are expected to be implemented
// separately and registered with Handle method.
type Server struct {
	log      Logger
	handlers map[string]HandlerFunc
}

// HandleConn processes single client connection, automatically handling
// following commands MULTI/EXEC (transactions), QUIT (client disconnect). It
// calls user-provided handlers for registered commands.
func (s *Server) HandleConn(conn io.ReadWriteCloser) error {
	defer conn.Close()
	rd := bufio.NewReader(conn)
	var tx []Request
	var inTx bool  // if we're inside transaction
	var errTx bool // true if transaction seen error and should be discarded
	var err error
	for {
		if err != nil {
			return err
		}
		req, err := resp.DecodeRequest(rd)
		switch err {
		case nil:
		case resp.ErrInvalidRequest:
			err = resp.Encode(conn, resp.Error("ERR unknown command"))
			continue
		default:
			return err
		}
		cmd := strings.ToLower(req[0])
		s.log.Println("REQ:", req)
		switch cmd {
		case "quit":
			return nil
		case "multi":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if inTx {
				errTx = true
				err = resp.Encode(conn, resp.Error("ERR MULTI calls can not be nested"))
				continue
			}
			inTx, errTx = true, false
			err = resp.Encode(conn, resp.OK{})
			continue
		case "exec":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if !inTx {
				err = resp.Encode(conn, resp.Error("ERR EXEC without MULTI"))
				continue
			}
			if errTx {
				inTx, errTx = false, false
				tx = tx[:0]
				err = resp.Encode(conn, resp.Error("EXECABORT Transaction discarded because of previous errors."))
				continue
			}
		default:
			h, ok := s.handlers[cmd]
			if !ok {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errNoCmd(cmd))
				continue
			}
			if inTx {
				if !errTx {
					tx = append(tx, Request{Name: cmd, Args: req[1:]})
				}
				err = resp.Encode(conn, resp.SimpleString("QUEUED"))
				continue
			}
			err = resp.Encode(conn, singleVal(h, Request{Name: cmd, Args: req[1:]}))
			continue
		}

		txReplies := make(resp.Array, 0, len(tx))
		for _, r := range tx {
			h, ok := s.handlers[r.Name]
			if !ok {
				txReplies = append(txReplies, errNoCmd(r.Name))
				continue
			}
			txReplies = append(txReplies, singleVal(h, r))
		}
		inTx, errTx = false, false
		tx = tx[:0]
		err = resp.Encode(conn, txReplies)
	}
}

// ListenAndServe listens on TCP network address addr and then calls Serve to
// handle requests on incoming connections.
func (s *Server) ListenAndServe(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return s.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

// Serve accepts incoming connections on the Listener l, creating a new service
// goroutine for each.
func (s *Server) Serve(l net.Listener) error {
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		go func(c net.Conn) {
			switch err := s.HandleConn(c); err {
			case nil, io.EOF:
			default:
				if s.log != nil {
					s.log.Println(err)
				}
			}
		}(conn)
	}
}

// Logger is a set of methods used to log information. *log.Logger implements
// this interface.
type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

type noopLogger struct{}

func (noopLogger) Print(v ...interface{})                 {}
func (noopLogger) Printf(format string, v ...interface{}) {}
func (noopLogger) Println(v ...interface{})               {}

func errNoCmd(name string) resp.Error { return resp.Error("ERR unknown command '" + name + "'") }

// ErrWrongArgs are expected to be returned by HandlerFunc implementations when
// number of arguments are wrong. This error is automatically passed to client
// with command name annotated.
var ErrWrongArgs = errors.New("wrong number of arguments")

func errWrongArgs(name string) resp.Error {
	return resp.Error("ERR wrong number of arguments for '" + name + "' command")
}

// silgleVal calls HandlerFunc h with given Request r and returns single value
// that is expected to be passed to resp.Encode.
//
// If h returns a non-nil error, then singleVal returns resp.Error type,
// otherwise it's an interface{} returned by h.
func singleVal(h HandlerFunc, r Request) interface{} {
	v, err := h(r)
	if err != nil {
		if err == ErrWrongArgs {
			return errWrongArgs(r.Name)
		}
		text := err.Error()
		if strings.ContainsAny(text, "\r\n") {
			text = strings.Replace(text, "\r", " ", -1)
			text = strings.Replace(text, "\n", " ", -1)
		}
		return resp.Error("ERR " + text)
	}
	return v
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}
<|endoftext|>


<commit_before>package excl

import (
	"encoding/xml"
	"fmt"
	"math"
	"strconv"
)

// Row 行の構造体
type Row struct {
	rowID         int
	row           *Tag
	cells         []*Cell
	sharedStrings *SharedStrings
	colsStyles    []ColsStyle
	style         string
	minColNo      int
	maxColNo      int
	styles        *Styles
}

// NewRow は新しく行を追加する際に使用する
func NewRow(tag *Tag, sharedStrings *SharedStrings, styles *Styles) *Row {
	row := &Row{row: tag, sharedStrings: sharedStrings, styles: styles}
	for _, attr := range tag.Attr {
		if attr.Name.Local == "r" {
			row.rowID, _ = strconv.Atoi(attr.Value)
		} else if attr.Name.Local == "s" {
			row.style = attr.Value
		}
	}
	for _, child := range tag.Children {
		switch col := child.(type) {
		case *Tag:
			if col.Name.Local == "c" {
				cell := NewCell(col, sharedStrings, styles)
				if cell == nil {
					return nil
				}
				cell.styles = row.styles
				row.cells = append(row.cells, cell)
				row.maxColNo = cell.colNo
				if row.minColNo == 0 {
					row.minColNo = cell.colNo
				}
			}
		}
	}
	return row
}

// CreateCells セル一覧を用意する
func (row *Row) CreateCells(from int, to int) []*Cell {
	if row.maxColNo < to {
		row.maxColNo = to
	}
	cells := make([]*Cell, row.maxColNo)
	for _, cell := range row.cells {
		if cell == nil || cell.colNo == 0 {
			break
		}
		cells[cell.colNo-1] = cell
	}
	for i := from; i <= to; i++ {
		if cells[i-1] != nil {
			continue
		}
		attr := []xml.Attr{
			xml.Attr{
				Name:  xml.Name{Local: "r"},
				Value: fmt.Sprintf("%s%d", ColStringPosition(i), row.rowID),
			},
		}
		tag := &Tag{
			Name: xml.Name{Local: "c"},
			Attr: attr,
		}
		style := 0
		if row.style != "" {
			style, _ = strconv.Atoi(row.style)
		} else {
			for _, colStyle := range row.colsStyles {
				if i <= colStyle.min && colStyle.max <= i {
					style, _ = strconv.Atoi(colStyle.style)
					break
				}
			}
		}
		cells[i-1] = &Cell{cell: tag, colNo: i, sharedStrings: row.sharedStrings, styleIndex: style}
	}
	row.cells = cells
	return row.cells
}

// GetCell セル番号のセルを取得する
func (row *Row) GetCell(colNo int) *Cell {
	var afterTag *Tag
	for _, cell := range row.cells {
		if cell.colNo == colNo {
			return cell
		}
		if cell.colNo > colNo {
			afterTag = cell.cell
			break
		}
	}

	// 存在しない場合はセルを追加する
	tag := &Tag{Name: xml.Name{Local: "c"}}
	tag.setAttr("r", fmt.Sprintf("%s%d", ColStringPosition(int(colNo)), row.rowID))
	if row.style != "" {
		tag.setAttr("s", row.style)
	} else if style := getStyleNo(row.colsStyles, int(colNo)); style != "" {
		tag.setAttr("s", style)
	}
	if afterTag == nil {
		row.row.Children = append(row.row.Children, tag)
	} else {
		added := false
		children := make([]interface{}, len(row.row.Children)+1)
		for index, child := range row.row.Children {
			if afterTag == child {
				children[index] = tag
				children[index+1] = child
				added = true
			} else if added {
				children[index+1] = child
			} else {
				children[index] = child
			}
		}
		row.row.Children = children
	}
	cell := NewCell(tag, row.sharedStrings, row.styles)
	cells := make([]*Cell, len(row.cells)+1)
	added := false
	for index, c := range row.cells {
		if c.colNo < colNo {
			cells[index] = c
		} else if c.colNo > colNo {
			if !added {
				cells[index] = cell
				added = true
			}
			cells[index+1] = c
		}
	}
	if !added {
		cells[len(row.cells)] = cell
	}
	row.cells = cells
	return cell
}

// SetString 文字を出力する
func (row *Row) SetString(val string, colNo int) *Cell {
	cell := row.GetCell(colNo).SetString(val)
	return cell
}

// SetNumber 数値を出力する
func (row *Row) SetNumber(val string, colNo int) *Cell {
	cell := row.GetCell(colNo).SetNumber(val)
	return cell
}

// ColStringPosition カラム番号からA-Z文字列を取得する
func ColStringPosition(num int) string {
	atoz := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	if num <= 26 {
		return atoz[num-1]
	}
	return ColStringPosition(num/26) + atoz[num%26]
}

// ColNumPosition カラム番号をA-Z文字列から取得する
func ColNumPosition(col string) int {
	var num int
	for i := len(col) - 1; i >= 0; i-- {
		p := math.Pow(26, float64(len(col)-i-1))
		num += int(p) * int(col[i]-0x40)
	}
	return num
}

// MarshalXML タグを作成しなおす
func (row *Row) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start.Name = row.row.Name
	start.Attr = row.row.Attr
	e.EncodeToken(start)
	for _, c := range row.cells {
		if err := e.Encode(c.cell); err != nil {
			return err
		}
	}
	e.EncodeToken(start.End())
	return nil
}

func (row *Row) resetStyleIndex() {
	for _, cell := range row.cells {
		cell.resetStyleIndex()
	}
}
<commit_msg>Fixrowstyle (#12)<commit_after>package excl

import (
	"encoding/xml"
	"fmt"
	"math"
	"sort"
	"strconv"
)

// Row 行の構造体
type Row struct {
	rowID         int
	row           *Tag
	cells         []*Cell
	sharedStrings *SharedStrings
	colsStyles    []ColsStyle
	style         string
	minColNo      int
	maxColNo      int
	styles        *Styles
}

// NewRow は新しく行を追加する際に使用する
func NewRow(tag *Tag, sharedStrings *SharedStrings, styles *Styles) *Row {
	row := &Row{row: tag, sharedStrings: sharedStrings, styles: styles}
	for _, attr := range tag.Attr {
		if attr.Name.Local == "r" {
			row.rowID, _ = strconv.Atoi(attr.Value)
		} else if attr.Name.Local == "s" {
			row.style = attr.Value
		}
	}
	for _, child := range tag.Children {
		switch col := child.(type) {
		case *Tag:
			if col.Name.Local == "c" {
				cell := NewCell(col, sharedStrings, styles)
				if cell == nil {
					return nil
				}
				cell.styles = row.styles
				row.cells = append(row.cells, cell)
				row.maxColNo = cell.colNo
				if row.minColNo == 0 {
					row.minColNo = cell.colNo
				}
			}
		}
	}
	return row
}

// CreateCells セル一覧を用意する
func (row *Row) CreateCells(from int, to int) []*Cell {
	if row.maxColNo < to {
		row.maxColNo = to
	}
	cells := make([]*Cell, row.maxColNo)
	for _, cell := range row.cells {
		if cell == nil || cell.colNo == 0 {
			continue
		}
		cells[cell.colNo-1] = cell
	}
	for i := from; i <= to; i++ {
		if cells[i-1] != nil {
			continue
		}
		attr := []xml.Attr{
			xml.Attr{
				Name:  xml.Name{Local: "r"},
				Value: fmt.Sprintf("%s%d", ColStringPosition(i), row.rowID),
			},
		}
		tag := &Tag{
			Name: xml.Name{Local: "c"},
			Attr: attr,
		}
		style := 0
		if row.style != "" {
			style, _ = strconv.Atoi(row.style)
		} else {
			for _, colStyle := range row.colsStyles {
				if colStyle.min <= i && i <= colStyle.max {
					style, _ = strconv.Atoi(colStyle.style)
					break
				}
			}
		}
		cells[i-1] = &Cell{cell: tag, colNo: i, sharedStrings: row.sharedStrings, styleIndex: style}
	}
	row.cells = cells
	return row.cells
}

// ByCell セルに対するソート用
type ByCell []*Cell

func (c ByCell) Len() int           { return len(c) }
func (c ByCell) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
func (c ByCell) Less(i, j int) bool { return c[i].colNo < c[j].colNo }

// GetCell セル番号のセルを取得する
func (row *Row) GetCell(colNo int) *Cell {

	for _, cell := range row.cells {
		if cell.colNo == colNo {
			return cell
		}
		if cell.colNo > colNo {
			break
		}
	}

	// 存在しない場合はセルを追加する
	tag := &Tag{Name: xml.Name{Local: "c"}}
	tag.setAttr("r", fmt.Sprintf("%s%d", ColStringPosition(int(colNo)), row.rowID))
	if row.style != "" {
		tag.setAttr("s", row.style)
	} else if style := getStyleNo(row.colsStyles, int(colNo)); style != "" {
		tag.setAttr("s", style)
	}

	cell := NewCell(tag, row.sharedStrings, row.styles)
	row.cells = append(row.cells, cell)
	sort.Sort(ByCell(row.cells))
	return cell
}

// SetString 文字を出力する
func (row *Row) SetString(val string, colNo int) *Cell {
	cell := row.GetCell(colNo).SetString(val)
	return cell
}

// SetNumber 数値を出力する
func (row *Row) SetNumber(val string, colNo int) *Cell {
	cell := row.GetCell(colNo).SetNumber(val)
	return cell
}

// ColStringPosition カラム番号からA-Z文字列を取得する
func ColStringPosition(num int) string {
	atoz := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	if num <= 26 {
		return atoz[num-1]
	}
	return ColStringPosition(num/26) + atoz[(num-1)%26]
}

// ColNumPosition カラム番号をA-Z文字列から取得する
func ColNumPosition(col string) int {
	var num int
	for i := len(col) - 1; i >= 0; i-- {
		p := math.Pow(26, float64(len(col)-i-1))
		num += int(p) * int(col[i]-0x40)
	}
	return num
}

// MarshalXML タグを作成しなおす
func (row *Row) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start.Name = row.row.Name
	start.Attr = row.row.Attr
	e.EncodeToken(start)
	for _, c := range row.cells {
		if err := e.Encode(c.cell); err != nil {
			return err
		}
	}
	e.EncodeToken(start.End())
	return nil
}

func (row *Row) resetStyleIndex() {
	for _, cell := range row.cells {
		cell.resetStyleIndex()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"io"
	"log"
	"net/url"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"

	"github.com/remind101/emp/Godeps/_workspace/src/github.com/bgentry/heroku-go"
	"github.com/remind101/emp/term"
)

var (
	detachedRun bool
	dynoSize    string
)

var cmdRun = &Command{
	Run:      runRun,
	Usage:    "run [-s <size>] [-d] <command> [<argument>...]",
	NeedsApp: true,
	Category: "dyno",
	Short:    "run a process in a dyno",
	Long: `
Run a process on Heroku. Flags such as` + " `-a` " + `may be parsed out of
the command unless the command is quoted or provided after a
double-dash (--).

Options:

    -s <size>  set the size for this dyno (e.g. 2X)
    -d         run in detached mode instead of attached to terminal

Examples:

    $ emp run echo "hello"
    Running ` + "`echo \"hello\"`" + ` on myapp as run.1234:
    "hello"

    $ emp run console
    Running ` + "`console`" + ` on myapp as run.5678:
    Loading production environment (Rails 3.2.14)
    irb(main):001:0> ...

    $ emp run -d -s 2X bin/my_worker
    Ran ` + "`bin/my_worker`" + ` on myapp as run.4321, detached.

    $ emp run -a myapp -- ls -a /
    Running ` + "`ls -a bin /`" + ` on myapp as run.8650:
    /:
    .  ..  app  bin  dev  etc  home  lib  lib64  lost+found  proc  sbin  tmp  usr  var
`,
}

func init() {
	cmdRun.Flag.BoolVarP(&detachedRun, "detached", "d", false, "detached")
	cmdRun.Flag.StringVarP(&dynoSize, "size", "s", "", "dyno size")
}

func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	dyno, err := client.DynoCreate(appname, command, &opts)
	must(err)

	if detachedRun {
		log.Printf("Ran `%s` on %s as %s, detached.", dyno.Command, appname, dyno.Name)
		return
	}
	log.Printf("Running `%s` on %s as %s:", dyno.Command, appname, dyno.Name)

	u, err := url.Parse(*dyno.AttachURL)
	if err != nil {
		printFatal(err.Error())
	}

	cn, err := tls.Dial("tcp", u.Host, nil)
	if err != nil {
		printFatal(err.Error())
	}
	defer cn.Close()

	br := bufio.NewReader(cn)

	_, err = io.WriteString(cn, u.Path[1:]+"\r\n")
	if err != nil {
		printFatal(err.Error())
	}

	for {
		_, pre, err := br.ReadLine()
		if err != nil {
			printFatal(err.Error())
		}
		if !pre {
			break
		}
	}

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			printFatal(err.Error())
		}
		defer term.Restore(os.Stdin)

		sig := make(chan os.Signal)
		signal.Notify(sig, os.Signal(syscall.SIGQUIT), os.Interrupt)
		go func() {
			defer term.Restore(os.Stdin)
			for sg := range sig {
				switch sg {
				case os.Interrupt:
					cn.Write([]byte{3})
				case os.Signal(syscall.SIGQUIT):
					cn.Write([]byte{28})
				default:
					panic("not reached")
				}
			}
		}()
	}

	errc := make(chan error)
	cp := func(a io.Writer, b io.Reader) {
		_, err := io.Copy(a, b)
		errc <- err
	}

	go cp(os.Stdout, br)
	go cp(cn, os.Stdin)
	if err = <-errc; err != nil {
		printFatal(err.Error())
	}
}
<commit_msg>Hijack connection for run.<commit_after>package main

import (
	"io"
	"net"
	"net/http/httputil"
	"os"
	"strconv"
	"strings"

	"github.com/remind101/emp/Godeps/_workspace/src/github.com/bgentry/heroku-go"
	"github.com/remind101/emp/term"
)

var (
	detachedRun bool
	dynoSize    string
)

var cmdRun = &Command{
	Run:      runRun,
	Usage:    "run [-s <size>] [-d] <command> [<argument>...]",
	NeedsApp: true,
	Category: "dyno",
	Short:    "run a process in a dyno",
	Long: `
Run a process on Heroku. Flags such as` + " `-a` " + `may be parsed out of
the command unless the command is quoted or provided after a
double-dash (--).

Options:

    -s <size>  set the size for this dyno (e.g. 2X)
    -d         run in detached mode instead of attached to terminal

Examples:

    $ emp run echo "hello"
    Running ` + "`echo \"hello\"`" + ` on myapp as run.1234:
    "hello"

    $ emp run console
    Running ` + "`console`" + ` on myapp as run.5678:
    Loading production environment (Rails 3.2.14)
    irb(main):001:0> ...

    $ emp run -d -s 2X bin/my_worker
    Ran ` + "`bin/my_worker`" + ` on myapp as run.4321, detached.

    $ emp run -a myapp -- ls -a /
    Running ` + "`ls -a bin /`" + ` on myapp as run.8650:
    /:
    .  ..  app  bin  dev  etc  home  lib  lib64  lost+found  proc  sbin  tmp  usr  var
`,
}

func init() {
	cmdRun.Flag.BoolVarP(&detachedRun, "detached", "d", false, "detached")
	cmdRun.Flag.StringVarP(&dynoSize, "size", "s", "", "dyno size")
}

func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	params := struct {
		Command string             `json:"command"`
		Attach  *bool              `json:"attach,omitempty"`
		Env     *map[string]string `json:"env,omitempty"`
		Size    *string            `json:"size,omitempty"`
	}{
		Command: command,
		Attach:  opts.Attach,
		Env:     opts.Env,
		Size:    opts.Size,
	}
	req, err := client.NewRequest("POST", "/apps/"+appname+"/dynos", params)
	must(err)

	dial, err := net.Dial("tcp", "192.168.59.103:8080")
	must(err)

	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()
	clientconn.Do(req)
	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	errChanOut := make(chan error, 1)
	errChanIn := make(chan error, 1)
	exit := make(chan bool)
	go func() {
		defer close(exit)
		defer close(errChanOut)
		var err error
		_, err = io.Copy(os.Stdout, br)
		errChanOut <- err
	}()
	go func() {
		_, err := io.Copy(rwc, os.Stdin)
		errChanIn <- err
		rwc.(interface {
			CloseWrite() error
		}).CloseWrite()
	}()
	<-exit
	select {
	case err = <-errChanIn:
		must(err)
	case err = <-errChanOut:
		must(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	docker "github.com/fsouza/go-dockerclient"
)

type Run struct {
	Id         string
	VolumePath string
	Config     *Config
	Container  *docker.Container
	Client     *docker.Client
	Request    *Request
	Done       chan bool
}

type RunResult struct {
	ExitCode int    `json:"exit_code"`
	Output   []byte `json:"output"`
	Duration string `json:"-"`
}

type Done struct {
	*RunResult
	error
}

func NewRun(config *Config, client *docker.Client, req *Request) *Run {
	id, _ := randomHex(20)

	return &Run{
		Id:         id,
		Config:     config,
		Client:     client,
		VolumePath: fmt.Sprintf("%s/%s", config.SharedPath, id),
		Request:    req,
		Done:       make(chan bool),
	}
}

func (run *Run) Setup() error {
	fullPath := fmt.Sprintf("%s/%s", run.VolumePath, run.Request.Filename)

	if err := os.Mkdir(run.VolumePath, 0777); err != nil {
		return err
	}

	if err := ioutil.WriteFile(fullPath, []byte(run.Request.Content), 0666); err != nil {
		return err
	}

	memLimit := run.Request.MemoryLimit
	if memLimit <= 1024 || memLimit > run.Config.MemoryLimit {
		memLimit = run.Config.MemoryLimit
	}

	opts := docker.CreateContainerOptions{
		HostConfig: &docker.HostConfig{
			Binds: []string{
				run.VolumePath + ":/code",
				run.VolumePath + ":/tmp",
			},
			ReadonlyRootfs: true,
			Memory:         run.Config.MemoryLimit,
			MemorySwap:     0,
		},
		Config: &docker.Config{
			Hostname:        "bitrun",
			Image:           run.Request.Image,
			AttachStdout:    true,
			AttachStderr:    true,
			AttachStdin:     false,
			OpenStdin:       false,
			Tty:             true,
			NetworkDisabled: run.Config.NetworkDisabled,
			WorkingDir:      "/code",
			Cmd:             []string{"bash", "-c", run.Request.Command},
		},
	}

	container, err := run.Client.CreateContainer(opts)
	if err != nil {
		return err
	}

	run.Container = container
	return nil
}

func (run *Run) Start() (*RunResult, error) {
	ts := time.Now()

	err := run.Client.StartContainer(run.Container.ID, run.Container.HostConfig)
	if err != nil {
		return nil, err
	}

	result := RunResult{}

	exitCode, err := run.Client.WaitContainer(run.Container.ID)
	if err != nil {
		return nil, err
	}

	result.Duration = time.Now().Sub(ts).String()
	result.ExitCode = exitCode

	buff := bytes.NewBuffer([]byte{})

	err = run.Client.Logs(docker.LogsOptions{
		Container:    run.Container.ID,
		Stdout:       true,
		Stderr:       true,
		OutputStream: buff,
		ErrorStream:  buff,
		RawTerminal:  true,
	})

	if err != nil {
		return nil, err
	}

	result.Output = buff.Bytes()
	return &result, nil
}

func (run *Run) StartWithTimeout(duration time.Duration) (*RunResult, error) {
	timeout := time.After(duration)
	chDone := make(chan Done)

	go func() {
		res, err := run.Start()
		chDone <- Done{res, err}
	}()

	select {
	case done := <-chDone:
		return done.RunResult, done.error
	case <-timeout:
		return nil, fmt.Errorf("Operation timed out after %s", duration.String())
	}
}

func (run *Run) Destroy() error {
	if run.Container != nil {
		destroyContainer(run.Client, run.Container.ID)
	}

	return os.RemoveAll(run.VolumePath)
}

func destroyContainer(client *docker.Client, id string) error {
	return client.RemoveContainer(docker.RemoveContainerOptions{
		ID:            id,
		RemoveVolumes: true,
		Force:         true,
	})
}
<commit_msg>Replace standard runs with exec-based runs<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"time"

	docker "github.com/fsouza/go-dockerclient"
)

type Run struct {
	Id         string
	VolumePath string
	Config     *Config
	Container  *docker.Container
	Client     *docker.Client
	Request    *Request
	Done       chan bool
}

type RunResult struct {
	ExitCode int    `json:"exit_code"`
	Output   []byte `json:"output"`
	Duration string `json:"-"`
}

type Done struct {
	*RunResult
	error
}

func NewRun(config *Config, client *docker.Client, req *Request) *Run {
	id, _ := randomHex(20)

	return &Run{
		Id:         id,
		Config:     config,
		Client:     client,
		VolumePath: fmt.Sprintf("%s/%s", config.SharedPath, id),
		Request:    req,
		Done:       make(chan bool),
	}
}

func (run *Run) Setup() error {
	container, err := CreateContainer(run.Client, run.Config, run.Request.Image, 60)
	if err != nil {
		return err
	}

	volumePath := fmt.Sprintf("%s/%s", run.Config.SharedPath, container.Config.Labels["id"])
	fullPath := fmt.Sprintf("%s/%s", volumePath, run.Request.Filename)

	if err := ioutil.WriteFile(fullPath, []byte(run.Request.Content), 0666); err != nil {
		return err
	}

	run.Container = container

	if err := run.Client.StartContainer(container.ID, nil); err != nil {
		return err
	}

	return nil
}

func (run *Run) Start() (*RunResult, error) {
	return run.StartExec(run.Container)
}

func (run *Run) StartWithTimeout(duration time.Duration) (*RunResult, error) {
	timeout := time.After(duration)
	chDone := make(chan Done)

	go func() {
		res, err := run.Start()
		chDone <- Done{res, err}
	}()

	select {
	case done := <-chDone:
		return done.RunResult, done.error
	case <-timeout:
		return nil, fmt.Errorf("Operation timed out after %s", duration.String())
	}
}

func (run *Run) Destroy() error {
	if run.Container != nil {
		destroyContainer(run.Client, run.Container.ID)
	}

	return os.RemoveAll(run.VolumePath)
}

func destroyContainer(client *docker.Client, id string) error {
	return client.RemoveContainer(docker.RemoveContainerOptions{
		ID:            id,
		RemoveVolumes: true,
		Force:         true,
	})
}
<|endoftext|>


<commit_before>package httppool

import (
	"errors"
	"fmt"
	"github.com/Comcast/webpa-common/logging"
	"github.com/stretchr/testify/assert"
	"net/http"
	"os"
	"sync"
	"testing"
	"time"
)

const (
	requestCount = 100
)

var (
	taskError        = errors.New("Task error")
	transactionError = errors.New("Transaction error")
)

func TestClientDefaults(t *testing.T) {
	assert := assert.New(t)

	// all these clients should use default values
	var testData = []Client{
		Client{},
		Client{
			QueueSize: -1,
			Workers:   -1,
		},
		Client{
			QueueSize: -34582,
			Workers:   -4582,
			Period:    400 * time.Second,
		},
	}

	for _, client := range testData {
		t.Logf("client: %#v", client)
		assert.Equal(http.DefaultClient, client.handler())
		assert.Equal(DefaultQueueSize, client.queueSize())
		assert.Equal(DefaultWorkers, client.workers())

		_, ok := client.logger().(*logging.LoggerWriter)
		assert.True(ok)
	}
}

func TestClientNonDefaults(t *testing.T) {
	assert := assert.New(t)

	expectedHandler := &http.Client{}
	expectedLogger := &logging.LoggerWriter{os.Stderr}

	// all these clients should use real values, not the defaults
	var testData = []Client{
		Client{
			Handler:   expectedHandler,
			Logger:    expectedLogger,
			Workers:   1234,
			QueueSize: 7983481,
		},
		Client{
			Handler:   expectedHandler,
			Logger:    expectedLogger,
			Workers:   2956,
			QueueSize: 275,
			Period:    1000 * time.Hour,
		},
	}

	for _, client := range testData {
		t.Logf("client: %#v", client)
		assert.Equal(expectedHandler, client.handler())
		assert.Equal(expectedLogger, client.logger())
		assert.Equal(client.QueueSize, client.queueSize())
		assert.Equal(client.Workers, client.workers())
	}
}

func TestClientDispatcher(t *testing.T) {
	assert := assert.New(t)

	var testData = []Client{
		Client{},
		Client{
			Workers:   1,
			QueueSize: 5,
		},
		Client{
			Period: 100 * time.Millisecond,
		},
		Client{
			Workers:   12,
			QueueSize: 200,
			Period:    100 * time.Millisecond,
		},
	}

	for _, client := range testData {
		taskWaitGroup := &sync.WaitGroup{}
		taskWaitGroup.Add(requestCount)

		handler := &mockTransactionHandler{}
		client.Handler = handler

		tasks := make([]Task, 0, requestCount)

		for requestNumber := 0; requestNumber < requestCount; requestNumber++ {
			request, err := http.NewRequest("GET", fmt.Sprintf("http://example.com/%d", requestNumber), nil)
			assert.NotNil(request)
			assert.Nil(err)

			var task Task

			switch requestNumber % 3 {
			case 0:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return request, nil
				})

				handler.On("Do", request).Return(&http.Response{}, nil)

			case 1:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return nil, taskError
				})

			default:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return request, nil
				})

				handler.On("Do", request).Return(nil, transactionError)
			}

			tasks = append(tasks, task)
		}

		dispatcher := client.Start()
		assert.NotNil(dispatcher)

		for _, task := range tasks {
			assert.Nil(dispatcher.Send(task))
		}

		taskWaitGroup.Wait()
		assert.Nil(dispatcher.Close())

		assert.Equal(
			ErrorClosed,
			dispatcher.Send(
				Task(func() (*http.Request, error) {
					assert.Fail("Task should not have been called after Close()")
					return nil, errors.New("Task should not have been called after Close()")
				}),
			),
		)

		handler.AssertExpectations(t)
	}
}
<commit_msg>Renamed things for clarity<commit_after>package httppool

import (
	"errors"
	"fmt"
	"github.com/Comcast/webpa-common/logging"
	"github.com/stretchr/testify/assert"
	"net/http"
	"os"
	"sync"
	"testing"
	"time"
)

const (
	taskCount = 100
)

var (
	taskError        = errors.New("Task error")
	transactionError = errors.New("Transaction error")
)

func TestClientDefaults(t *testing.T) {
	assert := assert.New(t)

	// all these clients should use default values
	var testData = []Client{
		Client{},
		Client{
			QueueSize: -1,
			Workers:   -1,
		},
		Client{
			QueueSize: -34582,
			Workers:   -4582,
			Period:    400 * time.Second,
		},
	}

	for _, client := range testData {
		t.Logf("client: %#v", client)
		assert.Equal(http.DefaultClient, client.handler())
		assert.Equal(DefaultQueueSize, client.queueSize())
		assert.Equal(DefaultWorkers, client.workers())

		_, ok := client.logger().(*logging.LoggerWriter)
		assert.True(ok)
	}
}

func TestClientNonDefaults(t *testing.T) {
	assert := assert.New(t)

	expectedHandler := &http.Client{}
	expectedLogger := &logging.LoggerWriter{os.Stderr}

	// none of these clients should use default values
	var testData = []Client{
		Client{
			Handler:   expectedHandler,
			Logger:    expectedLogger,
			Workers:   1234,
			QueueSize: 7983481,
		},
		Client{
			Handler:   expectedHandler,
			Logger:    expectedLogger,
			Workers:   2956,
			QueueSize: 275,
			Period:    1000 * time.Hour,
		},
	}

	for _, client := range testData {
		t.Logf("client: %#v", client)
		assert.Equal(expectedHandler, client.handler())
		assert.Equal(expectedLogger, client.logger())
		assert.Equal(client.QueueSize, client.queueSize())
		assert.Equal(client.Workers, client.workers())
	}
}

func TestClientDispatcher(t *testing.T) {
	assert := assert.New(t)

	var testData = []Client{
		Client{},
		Client{
			Workers:   1,
			QueueSize: 5,
		},
		Client{
			Period: 100 * time.Millisecond,
		},
		Client{
			Workers:   12,
			QueueSize: 200,
			Period:    100 * time.Millisecond,
		},
	}

	for _, client := range testData {
		taskWaitGroup := &sync.WaitGroup{}
		taskWaitGroup.Add(taskCount)

		handler := &mockTransactionHandler{}
		client.Handler = handler

		tasks := make([]Task, 0, taskCount)

		for taskNumber := 0; taskNumber < taskCount; taskNumber++ {
			request, err := http.NewRequest("GET", fmt.Sprintf("http://example.com/%d", taskNumber), nil)
			assert.NotNil(request)
			assert.Nil(err)

			var task Task

			switch taskNumber % 3 {
			case 0:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return request, nil
				})

				handler.On("Do", request).Return(&http.Response{}, nil)

			case 1:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return nil, taskError
				})

			default:
				task = Task(func() (*http.Request, error) {
					defer taskWaitGroup.Done()
					return request, nil
				})

				handler.On("Do", request).Return(nil, transactionError)
			}

			tasks = append(tasks, task)
		}

		dispatcher := client.Start()
		assert.NotNil(dispatcher)

		for _, task := range tasks {
			assert.Nil(dispatcher.Send(task))
		}

		taskWaitGroup.Wait()
		assert.Nil(dispatcher.Close())

		assert.Equal(
			ErrorClosed,
			dispatcher.Send(
				Task(func() (*http.Request, error) {
					assert.Fail("Task should not have been called after Close()")
					return nil, errors.New("Task should not have been called after Close()")
				}),
			),
		)

		handler.AssertExpectations(t)
	}
}
<|endoftext|>


<commit_before>package oneandone_cloudserver_api

import (
	"github.com/docker/machine/log"
	"net/http"
)

type FirewallPolicy struct {
	withId
	withName
	withDescription
	// should be fixed: Status        Status                   `json:"status"`
	Status        string                   `json:"state"`
	DefaultPolicy int                      `json:"default"`
	Rules         []FirewallPolicyRules    `json:"rules"`
	ServerIps     []FirewallPolicyServerIp `json:"server_ips"`
	withApi
}

type FirewallPolicyRules struct {
	withId
	Protocol string `json:"protocol"`
	PortFrom *int   `json:"port_from"`
	PortTo   *int   `json:"port_to"`
	SourceIp string `json:"source"`
}

type FirewallPolicyServerIp struct {
	withId
	Ip         string `json:"ip"`
	ServerName string `json:"server_name"`
}

type FirewallPolicyCreateData struct {
	Name        string                          `json:"name"`
	Description string                          `json:"description"`
	Rules       []FirewallPolicyRulesCreateData `json:"rules"`
}

type FirewallPolicyRulesCreateData struct {
	Protocol string `json:"protocol"`
	PortFrom *int   `json:"port_from"`
	PortTo   *int   `json:"port_to"`
	SourceIp string `json:"source"`
}

type FirewallPolicyAddIpsData struct {
	ServerIps []string `json:"server_ips"`
}

// GET /firewall_policies
func (api *API) GetFirewallPolicies() ([]FirewallPolicy, error) {
	log.Debug("requesting information about firewall policies")
	result := []FirewallPolicy{}
	err := api.Client.Get(createUrl(api, "firewall_policies"), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	for index, _ := range result {
		result[index].api = api
	}
	return result, nil
}

// POST /firewall_policies
func (api *API) CreateFirewallPolicy(configuration FirewallPolicyCreateData) (*FirewallPolicy, error) {
	log.Debug("requesting to create a new firewall policy")
	result := new(FirewallPolicy)
	err := api.Client.Post(createUrl(api, "firewall_policies"), configuration, &result, http.StatusCreated)
	if err != nil {
		return nil, err
	}
	result.api = api
	return result, nil
}

// GET /firewall_policies/{id}
func (api *API) GetFirewallPolicy(Id string) (*FirewallPolicy, error) {
	log.Debug("requesting to about firewall policy ", Id)
	result := new(FirewallPolicy)
	err := api.Client.Get(createUrl(api, "firewall_policies", Id), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	result.api = api
	return result, nil

}

// DELETE /firewall_policies/{id}
func (fwp *FirewallPolicy) Delete() (*FirewallPolicy, error) {
	log.Debug("Requested to delete firewall policy ", fwp.Id)
	result := new(FirewallPolicy)
	err := fwp.api.Client.Delete(createUrl(fwp.api, "firewall_policies", fwp.Id), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	result.api = fwp.api
	return result, nil
}

// PUT /firewall_policies/{id}

// GET /firewall_policies/{id}/server_ips

// PUT /firewall_policies/{id}/server_ips
func (fwp *FirewallPolicy) AddIp(ipId string) (*FirewallPolicy, error) {
	log.Debugf("Requested to apply firewall policy '%v' to ip '%v'", fwp.Id, ipId)
	result := new(FirewallPolicy)
	request := FirewallPolicyAddIpsData{
		ServerIps: []string{ipId},
	}
	err := fwp.api.Client.Put(createUrl(fwp.api, "firewall_policies", fwp.Id, "server_ips"), request, result, http.StatusAccepted)
	if err != nil {
		return nil, err
	}
	result.api = fwp.api
	return result, nil
}

// GET /firewall_policies/{id}/server_ips/{id}

// DELETE /firewall_policies/{id}/server_ips/{id}

// GET /firewall_policies/{id}/rules

// PUT /firewall_policies/{id}/rules

// GET /firewall_policies/{id}/rules/{id}

// DELETE /firewall_policies/{id}/rules/{id}
<commit_msg>Add function to remove server IP to a firewall policy.<commit_after>package oneandone_cloudserver_api

import (
	"github.com/docker/machine/log"
	"net/http"
)

type FirewallPolicy struct {
	withId
	withName
	withDescription
	// should be fixed: Status        Status                   `json:"status"`
	Status        string                   `json:"state"`
	DefaultPolicy int                      `json:"default"`
	Rules         []FirewallPolicyRules    `json:"rules"`
	ServerIps     []FirewallPolicyServerIp `json:"server_ips"`
	withApi
}

type FirewallPolicyRules struct {
	withId
	Protocol string `json:"protocol"`
	PortFrom *int   `json:"port_from"`
	PortTo   *int   `json:"port_to"`
	SourceIp string `json:"source"`
}

type FirewallPolicyServerIp struct {
	withId
	Ip         string `json:"ip"`
	ServerName string `json:"server_name"`
}

type FirewallPolicyCreateData struct {
	Name        string                          `json:"name"`
	Description string                          `json:"description"`
	Rules       []FirewallPolicyRulesCreateData `json:"rules"`
}

type FirewallPolicyRulesCreateData struct {
	Protocol string `json:"protocol"`
	PortFrom *int   `json:"port_from"`
	PortTo   *int   `json:"port_to"`
	SourceIp string `json:"source"`
}

type FirewallPolicyAddIpsData struct {
	ServerIps []string `json:"server_ips"`
}

// GET /firewall_policies
func (api *API) GetFirewallPolicies() ([]FirewallPolicy, error) {
	log.Debug("requesting information about firewall policies")
	result := []FirewallPolicy{}
	err := api.Client.Get(createUrl(api, "firewall_policies"), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	for index, _ := range result {
		result[index].api = api
	}
	return result, nil
}

// POST /firewall_policies
func (api *API) CreateFirewallPolicy(configuration FirewallPolicyCreateData) (*FirewallPolicy, error) {
	log.Debug("requesting to create a new firewall policy")
	result := new(FirewallPolicy)
	err := api.Client.Post(createUrl(api, "firewall_policies"), configuration, &result, http.StatusCreated)
	if err != nil {
		return nil, err
	}
	result.api = api
	return result, nil
}

// GET /firewall_policies/{id}
func (api *API) GetFirewallPolicy(Id string) (*FirewallPolicy, error) {
	log.Debug("requesting to about firewall policy ", Id)
	result := new(FirewallPolicy)
	err := api.Client.Get(createUrl(api, "firewall_policies", Id), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	result.api = api
	return result, nil

}

// DELETE /firewall_policies/{id}
func (fwp *FirewallPolicy) Delete() (*FirewallPolicy, error) {
	log.Debug("Requested to delete firewall policy ", fwp.Id)
	result := new(FirewallPolicy)
	err := fwp.api.Client.Delete(createUrl(fwp.api, "firewall_policies", fwp.Id), &result, http.StatusOK)
	if err != nil {
		return nil, err
	}
	result.api = fwp.api
	return result, nil
}

// PUT /firewall_policies/{id}

// GET /firewall_policies/{id}/server_ips

// PUT /firewall_policies/{id}/server_ips
func (fwp *FirewallPolicy) AddServerIp(ipId string) (*FirewallPolicy, error) {
	log.Debugf("Requested to apply firewall policy '%v' to ip '%v'", fwp.Id, ipId)
	result := new(FirewallPolicy)
	request := FirewallPolicyAddIpsData{
		ServerIps: []string{ipId},
	}
	err := fwp.api.Client.Put(createUrl(fwp.api, "firewall_policies", fwp.Id, "server_ips"), request, result, http.StatusAccepted)
	if err != nil {
		return nil, err
	}
	result.api = fwp.api
	return result, nil
}

// GET /firewall_policies/{id}/server_ips/{id}

// DELETE /firewall_policies/{id}/server_ips/{id}
func (fwp *FirewallPolicy) DeleteServerIp(ipId string) (*FirewallPolicy, error) {
	log.Debugf("Requested to remove firewall policy '%v' from ip '%v'", fwp.Id, ipId)
	result := new(FirewallPolicy)
	err := fwp.api.Client.Delete(createUrl(fwp.api, "firewall_policies", fwp.Id, "server_ips", ipId), result, http.StatusAccepted)
	if err != nil {
		return nil, err
	}
	result.api = fwp.api
	return result, nil
}

// GET /firewall_policies/{id}/rules

// PUT /firewall_policies/{id}/rules

// GET /firewall_policies/{id}/rules/{id}

// DELETE /firewall_policies/{id}/rules/{id}
<|endoftext|>


<commit_before>// +build windows

package firewall

func driverName() string {
	return "windows"
}

func apply(policy Policy) error {
	utils.RunCmd("netsh advfirewall set allprofiles state off")
	utils.RunCmd("netsh advfirewall set allprofiles firewallpolicy blockinbound,allowoutbound")
	utils.RunCmd("netsh advfirewall firewall delete rule name=all")

	for _, rule := range policy.Rules {
		utils.RunCmd(fmt.Sprintf("netsh advfirewall firewall add rule name=\"Concerto firewall\" dir=in action=allow remoteip=#{%s} protocol=#{%s} localport=#{%d}-#{%s}", rule.Cidr, rule.Protocol, rule.MinPort, rule.MaxPort))
	}

	utils.RunCmd("netsh advfirewall set allprofiles state on")
	return nil
}

func flush() error {
	utils.RunCmd("netsh advfirewall set allprofiles state off")
	utils.RunCmd("netsh advfirewall set allprofiles firewallpolicy allowinbound,allowoutbound")
	utils.RunCmd("netsh advfirewall firewall delete rule name=all")
	return nil
}
<commit_msg>Fixups for windows setups<commit_after>// +build windows

package firewall

import (
	"fmt"
	"github.com/flexiant/concerto/utils"
)

func driverName() string {
	return "windows"
}

func apply(policy Policy) error {
	utils.RunCmd("netsh advfirewall set allprofiles state off")
	utils.RunCmd("netsh advfirewall set allprofiles firewallpolicy blockinbound,allowoutbound")
	utils.RunCmd("netsh advfirewall firewall delete rule name=all")

	for _, rule := range policy.Rules {
		utils.RunCmd(fmt.Sprintf("netsh advfirewall firewall add rule name=\"Concerto firewall\" dir=in action=allow remoteip=#{%s} protocol=#{%s} localport=#{%d}-#{%s}", rule.Cidr, rule.Protocol, rule.MinPort, rule.MaxPort))
	}

	utils.RunCmd("netsh advfirewall set allprofiles state on")
	return nil
}

func flush() error {
	utils.RunCmd("netsh advfirewall set allprofiles state off")
	utils.RunCmd("netsh advfirewall set allprofiles firewallpolicy allowinbound,allowoutbound")
	utils.RunCmd("netsh advfirewall firewall delete rule name=all")
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/xkapasakal/go4OData/generated"
	"encoding/json"
)

type DType struct {
	Next string `json:"__next"`
	Results []generated.Customer
}

type Response struct {
	D DType
}

func main() {

	var jsonBlob = generated.Customers()
	var response Response
	err := json.Unmarshal(jsonBlob, &response)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("customers: %+v\n", response.D)

	var animalJsonBlob = []byte(`{"d": { "__next": "Kapas"}}`)
	type Animal struct {
		Name  string
		Order string
	}
	var animals Response
	err = json.Unmarshal(animalJsonBlob, &animals)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%+v\n ", animals)
}<commit_msg>Unmarshal json<commit_after>package main

import (
	"fmt"
	"github.com/xkapasakal/go4OData/generated"
	"encoding/json"
)

type DType struct {
	Next string `json:"__next"`
	Results []generated.Customer
}

type Response struct {
	D DType
}

func main() {

	var jsonBlob = generated.Customers()
	var response Response
	err := json.Unmarshal(jsonBlob, &response)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("customers: %+v\n", response.D)
	fmt.Printf("count customers: %+v\n", len(response.D.Results))

	var animalJsonBlob = []byte(`{"d": { "__next": "Kapas"}}`)
	type Animal struct {
		Name  string
		Order string
	}
	var animals Response
	err = json.Unmarshal(animalJsonBlob, &animals)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%+v\n ", animals)
}<|endoftext|>


<commit_before>// Copyright 2014 The goyy Authors.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package files implements file utility functions.
package files

import (
	"github.com/satori/go.uuid"
	"gopkg.in/goyy/goyy.v0/util/errors"
	"gopkg.in/goyy/goyy.v0/util/strings"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

// Reports whether the specified file exists.
// Returns true if the file exists, false if it does not exist.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}

// Read reads the file named by filename and returns the contents.
// A successful call returns err == nil, not err == EOF. Because Read
// reads the whole file, it does not treat an EOF from Read as an error
// to be reported.
func Read(filename string) (string, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

// Write writes data to a file named by filename.
// If the file does not exist, Write creates it with permissions perm;
// otherwise Write truncates it before writing.
func Write(filename string, data string, perm os.FileMode) error {
	return ioutil.WriteFile(filename, []byte(data), perm)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*os.File, error) {
	return os.Create(name)
}

// Copy copies from src to dst until either EOF is reached on src or an error occurs.
func Copy(dstfile string, srcfile string, perm os.FileMode) error {
	data, rerr := ioutil.ReadFile(srcfile)
	if rerr != nil {
		return rerr
	}
	werr := ioutil.WriteFile(dstfile, data, perm)
	if werr != nil {
		return werr
	}
	return nil
}

// Mkdir creates a new directory with the specified name and permission bits.
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

// MkdirAll creates a directory named path, along with any necessary parents,
// and returns nil, or else returns an error.
// The permission bits perm are used for all directories that MkdirAll creates.
// If path is already a directory, MkdirAll does nothing and returns nil.
func MkdirAll(name string, perm os.FileMode) error {
	return os.MkdirAll(name, perm)
}

// Rename renames a file.
func Rename(oldname, newname string) error {
	return os.Rename(oldname, newname)
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	return os.Remove(name)
}

// Returns the file
// extension for the given file name, or the empty string if the file has
// no extension.  The result does not include the '{@code .}'.
func Extension(fileName string) string {
	fname := strings.Replace(fileName, "\\", "/", -1)
	ext := strings.AfterLast(fname, ".")
	first := strings.Left(ext, 1)
	if first == "/" {
		return ""
	} else {
		return ext
	}
}

// ModTime returns the file modification time
func ModTime(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.ModTime().Unix(), nil
}

// Size returns the length in bytes for regular files
func Size(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.Size(), nil
}

// file upload
func Upload(w http.ResponseWriter, r *http.Request, field, dir string) (out string, err error) {
	if r.Method != "POST" {
		err = errors.New("status method tot allowed")
		logger.Error(err.Error())
		return
	}
	file, handler, err := r.FormFile(field)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	if !IsExist(dir) {
		if err = MkdirAll(dir, 0644); err != nil {
			logger.Error(err.Error())
			return
		}
	}
	filename := newId() + "." + Extension(handler.Filename)
	err = ioutil.WriteFile(dir+"/"+filename, data, 0700)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	out = handler.Filename
	return
}

// multipart file upload
func Uploads(w http.ResponseWriter, r *http.Request, field, dir string) (out []string, err error) {
	if r.Method != "POST" {
		err = errors.New("status method tot allowed")
		logger.Error(err.Error())
		return
	}
	//parse the multipart form in the request
	err = r.ParseMultipartForm(100000)
	if err != nil {
		logger.Error(err.Error())
		return
	}

	//get a ref to the parsed multipart form
	m := r.MultipartForm

	//get the *fileheaders
	files := m.File[field]
	for i, _ := range files {
		//for each fileheader, get a handle to the actual file
		file, ferr := files[i].Open()
		defer file.Close()
		if err != nil {
			err = ferr
			logger.Error(err.Error())
			return
		}
		if !IsExist(dir) {
			if err = MkdirAll(dir, 0644); err != nil {
				logger.Error(err.Error())
				return
			}
		}
		filename := newId() + "." + Extension(files[i].Filename)
		//create destination file making sure the path is writeable.
		dst, derr := os.Create(dir + "/" + filename)
		defer dst.Close()
		if err != nil {
			err = derr
			logger.Error(err.Error())
			return
		}
		//copy the uploaded file to the destination file
		if _, err = io.Copy(dst, file); err != nil {
			logger.Error(err.Error())
			return
		}
	}
	return
}

// newId returns the id string.
func newId() string {
	id := uuid.NewV1()
	return strings.Replace(id.String(), "-", "", -1)
}
<commit_msg>Add multipart file upload<commit_after>// Copyright 2014 The goyy Authors.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package files implements file utility functions.
package files

import (
	"github.com/satori/go.uuid"
	"gopkg.in/goyy/goyy.v0/util/errors"
	"gopkg.in/goyy/goyy.v0/util/strings"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

// Reports whether the specified file exists.
// Returns true if the file exists, false if it does not exist.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}

// Read reads the file named by filename and returns the contents.
// A successful call returns err == nil, not err == EOF. Because Read
// reads the whole file, it does not treat an EOF from Read as an error
// to be reported.
func Read(filename string) (string, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

// Write writes data to a file named by filename.
// If the file does not exist, Write creates it with permissions perm;
// otherwise Write truncates it before writing.
func Write(filename string, data string, perm os.FileMode) error {
	return ioutil.WriteFile(filename, []byte(data), perm)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*os.File, error) {
	return os.Create(name)
}

// Copy copies from src to dst until either EOF is reached on src or an error occurs.
func Copy(dstfile string, srcfile string, perm os.FileMode) error {
	data, rerr := ioutil.ReadFile(srcfile)
	if rerr != nil {
		return rerr
	}
	werr := ioutil.WriteFile(dstfile, data, perm)
	if werr != nil {
		return werr
	}
	return nil
}

// Mkdir creates a new directory with the specified name and permission bits.
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

// MkdirAll creates a directory named path, along with any necessary parents,
// and returns nil, or else returns an error.
// The permission bits perm are used for all directories that MkdirAll creates.
// If path is already a directory, MkdirAll does nothing and returns nil.
func MkdirAll(name string, perm os.FileMode) error {
	return os.MkdirAll(name, perm)
}

// Rename renames a file.
func Rename(oldname, newname string) error {
	return os.Rename(oldname, newname)
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	return os.Remove(name)
}

// Returns the file
// extension for the given file name, or the empty string if the file has
// no extension.  The result does not include the '{@code .}'.
func Extension(fileName string) string {
	fname := strings.Replace(fileName, "\\", "/", -1)
	ext := strings.AfterLast(fname, ".")
	first := strings.Left(ext, 1)
	if first == "/" {
		return ""
	} else {
		return ext
	}
}

// ModTime returns the file modification time
func ModTime(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.ModTime().Unix(), nil
}

// Size returns the length in bytes for regular files
func Size(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.Size(), nil
}

// file upload
func Upload(w http.ResponseWriter, r *http.Request, field, dir string) (out string, err error) {
	if r.Method != "POST" {
		err = errors.New("status method tot allowed")
		logger.Error(err.Error())
		return
	}
	file, handler, err := r.FormFile(field)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	if !IsExist(dir) {
		if err = MkdirAll(dir, 0644); err != nil {
			logger.Error(err.Error())
			return
		}
	}
	filename := newId() + "." + Extension(handler.Filename)
	err = ioutil.WriteFile(dir+"/"+filename, data, 0700)
	if err != nil {
		logger.Error(err.Error())
		return
	}
	out = filename
	return
}

// multipart file upload
func Uploads(w http.ResponseWriter, r *http.Request, field, dir string) (out []string, err error) {
	if r.Method != "POST" {
		err = errors.New("status method tot allowed")
		logger.Error(err.Error())
		return
	}
	//parse the multipart form in the request
	err = r.ParseMultipartForm(100000)
	if err != nil {
		logger.Error(err.Error())
		return
	}

	//get a ref to the parsed multipart form
	m := r.MultipartForm

	//get the *fileheaders
	files := m.File[field]
	for i, _ := range files {
		//for each fileheader, get a handle to the actual file
		file, ferr := files[i].Open()
		defer file.Close()
		if err != nil {
			err = ferr
			logger.Error(err.Error())
			return
		}
		if !IsExist(dir) {
			if err = MkdirAll(dir, 0644); err != nil {
				logger.Error(err.Error())
				return
			}
		}
		filename := newId() + "." + Extension(files[i].Filename)
		//create destination file making sure the path is writeable.
		dst, derr := os.Create(dir + "/" + filename)
		defer dst.Close()
		if err != nil {
			err = derr
			logger.Error(err.Error())
			return
		}
		//copy the uploaded file to the destination file
		if _, err = io.Copy(dst, file); err != nil {
			logger.Error(err.Error())
			return
		}
		out = append(out, filename)
	}
	return
}

// newId returns the id string.
func newId() string {
	id := uuid.NewV1()
	return strings.Replace(id.String(), "-", "", -1)
}
<|endoftext|>


<commit_before>// Copyright 2012 Yuichi Araki. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package yall

import (
    "os"
)

func bindLambdaList(env *Env, lambdaList *Cell, args *Cell) {
    for c := lambdaList; c != Empty; c = c.cdr {
        e := c.car
        if symbol, ok := e.(*Symbol); ok {
            if symbol.name == "." { // &rest (&body)
                env.Intern(c.Cadr().(*Symbol), args)
                break
            } else {
                expr := args.Car()
                env.Intern(symbol, expr)
                args = args.Cdr()
            }
        } else if cell, ok := e.(*Cell); ok {
            symbol := cell.car.(*Symbol)
            if Empty == args {
                defaultValue := cell.Cadr()
                env.Intern(symbol, defaultValue)
            } else {
                expr := args.Car()
                env.Intern(symbol, expr)
                args = args.Cdr()
            }
        }
    }
}

func Lambda(env *Env, args *Cell) Expr {
    lambdaList := args.Car().(*Cell)
    body := args.Cdr()
    return NewFunction("#lambda", func(args *Cell) Expr {
        derived := env.Derive()
        bindLambdaList(derived, lambdaList, args)
        return derived.Begin(body)
    })
}

var specialForms = map[string]func(*Env, *Cell) Expr{

    "def": func(env *Env, args *Cell) Expr {
        if symbol, ok := args.Car().(*Symbol); ok {
            value := env.Eval(args.Cadr())
            if function, ok := value.(*Function); ok {
                function.SetName(symbol.Name())
            }
            env.Intern(symbol, value)
            return symbol
        }
        panic(NewRuntimeError("Can't define"))
    },

    "lambda": Lambda,
    "fn":     Lambda,

    "macro": func(env *Env, args *Cell) Expr {
        lambdaList := args.Car().(*Cell)
        body := args.Cdr()
        return NewMacro("#macro", func(args *Cell) Expr {
            derived := env.Derive()
            bindLambdaList(derived, lambdaList, args)
            return derived.Begin(body)
        })
    },

    "defn": func(env *Env, args *Cell) Expr {
        cell, ok := args.Car().(*Cell)
        if !ok {
            panic(NewRuntimeError("Can't define function."))
        }
        symbol := cell.Car().(*Symbol)
        lambdaArgs := cell.Cdr()
        lambdaBody := args.Cdr()
        lambda := Lambda(env, NewCell(lambdaArgs, lambdaBody)).(*Function)
        lambda.SetName(symbol.Name())
        env.Intern(symbol, lambda)
        return symbol
    },

    "defmacro": func(env *Env, args *Cell) Expr {
        return True
    },

    "if": func(env *Env, args *Cell) Expr {
        condition := env.Eval(args.Car())
        if condition != False {
            return env.Eval(args.Cadr())
        }
        return env.Eval(args.Caddr())
    },

    "inc!": func(env *Env, args *Cell) Expr {
        symbol, ok := args.Car().(*Symbol)
        if !ok {
            panic(NewRuntimeError("inc! requires a symbol"))
        }
        integer, ok := env.Eval(symbol).(*Integer)
        integer.setValue(integer.Value() + 1)
        return integer
    },

    "load": func(env *Env, args *Cell) Expr {
        args.Each(func(expr Expr) {
            if filename, ok := expr.(*String); ok {
                file, err := os.Open(filename.value)
                if nil != err {
                    panic(NewRuntimeError("Cannot load: " + filename.String()))
                }
                defer file.Close()
                env.Load(file)
            } else {
                panic(NewRuntimeError("Cannot load: " + expr.String()))
            }
        })
        return True
    },
}
<commit_msg>Added "defmacro".<commit_after>// Copyright 2012 Yuichi Araki. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package yall

import (
    "os"
)

func bindLambdaList(env *Env, lambdaList *Cell, args *Cell) {
    for c := lambdaList; c != Empty; c = c.cdr {
        e := c.car
        if symbol, ok := e.(*Symbol); ok {
            if symbol.name == "." { // &rest (&body)
                env.Intern(c.Cadr().(*Symbol), args)
                break
            } else {
                expr := args.Car()
                env.Intern(symbol, expr)
                args = args.Cdr()
            }
        } else if cell, ok := e.(*Cell); ok {
            symbol := cell.car.(*Symbol)
            if Empty == args {
                defaultValue := cell.Cadr()
                env.Intern(symbol, defaultValue)
            } else {
                expr := args.Car()
                env.Intern(symbol, expr)
                args = args.Cdr()
            }
        }
    }
}

func lambda(env *Env, args *Cell) Expr {
    lambdaList := args.Car().(*Cell)
    body := args.Cdr()
    return NewFunction("#lambda", func(args *Cell) Expr {
        derived := env.Derive()
        bindLambdaList(derived, lambdaList, args)
        return derived.Begin(body)
    })
}

func macro(env *Env, args *Cell) Expr {
    lambdaList := args.Car().(*Cell)
    body := args.Cdr()
    return NewMacro("#macro", func(args *Cell) Expr {
        derived := env.Derive()
        bindLambdaList(derived, lambdaList, args)
        return derived.Begin(body)
    })
}

var specialForms = map[string]func(*Env, *Cell) Expr{

    "def": func(env *Env, args *Cell) Expr {
        if symbol, ok := args.Car().(*Symbol); ok {
            value := env.Eval(args.Cadr())
            if function, ok := value.(*Function); ok {
                function.SetName(symbol.Name())
            }
            env.Intern(symbol, value)
            return symbol
        }
        panic(NewRuntimeError("Can't define"))
    },

    "lambda": lambda,
    "fn":     lambda,

    "macro": macro,

    "defn": func(env *Env, args *Cell) Expr {
        cell, ok := args.Car().(*Cell)
        if !ok {
            panic(NewRuntimeError("Can't define function."))
        }
        symbol := cell.Car().(*Symbol)
        lambdaArgs := cell.Cdr()
        lambdaBody := args.Cdr()
        f := lambda(env, NewCell(lambdaArgs, lambdaBody)).(*Function)
        f.SetName(symbol.Name())
        env.Intern(symbol, f)
        return symbol
    },

    "defmacro": func(env *Env, args *Cell) Expr {
        cell, ok := args.car.(*Cell)
        if !ok {
            panic(NewRuntimeError("Can't define macro."))
        }
        symbol := cell.car.(*Symbol)
        lambdaList := cell.Cdr()
        body := args.Cdr()
        m := macro(env, NewCell(lambdaList, body)).(*Macro)
        m.SetName(symbol.name)
        env.Intern(symbol, m)
        return symbol
    },

    "if": func(env *Env, args *Cell) Expr {
        condition := env.Eval(args.Car())
        if condition != False {
            return env.Eval(args.Cadr())
        }
        return env.Eval(args.Caddr())
    },

    "inc!": func(env *Env, args *Cell) Expr {
        symbol, ok := args.Car().(*Symbol)
        if !ok {
            panic(NewRuntimeError("inc! requires a symbol"))
        }
        integer, ok := env.Eval(symbol).(*Integer)
        integer.setValue(integer.Value() + 1)
        return integer
    },

    "load": func(env *Env, args *Cell) Expr {
        args.Each(func(expr Expr) {
            if filename, ok := expr.(*String); ok {
                file, err := os.Open(filename.value)
                if nil != err {
                    panic(NewRuntimeError("Cannot load: " + filename.String()))
                }
                defer file.Close()
                env.Load(file)
            } else {
                panic(NewRuntimeError("Cannot load: " + expr.String()))
            }
        })
        return True
    },
}
<|endoftext|>


<commit_before>// Copyright 2015 Eleme Inc. All rights reserved.

package util

import "testing"

func TestLogger(t *testing.T) {
	l := NewLogger("example")
	l.Runtime()
	l.Debug("this is a debug message %v", 1)
	l.Info("this is a debug message %v", 2)
	l.Warn("this is a debug message %v", 3)
	l.Error("this is a debug message %v", 4)
}
<commit_msg>Minor fix<commit_after>// Copyright 2015 Eleme Inc. All rights reserved.

package util

import "testing"

func TestLogger(t *testing.T) {
	l := NewLogger("example")
	l.Runtime()
	l.Debug("this is a debug message %v", 1)
	l.Info("this is a info message %v", 2)
	l.Warn("this is a warn message %v", 3)
	l.Error("this is a error message %v", 4)
}
<|endoftext|>