<commit_before>package logberry

import (
	"log"

	"bytes"
	"fmt"
	"io"
	"os"
	"syscall"
	"time"

	"reflect"

	"github.com/BellerophonMobile/logberry/terminal"
)

// TextOutput is an OutputDriver that writes out log events in a
// structured but human readable form.  It has the following public
// properties:
//
//   DifferentialTime           Set to true to timestamp logs based on
//                              the duration since the start of the
//                              run rather than the absolute time.
//
//   Color                      Set to true/false to enable/disable
//                              outputting terminal color codes as
//                              part of formatting log entries.
//                              Defaults to false except for when
//                              constructed via NewStdOutput and
//                              NewErrOutput as below, in which case
//                              it defaults to true iff the underlying
//                              streams are terminals.
//
//   IDOffset                   The column at which to start printing
//                              identifying information.
//
//   DataOffset                 The column at which to start printing
//                              event data.
//
// The default offsets are designed to wrap well on either 80 column
// or very wide terminals, generally putting each event on 1 or 2
// lines respectively.
type TextOutput struct {
	root   *Root
	writer io.Writer

	start            time.Time
	DifferentialTime bool

	Color bool

	IDOffset   int
	DataOffset int
}

const (
	black int = iota
	red
	green
	yellow
	blue
	magenta
	cyan
	white
)

const (
	high_intensity int = 90
	low_intensity  int = 30
)

type terminalstyle struct {
	color     int
	bold      bool
	intensity int
}

var componenteventterminalstyles = [...]terminalstyle{
	{black, false, high_intensity},  // start
	{black, false, high_intensity},  // finish
	{blue, false, low_intensity},    // configuration
	{green, true, high_intensity},   // ready
	{white, false, high_intensity},  // info
	{yellow, false, high_intensity}, // warning
	{red, true, high_intensity},     // error
	{red, true, high_intensity},     // fatal
}

var taskeventterminalstyles = [...]terminalstyle{
	{white, false, high_intensity},  // begin
	{white, false, high_intensity},  // end
	{white, false, low_intensity},   // info
	{yellow, false, high_intensity}, // warning
	{red, true, high_intensity},     // error
}

func init() {

	//-- Check that labels are defined for the enumerations
	if len(componenteventterminalstyles) != int(componenteventclass_sentinel) {
		log.Fatal("Fatal internal error: " +
			"len(componenteventterminalstyles) != |ComponentEventClass|")
	}

	if len(taskeventterminalstyles) != int(taskeventclass_sentinel) {
		log.Fatal("Fatal internal error: " +
			"len(taskeventterminalstyles) != |TaskEventClass|")
	}

}

// NewStdOutput creates a new TextOutput attached to stdout.
func NewStdOutput() *TextOutput {
	t := NewTextOutput(os.Stdout)
	t.Color = terminal.IsTerminal(syscall.Stdout)
	return t
}

// NewErrOutput creates a new TextOutput attached to stderr.
func NewErrOutput() *TextOutput {
	t := NewTextOutput(os.Stderr)
	t.Color = terminal.IsTerminal(syscall.Stderr)
	return t
}

// NewTextOutput creates a new TextOutput attached to the given writer.
func NewTextOutput(w io.Writer) *TextOutput {
	return &TextOutput{
		writer:     w,
		start:      time.Now(),
		IDOffset:   84,
		DataOffset: 100,
	}
}

// Attach notifies the OutputDriver of its Root.  It should only be
// called by a Root.
func (o *TextOutput) Attach(root *Root) {
	o.root = root
}

// Detach notifies the OutputDriver that it has been removed from its
// Root.  It should only be called by a root.
func (o *TextOutput) Detach() {
	o.root = nil
}

func (o *TextOutput) timestamp() string {

	if o.DifferentialTime {
		return time.Since(o.start).String()
	}

	return time.Now().Format(time.RFC3339)

	// end timestamp
}

func (o *TextOutput) internalerror(err error) {

	if o.Color {
		fmt.Fprintf(o.writer, "\x1b[%d;1m", high_intensity+red)
	}

	fmt.Fprintf(o.writer, "%v [LOG ERROR] %v\n",
		o.timestamp(), err.Error())

	if o.Color {
		fmt.Fprintf(o.writer, "\x1b[0m")
	}

	fmt.Fprintf(o.writer, "\n")

	o.root.InternalError(WrapError(err, "Could not output log entry"))

}

// printf is a convenience function to handle potential write errors
// in outputting log events.
func (o *TextOutput) printf(msg string, a ...interface{}) int {

	n, e := fmt.Fprintf(o.writer, msg, a...)
	if e != nil {
		o.internalerror(e)
	}
	return n
}

// keyrender generates a []byte string of "key=value" pairs for the
// given data.
func keyrender(data interface{}) []byte {

	var bytes = new(bytes.Buffer)
	keyrenderrecurse(bytes, false, data)
	return bytes.Bytes()

}

func keyrenderrecurse(bytes *bytes.Buffer, wrap bool, data interface{}) {

	var val = reflect.ValueOf(data)

	switch val.Kind() {

	case reflect.Interface:
		fallthrough
	case reflect.Ptr:
		if val.IsNil() {
			fmt.Fprint(bytes, "nil")
		} else {
			keyrenderrecurse(bytes, wrap, val.Elem().Interface())
		}

	case reflect.Map:
		if val.IsNil() {
			fmt.Fprint(bytes, "nil")
		} else {
			var vals = val.MapKeys()
			if wrap {
				fmt.Fprint(bytes, "{ ")
			}
			for _, k := range vals {
				fmt.Fprintf(bytes, "%s=", k.Interface())
				keyrenderrecurse(bytes, true, val.MapIndex(k).Interface())
			}
			if wrap {
				fmt.Fprint(bytes, "}")
			}
		}

	case reflect.Struct:
		var vtype = val.Type()

		if wrap {
			fmt.Fprint(bytes, "{ ")
		}

		for i := 0; i < val.NumField(); i++ {
			var f = val.Field(i)
			fmt.Fprintf(bytes, "%s=", vtype.Field(i).Name)
			keyrenderrecurse(bytes, true, f.Interface())
		}

		if wrap {
			fmt.Fprint(bytes, "}")
		}

	case reflect.Array:
		fallthrough
	case reflect.Slice:
		fmt.Fprint(bytes, "[ ")

		if val.Len() > 0 {
			keyrenderrecurse(bytes, true, val.Index(0).Interface())
		}

		for i := 1; i < val.Len(); i++ {
			fmt.Fprint(bytes, ", ")
			keyrenderrecurse(bytes, true, val.Index(i).Interface())
		}
		fmt.Fprint(bytes, "]")

	case reflect.String:
		fmt.Fprintf(bytes, "%q", val.String())

	default:
		fmt.Fprintf(bytes, "%v", val.Interface())

		// end switch type
	}

	fmt.Fprint(bytes, " ")
}

func (o *TextOutput) contextevent(cxttype string,
	context Context,
	event string,
	msg string,
	data *D,
	style *terminalstyle) {

	var writsofar int

	if context.IsHighlighted() {
		style.bold = true
	}

	// Set the color
	var color int = white
	if o.Color {
		color = style.color

		// Terminal commands produce no text, so don't include in writsofar
		o.printf("\x1b[%dm", style.intensity+color)
		if style.bold {
			o.printf("\x1b[1m")
		}
	}

	// Write the timestamp, root tag, label, and message

	writsofar += o.printf("%v %v %v ",
		o.timestamp(), context.GetRoot().Tag, context.GetLabel())

	writsofar += o.printf("%v ", msg)

	// Space out and then write the data fields

	for writsofar < o.IDOffset {
		writsofar += o.printf(" ")
	}

	if o.Color {
		if color != black {
			o.printf("\x1b[0;%dm", low_intensity+color)
		} else {
			o.printf("\x1b[0;%dm", high_intensity+color)
		}
	}

	writsofar += o.printf("%7v %v %-2v ", event, cxttype, context.GetUID())

	for writsofar < o.DataOffset {
		writsofar += o.printf(" ")
	}

	o.printf("%s", keyrender(data))

	if o.Color {
		o.printf("\x1b[0m")
	}
	o.printf("\n")

	// end contextevent
}

// ComponentEvent logs an event generated by a Component.  It should
// only be called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) ComponentEvent(component *Component,
	event ComponentEventClass,
	msg string,
	data *D) {

	if InvalidComponentEventClass(event) {
		o.internalerror(NewError("ComponentEventClass out of range",
			component.GetUID(), event))
		return
	}

	if component.mute {
		return
	}

	var style = &componenteventterminalstyles[event]

	o.contextevent("cmpt", component, ComponentEventClassText[event], msg, data, style)

	// end ComponentEvent
}

// TaskEvent logs an event generated by a Task.  It should only be
// called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) TaskEvent(task *Task,
	event TaskEventClass) {

	if InvalidTaskEventClass(event) {
		o.internalerror(NewError("TaskEventClass out of range for TaskProgress()",
			task.GetUID(), event))
		return
	}

	if task.mute {
		return
	}

	var style = &taskeventterminalstyles[event]

	var msg string = task.activity

	switch event {
	case TASK_BEGIN:
		msg += " start"

	case TASK_END:
		msg += " success"
		if task.highlight {
			style = &terminalstyle{green, true, high_intensity}
		}

	case TASK_WARNING:
		msg += " warning"

	case TASK_ERROR:
		msg += " failure"

	default:
		o.internalerror(NewError("TaskEventClass out of range for TaskEvent()",
			task.GetUID(), event))
		return

	}

	o.contextevent("task", task, TaskEventClassText[event], msg, task.data, style)

	// end TaskEvent
}

// TaskProgress logs an event generated by a Task.  It should only be
// called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) TaskProgress(task *Task,
	event TaskEventClass,
	msg string,
	data *D) {

	if InvalidTaskEventClass(event) {
		o.internalerror(NewError("TaskEventClass out of range for TaskProgress()",
			task.GetUID(), event))
		return
	}

	if task.mute {
		return
	}

	var style = &taskeventterminalstyles[event]

	o.contextevent("task", task, TaskEventClassText[event], msg, data, style)

	// end TaskProgress
}
<commit_msg>Update spacing to not have multiple spaces before commas in list of structs/maps.<commit_after>package logberry

import (
	"log"

	"bytes"
	"fmt"
	"io"
	"os"
	"syscall"
	"time"

	"reflect"

	"github.com/BellerophonMobile/logberry/terminal"
)

// TextOutput is an OutputDriver that writes out log events in a
// structured but human readable form.  It has the following public
// properties:
//
//   DifferentialTime           Set to true to timestamp logs based on
//                              the duration since the start of the
//                              run rather than the absolute time.
//
//   Color                      Set to true/false to enable/disable
//                              outputting terminal color codes as
//                              part of formatting log entries.
//                              Defaults to false except for when
//                              constructed via NewStdOutput and
//                              NewErrOutput as below, in which case
//                              it defaults to true iff the underlying
//                              streams are terminals.
//
//   IDOffset                   The column at which to start printing
//                              identifying information.
//
//   DataOffset                 The column at which to start printing
//                              event data.
//
// The default offsets are designed to wrap well on either 80 column
// or very wide terminals, generally putting each event on 1 or 2
// lines respectively.
type TextOutput struct {
	root   *Root
	writer io.Writer

	start            time.Time
	DifferentialTime bool

	Color bool

	IDOffset   int
	DataOffset int
}

const (
	black int = iota
	red
	green
	yellow
	blue
	magenta
	cyan
	white
)

const (
	high_intensity int = 90
	low_intensity  int = 30
)

type terminalstyle struct {
	color     int
	bold      bool
	intensity int
}

var componenteventterminalstyles = [...]terminalstyle{
	{black, false, high_intensity},  // start
	{black, false, high_intensity},  // finish
	{blue, false, low_intensity},    // configuration
	{green, true, high_intensity},   // ready
	{white, false, high_intensity},  // info
	{yellow, false, high_intensity}, // warning
	{red, true, high_intensity},     // error
	{red, true, high_intensity},     // fatal
}

var taskeventterminalstyles = [...]terminalstyle{
	{white, false, high_intensity},  // begin
	{white, false, high_intensity},  // end
	{white, false, low_intensity},   // info
	{yellow, false, high_intensity}, // warning
	{red, true, high_intensity},     // error
}

func init() {

	//-- Check that labels are defined for the enumerations
	if len(componenteventterminalstyles) != int(componenteventclass_sentinel) {
		log.Fatal("Fatal internal error: " +
			"len(componenteventterminalstyles) != |ComponentEventClass|")
	}

	if len(taskeventterminalstyles) != int(taskeventclass_sentinel) {
		log.Fatal("Fatal internal error: " +
			"len(taskeventterminalstyles) != |TaskEventClass|")
	}

}

// NewStdOutput creates a new TextOutput attached to stdout.
func NewStdOutput() *TextOutput {
	t := NewTextOutput(os.Stdout)
	t.Color = terminal.IsTerminal(syscall.Stdout)
	return t
}

// NewErrOutput creates a new TextOutput attached to stderr.
func NewErrOutput() *TextOutput {
	t := NewTextOutput(os.Stderr)
	t.Color = terminal.IsTerminal(syscall.Stderr)
	return t
}

// NewTextOutput creates a new TextOutput attached to the given writer.
func NewTextOutput(w io.Writer) *TextOutput {
	return &TextOutput{
		writer:     w,
		start:      time.Now(),
		IDOffset:   84,
		DataOffset: 100,
	}
}

// Attach notifies the OutputDriver of its Root.  It should only be
// called by a Root.
func (o *TextOutput) Attach(root *Root) {
	o.root = root
}

// Detach notifies the OutputDriver that it has been removed from its
// Root.  It should only be called by a root.
func (o *TextOutput) Detach() {
	o.root = nil
}

func (o *TextOutput) timestamp() string {

	if o.DifferentialTime {
		return time.Since(o.start).String()
	}

	return time.Now().Format(time.RFC3339)

	// end timestamp
}

func (o *TextOutput) internalerror(err error) {

	if o.Color {
		fmt.Fprintf(o.writer, "\x1b[%d;1m", high_intensity+red)
	}

	fmt.Fprintf(o.writer, "%v [LOG ERROR] %v\n",
		o.timestamp(), err.Error())

	if o.Color {
		fmt.Fprintf(o.writer, "\x1b[0m")
	}

	fmt.Fprintf(o.writer, "\n")

	o.root.InternalError(WrapError(err, "Could not output log entry"))

}

// printf is a convenience function to handle potential write errors
// in outputting log events.
func (o *TextOutput) printf(msg string, a ...interface{}) int {

	n, e := fmt.Fprintf(o.writer, msg, a...)
	if e != nil {
		o.internalerror(e)
	}
	return n
}

// keyrender generates a []byte string of "key=value" pairs for the
// given data.
func keyrender(data interface{}) []byte {

	var bytes = new(bytes.Buffer)
	keyrenderrecurse(bytes, false, data)
	return bytes.Bytes()

}

func keyrenderrecurse(bytes *bytes.Buffer, wrap bool, data interface{}) {

	var val = reflect.ValueOf(data)

	switch val.Kind() {

	case reflect.Interface:
		fallthrough
	case reflect.Ptr:
		if val.IsNil() {
			fmt.Fprint(bytes, "nil")
		} else {
			keyrenderrecurse(bytes, wrap, val.Elem().Interface())
		}

	case reflect.Map:
		if val.IsNil() {
			fmt.Fprint(bytes, "nil")
		} else {
			var vals = val.MapKeys()
			if wrap {
				fmt.Fprint(bytes, "{")
			}
			for _, k := range vals {
				fmt.Fprintf(bytes, " %s=", k.Interface())
				keyrenderrecurse(bytes, true, val.MapIndex(k).Interface())
			}
			if wrap {
				fmt.Fprint(bytes, " }")
			}
		}

	case reflect.Struct:
		var vtype = val.Type()

		if wrap {
			fmt.Fprint(bytes, "{")
		}

		for i := 0; i < val.NumField(); i++ {
			var f = val.Field(i)
			fmt.Fprintf(bytes, " %s=", vtype.Field(i).Name)
			keyrenderrecurse(bytes, true, f.Interface())
		}

		if wrap {
			fmt.Fprint(bytes, " }")
		}

	case reflect.Array:
		fallthrough
	case reflect.Slice:
		fmt.Fprint(bytes, "[")

		if val.Len() > 0 {
			keyrenderrecurse(bytes, true, val.Index(0).Interface())
		}

		for i := 1; i < val.Len(); i++ {
			fmt.Fprint(bytes, ", ")
			keyrenderrecurse(bytes, true, val.Index(i).Interface())
		}
		fmt.Fprint(bytes, " ]")

	case reflect.String:
		fmt.Fprintf(bytes, "%q", val.String())

	default:
		fmt.Fprintf(bytes, "%v", val.Interface())

		// end switch type
	}

}

func (o *TextOutput) contextevent(cxttype string,
	context Context,
	event string,
	msg string,
	data *D,
	style *terminalstyle) {

	var writsofar int

	if context.IsHighlighted() {
		style.bold = true
	}

	// Set the color
	var color int = white
	if o.Color {
		color = style.color

		// Terminal commands produce no text, so don't include in writsofar
		o.printf("\x1b[%dm", style.intensity+color)
		if style.bold {
			o.printf("\x1b[1m")
		}
	}

	// Write the timestamp, root tag, label, and message

	writsofar += o.printf("%v %v %v ",
		o.timestamp(), context.GetRoot().Tag, context.GetLabel())

	writsofar += o.printf("%v ", msg)

	// Space out and then write the data fields

	for writsofar < o.IDOffset {
		writsofar += o.printf(" ")
	}

	if o.Color {
		if color != black {
			o.printf("\x1b[0;%dm", low_intensity+color)
		} else {
			o.printf("\x1b[0;%dm", high_intensity+color)
		}
	}

	writsofar += o.printf("%7v %v %-2v ", event, cxttype, context.GetUID())

	for writsofar < o.DataOffset {
		writsofar += o.printf(" ")
	}

	o.printf("%s", keyrender(data))

	if o.Color {
		o.printf("\x1b[0m")
	}
	o.printf("\n")

	// end contextevent
}

// ComponentEvent logs an event generated by a Component.  It should
// only be called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) ComponentEvent(component *Component,
	event ComponentEventClass,
	msg string,
	data *D) {

	if InvalidComponentEventClass(event) {
		o.internalerror(NewError("ComponentEventClass out of range",
			component.GetUID(), event))
		return
	}

	if component.mute {
		return
	}

	var style = &componenteventterminalstyles[event]

	o.contextevent("cmpt", component, ComponentEventClassText[event], msg, data, style)

	// end ComponentEvent
}

// TaskEvent logs an event generated by a Task.  It should only be
// called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) TaskEvent(task *Task,
	event TaskEventClass) {

	if InvalidTaskEventClass(event) {
		o.internalerror(NewError("TaskEventClass out of range for TaskProgress()",
			task.GetUID(), event))
		return
	}

	if task.mute {
		return
	}

	var style = &taskeventterminalstyles[event]

	var msg string = task.activity

	switch event {
	case TASK_BEGIN:
		msg += " start"

	case TASK_END:
		msg += " success"
		if task.highlight {
			style = &terminalstyle{green, true, high_intensity}
		}

	case TASK_WARNING:
		msg += " warning"

	case TASK_ERROR:
		msg += " failure"

	default:
		o.internalerror(NewError("TaskEventClass out of range for TaskEvent()",
			task.GetUID(), event))
		return

	}

	o.contextevent("task", task, TaskEventClassText[event], msg, task.data, style)

	// end TaskEvent
}

// TaskProgress logs an event generated by a Task.  It should only be
// called by a Root or an OutputDriver chaining outputs.
func (o *TextOutput) TaskProgress(task *Task,
	event TaskEventClass,
	msg string,
	data *D) {

	if InvalidTaskEventClass(event) {
		o.internalerror(NewError("TaskEventClass out of range for TaskProgress()",
			task.GetUID(), event))
		return
	}

	if task.mute {
		return
	}

	var style = &taskeventterminalstyles[event]

	o.contextevent("task", task, TaskEventClassText[event], msg, data, style)

	// end TaskProgress
}
<|endoftext|>


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

// Package sessions provides the JSON handlers to handle connections to gonawin app.
package sessions

import (
	"errors"
	golog "log"
	"net/http"
	"net/url"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
	"appengine/user"

	oauth "github.com/garyburd/go-oauth/oauth"

	"github.com/santiaago/gonawin/helpers"
	authhlp "github.com/santiaago/gonawin/helpers/auth"
	"github.com/santiaago/gonawin/helpers/log"
	"github.com/santiaago/gonawin/helpers/memcache"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

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

var (
	config                 *gwconfig.GwConfig
	twitterConfig          oauth.Client
	twitterCallbackURL     string
	googleVerifyTokenURL   string
	facebookVerifyTokenURL string
)

func init() {
	// read config file.
	var err error
	if config, err = gwconfig.ReadConfig(""); err != nil {
		golog.Printf("Error: unable to read config file; %v", err)
	}
	// Set up a configuration for twitter.
	twitterConfig = oauth.Client{
		Credentials:                   oauth.Credentials{Token: config.Twitter.Token, Secret: config.Twitter.Secret},
		TemporaryCredentialRequestURI: "https://api.twitter.com/oauth/request_token",
		ResourceOwnerAuthorizationURI: "https://api.twitter.com/oauth/authorize",
		TokenRequestURI:               "https://api.twitter.com/oauth/access_token",
	}
	twitterCallbackURL = "/j/auth/twitter/callback"
	googleVerifyTokenURL = "https://www.google.com/accounts/AuthSubTokenInfo?bearer_token"
	facebookVerifyTokenURL = "https://graph.facebook.com/me?access_token"
}

// JSON authentication handler
func Authenticate(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	if r.Method == "GET" {
		userInfo := authhlp.UserInfo{Id: r.FormValue("id"), Email: r.FormValue("email"), Name: r.FormValue("name")}

		var verifyURL string
		if r.FormValue("provider") == "google" {
			verifyURL = googleVerifyTokenURL
		} else if r.FormValue("provider") == "facebook" {
			verifyURL = facebookVerifyTokenURL
		}

		if !authhlp.CheckUserValidity(r, verifyURL, r.FormValue("access_token")) {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsAccessTokenNotValid)}
		}

		var user *mdl.User
		var err error
		if user, err = mdl.SigninUser(w, r, "Email", userInfo.Email, userInfo.Name, userInfo.Name); err != nil {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON authentication for Twitter.
func TwitterAuth(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Twitter Auth handler:"
	if r.Method == "GET" {
		credentials, err := twitterConfig.RequestTemporaryCredentials(urlfetch.Client(c), "http://"+r.Host+twitterCallbackURL, nil)
		if err != nil {
			c.Errorf("JsonTwitterAuth, error = %v", err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetTempCredentials)}
		}

		if err = memcache.Set(c, "secret", credentials.Secret); err != nil {
			// store secret in datastore
			secretId, _, err := datastore.AllocateIDs(c, "Secret", nil, 1)
			if err != nil {
				log.Errorf(c, "%s Cannot allocate ID for secret. %v", desc, err)
			}

			key := datastore.NewKey(c, "Secret", "", secretId, nil)

			_, err = datastore.Put(c, key, credentials.Secret)
			if err != nil {
				log.Errorf(c, "%s Cannot put secret in Datastore. %v", desc, err)
				return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotSetSecretValue)}
			}
		}

		// return OAuth token
		oAuthToken := struct {
			OAuthToken string
		}{
			credentials.Token,
		}

		return templateshlp.RenderJson(w, c, oAuthToken)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Twitter Authentication Callback
func TwitterAuthCallback(w http.ResponseWriter, r *http.Request) error {
	if r.Method == "GET" {
		http.Redirect(w, r, "http://"+r.Host+"/#/auth/twitter/callback?oauth_token="+r.FormValue("oauth_token")+"&oauth_verifier="+r.FormValue("oauth_verifier"), http.StatusFound)
		return nil
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Twitter Authentication Callback
func TwitterUser(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Twitter User handler:"
	if r.Method == "GET" {

		var user *mdl.User

		log.Infof(c, "%s oauth_verifier = %s", desc, r.FormValue("oauth_verifier"))
		log.Infof(c, "%s oauth_token = %s", desc, r.FormValue("oauth_token"))

		// get the request token
		requestToken := r.FormValue("oauth_token")
		// update credentials with request token and 'secret cookie value'
		var cred oauth.Credentials
		cred.Token = requestToken
		if secret, err := memcache.Get(c, "secret"); secret != nil {
			cred.Secret = string(secret.([]byte))
		} else {
			log.Errorf(c, "%s cannot get secret value from memcache: %v", desc, err)
			// try to get secret from datastore
			q := datastore.NewQuery("Secret")
			var secrets []string
			if keys, err := q.GetAll(c, &secrets); err == nil && len(secrets) > 0 {
				secret = secrets[0]

				// delete secret from datastore
				if err = datastore.Delete(c, keys[0]); err != nil {
					log.Errorf(c, "%s Error when trying to delete 'secret' key in Datastore: %v", desc, err)
				}

			} else if err != nil || len(secrets) == 0 {
				log.Errorf(c, "%s cannot get secret value from Datastore: %v", desc, err)
				return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetSecretValue)}
			}
		}

		if err := memcache.Delete(c, "secret"); err != nil {
			log.Errorf(c, "%s Error when trying to delete memcached 'secret' key: %v", desc, err)
		}

		token, values, err := twitterConfig.RequestToken(urlfetch.Client(c), &cred, r.FormValue("oauth_verifier"))
		if err != nil {
			log.Errorf(c, "%s Error when trying to delete memcached 'secret' key: %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetRequestToken)}
		}

		// get user info
		urlValues := url.Values{}
		urlValues.Set("user_id", values.Get("user_id"))
		resp, err := twitterConfig.Get(urlfetch.Client(c), token, "https://api.twitter.com/1.1/users/show.json", urlValues)
		if err != nil {
			log.Errorf(c, "%s Cannot get user info from twitter. %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetUserInfo)}
		}

		userInfo, err := authhlp.FetchTwitterUserInfo(resp)
		if err != nil {
			log.Errorf(c, "%s Cannot get user info by fetching twitter response. %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetUserInfo)}
		}

		if user, err = mdl.SigninUser(w, r, "Username", "", userInfo.Screen_name, userInfo.Name); err != nil {
			log.Errorf(c, "%s Unable to signin user %s. %v", desc, userInfo.Name, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to get Google accounts login URL.
func GoogleAccountsLoginURL(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts Login URL Handler:"
	if r.Method == "GET" {
		u := user.Current(c)
		var url string
		if u == nil {
			var err error
			url, err = user.LoginURL(c, "/j/auth/google/callback/")
			if err != nil {
				log.Errorf(c, "%s error when getting Google accounts login URL", desc)
				return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetGoogleLoginUrl)}
			}
		}

		// return user
		loginData := struct {
			Url string
		}{
			url,
		}

		return templateshlp.RenderJson(w, c, loginData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Google Authentication Callback
func GoogleAuthCallback(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts Auth Callback Handler:"
	if r.Method == "GET" {
		u := user.Current(c)
		if u == nil {
			log.Errorf(c, "%s user cannot be nil", desc)
			return &helpers.InternalServerError{Err: errors.New("user cannot be nil")}
		}

		http.Redirect(w, r, "http://"+r.Host+"/#/auth/google/callback?auth_token="+u.ID, http.StatusFound)
		return nil
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to get Google accounts user.
func GoogleUser(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts User Handler:"
	if r.Method == "GET" {
		u := user.Current(c)
		if u == nil {
			log.Errorf(c, "%s user cannot be nil", desc)
			return &helpers.InternalServerError{Err: errors.New("user cannot be nil")}
		}

		if u.ID != r.FormValue("auth_token") {
			log.Errorf(c, "%s Auth token doesn't match user ID", desc)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsAccessTokenNotValid)}
		}

		userInfo := authhlp.GetUserGoogleInfo(u)

		var user *mdl.User
		var err error
		if user, err = mdl.SigninUser(w, r, "Email", userInfo.Email, userInfo.Name, userInfo.Name); err != nil {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to delete cookie created by Google account
func GoogleDeleteCookie(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	if r.Method == "GET" {
		cookieName := "ACSID"
		if appengine.IsDevAppServer() {
			cookieName = "dev_appserver_login"
		}
		cookie := http.Cookie{Name: cookieName, Path: "/", MaxAge: -1}
		http.SetCookie(w, &cookie)

		return templateshlp.RenderJson(w, c, "Google user has been logged out")
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

func AuthServiceIds(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)

	if r.Method == "GET" {
		data := struct {
			GooglePlusClientId string
			FacebookAppId      string
		}{
			config.GooglePlus.ClientId,
			config.Facebook.AppId,
		}
		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<commit_msg>user is now able to log into gonawin after closing the browser (auth with gmail) Fixes #530<commit_after>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// Package sessions provides the JSON handlers to handle connections to gonawin app.
package sessions

import (
	"errors"
	golog "log"
	"net/http"
	"net/url"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
	"appengine/user"

	oauth "github.com/garyburd/go-oauth/oauth"

	"github.com/santiaago/gonawin/helpers"
	authhlp "github.com/santiaago/gonawin/helpers/auth"
	"github.com/santiaago/gonawin/helpers/log"
	"github.com/santiaago/gonawin/helpers/memcache"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

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

var (
	config                 *gwconfig.GwConfig
	twitterConfig          oauth.Client
	twitterCallbackURL     string
	googleVerifyTokenURL   string
	facebookVerifyTokenURL string
)

func init() {
	// read config file.
	var err error
	if config, err = gwconfig.ReadConfig(""); err != nil {
		golog.Printf("Error: unable to read config file; %v", err)
	}
	// Set up a configuration for twitter.
	twitterConfig = oauth.Client{
		Credentials:                   oauth.Credentials{Token: config.Twitter.Token, Secret: config.Twitter.Secret},
		TemporaryCredentialRequestURI: "https://api.twitter.com/oauth/request_token",
		ResourceOwnerAuthorizationURI: "https://api.twitter.com/oauth/authorize",
		TokenRequestURI:               "https://api.twitter.com/oauth/access_token",
	}
	twitterCallbackURL = "/j/auth/twitter/callback"
	googleVerifyTokenURL = "https://www.google.com/accounts/AuthSubTokenInfo?bearer_token"
	facebookVerifyTokenURL = "https://graph.facebook.com/me?access_token"
}

// JSON authentication handler
func Authenticate(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	if r.Method == "GET" {
		userInfo := authhlp.UserInfo{Id: r.FormValue("id"), Email: r.FormValue("email"), Name: r.FormValue("name")}

		var verifyURL string
		if r.FormValue("provider") == "google" {
			verifyURL = googleVerifyTokenURL
		} else if r.FormValue("provider") == "facebook" {
			verifyURL = facebookVerifyTokenURL
		}

		if !authhlp.CheckUserValidity(r, verifyURL, r.FormValue("access_token")) {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsAccessTokenNotValid)}
		}

		var user *mdl.User
		var err error
		if user, err = mdl.SigninUser(w, r, "Email", userInfo.Email, userInfo.Name, userInfo.Name); err != nil {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON authentication for Twitter.
func TwitterAuth(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Twitter Auth handler:"
	if r.Method == "GET" {
		credentials, err := twitterConfig.RequestTemporaryCredentials(urlfetch.Client(c), "http://"+r.Host+twitterCallbackURL, nil)
		if err != nil {
			c.Errorf("JsonTwitterAuth, error = %v", err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetTempCredentials)}
		}

		if err = memcache.Set(c, "secret", credentials.Secret); err != nil {
			// store secret in datastore
			secretId, _, err := datastore.AllocateIDs(c, "Secret", nil, 1)
			if err != nil {
				log.Errorf(c, "%s Cannot allocate ID for secret. %v", desc, err)
			}

			key := datastore.NewKey(c, "Secret", "", secretId, nil)

			_, err = datastore.Put(c, key, credentials.Secret)
			if err != nil {
				log.Errorf(c, "%s Cannot put secret in Datastore. %v", desc, err)
				return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotSetSecretValue)}
			}
		}

		// return OAuth token
		oAuthToken := struct {
			OAuthToken string
		}{
			credentials.Token,
		}

		return templateshlp.RenderJson(w, c, oAuthToken)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Twitter Authentication Callback
func TwitterAuthCallback(w http.ResponseWriter, r *http.Request) error {
	if r.Method == "GET" {
		http.Redirect(w, r, "http://"+r.Host+"/#/auth/twitter/callback?oauth_token="+r.FormValue("oauth_token")+"&oauth_verifier="+r.FormValue("oauth_verifier"), http.StatusFound)
		return nil
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Twitter Authentication Callback
func TwitterUser(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Twitter User handler:"
	if r.Method == "GET" {

		var user *mdl.User

		log.Infof(c, "%s oauth_verifier = %s", desc, r.FormValue("oauth_verifier"))
		log.Infof(c, "%s oauth_token = %s", desc, r.FormValue("oauth_token"))

		// get the request token
		requestToken := r.FormValue("oauth_token")
		// update credentials with request token and 'secret cookie value'
		var cred oauth.Credentials
		cred.Token = requestToken
		if secret, err := memcache.Get(c, "secret"); secret != nil {
			cred.Secret = string(secret.([]byte))
		} else {
			log.Errorf(c, "%s cannot get secret value from memcache: %v", desc, err)
			// try to get secret from datastore
			q := datastore.NewQuery("Secret")
			var secrets []string
			if keys, err := q.GetAll(c, &secrets); err == nil && len(secrets) > 0 {
				secret = secrets[0]

				// delete secret from datastore
				if err = datastore.Delete(c, keys[0]); err != nil {
					log.Errorf(c, "%s Error when trying to delete 'secret' key in Datastore: %v", desc, err)
				}

			} else if err != nil || len(secrets) == 0 {
				log.Errorf(c, "%s cannot get secret value from Datastore: %v", desc, err)
				return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetSecretValue)}
			}
		}

		if err := memcache.Delete(c, "secret"); err != nil {
			log.Errorf(c, "%s Error when trying to delete memcached 'secret' key: %v", desc, err)
		}

		token, values, err := twitterConfig.RequestToken(urlfetch.Client(c), &cred, r.FormValue("oauth_verifier"))
		if err != nil {
			log.Errorf(c, "%s Error when trying to delete memcached 'secret' key: %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetRequestToken)}
		}

		// get user info
		urlValues := url.Values{}
		urlValues.Set("user_id", values.Get("user_id"))
		resp, err := twitterConfig.Get(urlfetch.Client(c), token, "https://api.twitter.com/1.1/users/show.json", urlValues)
		if err != nil {
			log.Errorf(c, "%s Cannot get user info from twitter. %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetUserInfo)}
		}

		userInfo, err := authhlp.FetchTwitterUserInfo(resp)
		if err != nil {
			log.Errorf(c, "%s Cannot get user info by fetching twitter response. %v", desc, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetUserInfo)}
		}

		if user, err = mdl.SigninUser(w, r, "Username", "", userInfo.Screen_name, userInfo.Name); err != nil {
			log.Errorf(c, "%s Unable to signin user %s. %v", desc, userInfo.Name, err)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to get Google accounts login URL.
func GoogleAccountsLoginURL(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts Login URL Handler:"
	if r.Method == "GET" {
		var url string
		var err error
		url, err = user.LoginURL(c, "/j/auth/google/callback/")
		if err != nil {
			log.Errorf(c, "%s error when getting Google accounts login URL", desc)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsCannotGetGoogleLoginUrl)}
		}

		// return user
		loginData := struct {
			Url string
		}{
			url,
		}

		return templateshlp.RenderJson(w, c, loginData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// Google Authentication Callback
func GoogleAuthCallback(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts Auth Callback Handler:"
	if r.Method == "GET" {
		u := user.Current(c)
		if u == nil {
			log.Errorf(c, "%s user cannot be nil", desc)
			return &helpers.InternalServerError{Err: errors.New("user cannot be nil")}
		}

		http.Redirect(w, r, "http://"+r.Host+"/#/auth/google/callback?auth_token="+u.ID, http.StatusFound)
		return nil
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to get Google accounts user.
func GoogleUser(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	desc := "Google Accounts User Handler:"
	if r.Method == "GET" {
		u := user.Current(c)
		if u == nil {
			log.Errorf(c, "%s user cannot be nil", desc)
			return &helpers.InternalServerError{Err: errors.New("user cannot be nil")}
		}

		if u.ID != r.FormValue("auth_token") {
			log.Errorf(c, "%s Auth token doesn't match user ID", desc)
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsAccessTokenNotValid)}
		}

		userInfo := authhlp.GetUserGoogleInfo(u)

		var user *mdl.User
		var err error
		if user, err = mdl.SigninUser(w, r, "Email", userInfo.Email, userInfo.Name, userInfo.Name); err != nil {
			return &helpers.InternalServerError{Err: errors.New(helpers.ErrorCodeSessionsUnableToSignin)}
		}

		// return user
		userData := struct {
			User *mdl.User
		}{
			user,
		}

		return templateshlp.RenderJson(w, c, userData)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// JSON handler to delete cookie created by Google account
func GoogleDeleteCookie(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	if r.Method == "GET" {
		cookieName := "ACSID"
		if appengine.IsDevAppServer() {
			cookieName = "dev_appserver_login"
		}
		cookie := http.Cookie{Name: cookieName, Path: "/", MaxAge: -1}
		http.SetCookie(w, &cookie)

		return templateshlp.RenderJson(w, c, "Google user has been logged out")
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

func AuthServiceIds(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)

	if r.Method == "GET" {
		data := struct {
			GooglePlusClientId string
			FacebookAppId      string
		}{
			config.GooglePlus.ClientId,
			config.Facebook.AppId,
		}
		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<|endoftext|>


<commit_before>package convox

import (
	"errors"
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
)

// ResourceConvoxSyslog describes the schema for a Convox Syslog Resource resource
func ResourceConvoxSyslog(clientUnpacker ClientUnpacker) *schema.Resource {
	log.Printf("ResourceConvoxSyslog - schema.Resource")
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"rack": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"hostname": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"scheme": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"private": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"url": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
		Create: ResourceConvoxSyslogCreateFactory(clientUnpacker),
		Read:   ResourceConvoxSyslogReadFactory(clientUnpacker),
		Update: ResourceConvoxSyslogUpdateFactory(clientUnpacker),
		Delete: ResourceConvoxSyslogDeleteFactory(clientUnpacker),
	}
}

func formURLString(d *schema.ResourceData) string {
	return fmt.Sprintf("%s://%s:%d", d.Get("scheme"), d.Get("hostname"), d.Get("port"))
}

// ResourceConvoxSyslogCreateFactory builds the Convox Syslog CreateFunc
func ResourceConvoxSyslogCreateFactory(clientUnpacker ClientUnpacker) schema.CreateFunc {
	log.Printf("ResourceConvoxSyslogCreateFactory")

	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("CreateFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error unpacking client in CreateFunc: %s", err.Error())
		}

		options := map[string]string{
			"name": d.Get("name").(string),
			"Url":  formURLString(d),
		}

		if v, ok := d.GetOk("private"); ok {
			options["Private"] = fmt.Sprintf("%v", v)
		}

		log.Printf("[INFO] Calling Convox CreateResource...")
		_, err = c.CreateResource("syslog", options)
		if err != nil {
			return fmt.Errorf("Error calling CreateResource: %s -- %v", err.Error(), options)
		}

		// TODO: probably need to wait here for the status to stabilize. (and in update)

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogReadFactory builds the ReadFunc for the Convox Syslog Resource
func ResourceConvoxSyslogReadFactory(clientUnpacker ClientUnpacker) schema.ReadFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("ReadFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in ReadFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox GetResource(%s)...", name)
		convoxResource, err := c.GetResource(name)
		if err != nil {
			return fmt.Errorf("Error calling GetResource: %s", err.Error())
		}

		d.Set("url", convoxResource.Exports["URL"])

		return nil
	}
}

// ResourceConvoxSyslogUpdateFactory creates the UpdateFunc for the Convox Syslog Resource
func ResourceConvoxSyslogUpdateFactory(clientUnpacker ClientUnpacker) schema.UpdateFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("UpdateFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in UpdateFunc: %s", err.Error())
		}

		options := map[string]string{
			"Url": formURLString(d),
		}

		if v, ok := d.GetOk("private"); ok {
			options["Private"] = fmt.Sprintf("%v", v)
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox UpdateResource(%s, <options>)...", name)
		_, err = c.UpdateResource(name, options)
		if err != nil {
			return fmt.Errorf("Error calling UpdateResource: %s -- %v", err.Error(), options)
		}

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogDeleteFactory builds the DeleteFunc for thw Convox Syslog Resource
func ResourceConvoxSyslogDeleteFactory(clientUnpacker ClientUnpacker) schema.DeleteFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("DeleteFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in DeleteFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox DeleteResource(%s)...", name)
		_, err = c.DeleteResource(name)
		if err != nil {
			return fmt.Errorf("Error calling DeleteResource: %s", err.Error())
		}

		return nil
	}
}
<commit_msg>setID so it is an entity<commit_after>package convox

import (
	"errors"
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
)

// ResourceConvoxSyslog describes the schema for a Convox Syslog Resource resource
func ResourceConvoxSyslog(clientUnpacker ClientUnpacker) *schema.Resource {
	log.Printf("ResourceConvoxSyslog - schema.Resource")
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"rack": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"hostname": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"scheme": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"private": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"url": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
		Create: ResourceConvoxSyslogCreateFactory(clientUnpacker),
		Read:   ResourceConvoxSyslogReadFactory(clientUnpacker),
		Update: ResourceConvoxSyslogUpdateFactory(clientUnpacker),
		Delete: ResourceConvoxSyslogDeleteFactory(clientUnpacker),
	}
}

func formURLString(d *schema.ResourceData) string {
	return fmt.Sprintf("%s://%s:%d", d.Get("scheme"), d.Get("hostname"), d.Get("port"))
}

// ResourceConvoxSyslogCreateFactory builds the Convox Syslog CreateFunc
func ResourceConvoxSyslogCreateFactory(clientUnpacker ClientUnpacker) schema.CreateFunc {
	log.Printf("ResourceConvoxSyslogCreateFactory")

	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("CreateFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error unpacking client in CreateFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		options := map[string]string{
			"name": name,
			"Url":  formURLString(d),
		}

		if v, ok := d.GetOk("private"); ok {
			options["Private"] = fmt.Sprintf("%v", v)
		}

		log.Printf("[INFO] Calling Convox CreateResource...")
		_, err = c.CreateResource("syslog", options)
		if err != nil {
			return fmt.Errorf("Error calling CreateResource: %s -- %v", err.Error(), options)
		}

		d.SetId(name)

		// TODO: probably need to wait here for the status to stabilize. (and in update)

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogReadFactory builds the ReadFunc for the Convox Syslog Resource
func ResourceConvoxSyslogReadFactory(clientUnpacker ClientUnpacker) schema.ReadFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("ReadFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in ReadFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox GetResource(%s)...", name)
		convoxResource, err := c.GetResource(name)
		if err != nil {
			return fmt.Errorf("Error calling GetResource: %s", err.Error())
		}

		d.SetId(name)
		d.Set("url", convoxResource.Exports["URL"])

		return nil
	}
}

// ResourceConvoxSyslogUpdateFactory creates the UpdateFunc for the Convox Syslog Resource
func ResourceConvoxSyslogUpdateFactory(clientUnpacker ClientUnpacker) schema.UpdateFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("UpdateFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in UpdateFunc: %s", err.Error())
		}

		options := map[string]string{
			"Url": formURLString(d),
		}

		if v, ok := d.GetOk("private"); ok {
			options["Private"] = fmt.Sprintf("%v", v)
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox UpdateResource(%s, <options>)...", name)
		_, err = c.UpdateResource(name, options)
		if err != nil {
			return fmt.Errorf("Error calling UpdateResource: %s -- %v", err.Error(), options)
		}

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogDeleteFactory builds the DeleteFunc for thw Convox Syslog Resource
func ResourceConvoxSyslogDeleteFactory(clientUnpacker ClientUnpacker) schema.DeleteFunc {
	return func(d *schema.ResourceData, meta interface{}) error {
		log.Printf("DeleteFunc")

		if clientUnpacker == nil {
			return errors.New("clientUnpacker is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in DeleteFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		log.Printf("[INFO] Calling Convox DeleteResource(%s)...", name)
		_, err = c.DeleteResource(name)
		if err != nil {
			return fmt.Errorf("Error calling DeleteResource: %s", err.Error())
		}

		return nil
	}
}
<|endoftext|>


<commit_before>package humanize

import (
	"testing"
	"time"
)

func checkTime(t *testing.T, expected, got string) {
	if got != expected {
		t.Fatalf("Expected %s, got %s", expected, got)
	}
}

func TestPast(t *testing.T) {

	expected := []string{
		"now",
		"1 second ago",
		"12 seconds ago",
		"30 seconds ago",
		"45 seconds ago",
		"15 minutes ago",
		"2 hours ago",
		"21 hours ago",
		"1 day ago",
		"2 days ago",
		"3 days ago",
		"1 week ago",
		"1 week ago",
		"2 weeks ago",
		"1 month ago",
		"1 year ago",
	}

	i := 0
	now := time.Now().Unix()

	checkTime(t, expected[i], Time(time.Unix(now, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-1, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-12, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-30, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-45, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-15*Minute, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-2*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-21*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-26*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-49*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-3*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-7*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-12*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-15*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-39*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-365*Day, 0)))
}

func TestFuture(t *testing.T) {

	expected := []string{
		"now",
		"1 second from now",
		"12 seconds from now",
		"30 seconds from now",
		"45 seconds from now",
		"15 minutes from now",
		"2 hours from now",
		"21 hours from now",
		"1 day from now",
		"2 days from now",
		"3 days from now",
		"1 week from now",
		"1 week from now",
		"2 weeks from now",
		"1 month from now",
		"1 year from now",
	}

	i := 0
	now := time.Now().Unix()

	checkTime(t, expected[i], Time(time.Unix(now, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+1, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+12, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+30, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+45, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+15*Minute, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+2*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+21*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+26*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+49*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+3*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+7*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+12*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+15*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+39*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+365*Day, 0)))
}
<commit_msg>More time testing.<commit_after>package humanize

import (
	"testing"
	"time"
)

func checkTime(t *testing.T, expected, got string) {
	if got != expected {
		t.Fatalf("Expected %s, got %s", expected, got)
	}
}

func TestPast(t *testing.T) {

	expected := []string{
		"now",
		"1 second ago",
		"12 seconds ago",
		"30 seconds ago",
		"45 seconds ago",
		"1 minute ago",
		"15 minutes ago",
		"1 hour ago",
		"2 hours ago",
		"21 hours ago",
		"1 day ago",
		"2 days ago",
		"3 days ago",
		"1 week ago",
		"1 week ago",
		"2 weeks ago",
		"1 month ago",
		"3 month ago",
		"1 year ago",
	}

	i := 0
	now := time.Now().Unix()

	checkTime(t, expected[i], Time(time.Unix(now, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-1, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-12, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-30, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-45, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-63, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-15*Minute, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-63*Minute, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-2*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-21*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-26*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-49*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-3*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-7*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-12*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-15*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-39*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-99*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now-365*Day, 0)))
}

func TestFuture(t *testing.T) {

	expected := []string{
		"now",
		"1 second from now",
		"12 seconds from now",
		"30 seconds from now",
		"45 seconds from now",
		"15 minutes from now",
		"2 hours from now",
		"21 hours from now",
		"1 day from now",
		"2 days from now",
		"3 days from now",
		"1 week from now",
		"1 week from now",
		"2 weeks from now",
		"1 month from now",
		"1 year from now",
	}

	i := 0
	now := time.Now().Unix()

	checkTime(t, expected[i], Time(time.Unix(now, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+1, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+12, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+30, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+45, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+15*Minute, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+2*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+21*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+26*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+49*Hour, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+3*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+7*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+12*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+15*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+39*Day, 0)))
	i++
	checkTime(t, expected[i], Time(time.Unix(now+365*Day, 0)))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/user"
	"regexp"
	"strings"

	"os/exec"

	"github.com/bullettrain-sh/bullettrain-go-core/car_context"
	"github.com/bullettrain-sh/bullettrain-go-core/car_date"
	"github.com/bullettrain-sh/bullettrain-go-core/car_directory"
	"github.com/bullettrain-sh/bullettrain-go-core/car_os"
	"github.com/bullettrain-sh/bullettrain-go-core/car_status"
	"github.com/bullettrain-sh/bullettrain-go-core/car_time"
	"github.com/bullettrain-sh/bullettrain-go-git"
	"github.com/bullettrain-sh/bullettrain-go-golang"
	"github.com/bullettrain-sh/bullettrain-go-nodejs"
	"github.com/bullettrain-sh/bullettrain-go-php"
	"github.com/bullettrain-sh/bullettrain-go-python"
	"github.com/bullettrain-sh/bullettrain-go-ruby"
	"github.com/mgutz/ansi"
)

func main() {
	if d := os.Getenv("BULLETTRAIN_NO_PAINT"); d == "true" {
		ansi.DisableColors(true)
	}

	// List of cars available for use.
	trailers := carsOrderByTrigger()

	// Create a channel for each car.
	noOfCars := len(trailers) * 2
	chans := make([]chan string, noOfCars)
	for i := range chans {
		chans[i] = make(chan string)
	}

	// Spin off a goroutine for each car.
	var lastSeparator bool
	paintFlipper := flipPaint()
	for j, k := 0, 0; j < noOfCars; j, k = j+2, k+1 {
		// Render car.
		go trailers[k].Render(chans[j])

		// Render separator.
		sep := &separator{}
		var newPaint string
		if newPaint = trailers[k].GetSeparatorPaint(); newPaint == "" {
			lastSeparator = j+2 == noOfCars
			if lastSeparator {
				newPaint = paintFlipper(
					trailers[k].GetPaint(),
					"default:default")
			} else {
				newPaint = paintFlipper(
					trailers[k].GetPaint(),
					trailers[k+1].GetPaint())
			}
		}

		go sep.Render(chans[j+1], newPaint, trailers[k].GetSeparatorSymbol())
	}

	var n bytes.Buffer
	// Gather each goroutine's response through their channels,
	// keeping their order.
	for _, c := range chans {
		n.WriteString(<-c)
	}

	if l := os.Getenv("BULLETTRAIN_CARS_SEPARATE_LINE"); l == "true" {
		n.WriteString("\n")
	}

	n.WriteString(lineEnding())

	if d := os.Getenv("BULLETTRAIN_DEBUG"); d == "true" {
		fmt.Print(n.String())
	} else {
		fmt.Printf("%s", n.String())
	}
}

func pwd() string {
	cmd := exec.Command("pwd", "-P")
	pwd, err := cmd.Output()
	var d string
	if err == nil {
		d = strings.Trim(string(pwd), "\n")
	}

	return d
}

func carsOrderByTrigger() []carRenderer {
	// Cars basic, default order.
	var o []string
	if envOrder := os.Getenv("BULLETTRAIN_CARS"); envOrder == "" {
		o = append(o, "os", "time", "date", "context", "dir", "python", "go", "ruby", "nodejs", "php", "git", "status")
	} else {
		o = strings.Split(strings.TrimSpace(envOrder), " ")
	}

	d := pwd()
	// List of cars to be available for use.
	trailers := map[string]carRenderer{
		"context": &carContext.Context{},
		"date":    &carDate.Date{},
		"dir":     &carDirectory.Directory{Pwd: d},
		"git":     &carGit.Car{Pwd: d},
		"go":      &carGo.Car{Pwd: d},
		"nodejs":  &carNodejs.Car{Pwd: d},
		"os":      &carOs.Os{},
		"php":     &carPhp.Car{Pwd: d},
		"python":  &carPython.Car{Pwd: d},
		"ruby":    &carRuby.Car{Pwd: d},
		"status":  &carStatus.Status{},
		"time":    &carTime.Time{},
	}

	var carsToRender []carRenderer
	for _, car := range o {
		if trailers[car].CanShow() {
			carsToRender = append(carsToRender, trailers[car])
		}
	}

	return carsToRender
}

func lineEnding() string {
	u, e := user.Current()
	if e != nil {
		panic("Can't figure out current username.")
	}

	var l, c string
	if u.Username == "root" {
		if l = os.Getenv("BULLETTRAIN_PROMPT_CHAR_ROOT"); l == "" {
			l = "# "
		}

		if c = os.Getenv("BULLETTRAIN_PROMPT_CHAR_ROOT_PAINT"); c == "" {
			c = "red"
		}
	} else {
		if l = os.Getenv("BULLETTRAIN_PROMPT_CHAR"); l == "" {
			l = "$ "
		}

		if c = os.Getenv("BULLETTRAIN_PROMPT_CHAR_PAINT"); c == "" {
			c = "green"
		}
	}

	return ansi.Color(l, c)
}

// flipPaint flips the FG and BG setup in colour strings of cars for a separator.
// Use it as a closure.
func flipPaint() func(string, string) string {
	// foregroundColor+attributes:backgroundColor+attributes
	colourExp := regexp.MustCompile(`\w*\+?\w*:?(\w*)\+?\w?`)

	flipped := func(currentPaint, nextPaint string) string {
		currentParts := colourExp.FindStringSubmatch(currentPaint)
		nextParts := colourExp.FindStringSubmatch(nextPaint)

		newFg := "default"
		if len(currentParts) == 2 && currentParts[1] != "" {
			newFg = currentParts[1]
		}

		newBg := "default"
		if len(nextParts) == 2 && nextParts[1] != "" {
			newBg = nextParts[1]
		}

		return fmt.Sprintf("%s:%s", newFg, newBg)
	}

	return flipped
}

type carRenderer interface {
	// Render builds and passes the end product of a completely composed car onto
	// the channel.
	Render(out chan<- string)

	// GetPaint returns the calculated end paint string for the car.
	GetPaint() string

	// CanShow decides if this car needs to be displayed.
	CanShow() bool

	// GetSeparatorPaint overrides the Fg/Bg colours of the right hand side
	// separator through ENV variables.
	GetSeparatorPaint() string

	// GetSeparatorSymbol overrides the symbol of the right hand side
	// separator through ENV variables.
	GetSeparatorSymbol() string
}

type separator struct{}

func (s *separator) Render(out chan<- string, paint, symbolOverride string) {
	defer close(out)

	var symbol string
	if symbolOverride != "" {
		symbol = symbolOverride
	} else if symbol = os.Getenv("BULLETTRAIN_SEPARATOR_ICON"); symbol == "" {
		symbol = " "
	}

	out <- ansi.Color(symbol, paint)
}
<commit_msg>Formatting imports. Fixing debug mode output format.<commit_after>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"os/user"
	"regexp"
	"strings"

	"github.com/bullettrain-sh/bullettrain-go-core/car_context"
	"github.com/bullettrain-sh/bullettrain-go-core/car_date"
	"github.com/bullettrain-sh/bullettrain-go-core/car_directory"
	"github.com/bullettrain-sh/bullettrain-go-core/car_os"
	"github.com/bullettrain-sh/bullettrain-go-core/car_status"
	"github.com/bullettrain-sh/bullettrain-go-core/car_time"
	"github.com/bullettrain-sh/bullettrain-go-git"
	"github.com/bullettrain-sh/bullettrain-go-golang"
	"github.com/bullettrain-sh/bullettrain-go-nodejs"
	"github.com/bullettrain-sh/bullettrain-go-php"
	"github.com/bullettrain-sh/bullettrain-go-python"
	"github.com/bullettrain-sh/bullettrain-go-ruby"
	"github.com/mgutz/ansi"
)

func main() {
	if d := os.Getenv("BULLETTRAIN_NO_PAINT"); d == "true" {
		ansi.DisableColors(true)
	}

	// List of cars available for use.
	trailers := carsOrderByTrigger()

	// Create a channel for each car.
	noOfCars := len(trailers) * 2
	chans := make([]chan string, noOfCars)
	for i := range chans {
		chans[i] = make(chan string)
	}

	// Spin off a goroutine for each car.
	var lastSeparator bool
	paintFlipper := flipPaint()
	for j, k := 0, 0; j < noOfCars; j, k = j+2, k+1 {
		// Render car.
		go trailers[k].Render(chans[j])

		// Render separator.
		sep := &separator{}
		var newPaint string
		if newPaint = trailers[k].GetSeparatorPaint(); newPaint == "" {
			lastSeparator = j+2 == noOfCars
			if lastSeparator {
				newPaint = paintFlipper(
					trailers[k].GetPaint(),
					"default:default")
			} else {
				newPaint = paintFlipper(
					trailers[k].GetPaint(),
					trailers[k+1].GetPaint())
			}
		}

		go sep.Render(chans[j+1], newPaint, trailers[k].GetSeparatorSymbol())
	}

	var n bytes.Buffer
	// Gather each goroutine's response through their channels,
	// keeping their order.
	for _, c := range chans {
		n.WriteString(<-c)
	}

	if l := os.Getenv("BULLETTRAIN_CARS_SEPARATE_LINE"); l == "true" {
		n.WriteString("\n")
	}

	n.WriteString(lineEnding())

	if d := os.Getenv("BULLETTRAIN_DEBUG"); d == "true" {
		fmt.Printf("%q", n.String())
	} else {
		fmt.Printf("%s", n.String())
	}
}

func pwd() string {
	cmd := exec.Command("pwd", "-P")
	pwd, err := cmd.Output()
	var d string
	if err == nil {
		d = strings.Trim(string(pwd), "\n")
	}

	return d
}

func carsOrderByTrigger() []carRenderer {
	// Cars basic, default order.
	var o []string
	if envOrder := os.Getenv("BULLETTRAIN_CARS"); envOrder == "" {
		o = append(o, "os", "time", "date", "context", "dir", "python", "go", "ruby", "nodejs", "php", "git", "status")
	} else {
		o = strings.Split(strings.TrimSpace(envOrder), " ")
	}

	d := pwd()
	// List of cars to be available for use.
	trailers := map[string]carRenderer{
		"context": &carContext.Context{},
		"date":    &carDate.Date{},
		"dir":     &carDirectory.Directory{Pwd: d},
		"git":     &carGit.Car{Pwd: d},
		"go":      &carGo.Car{Pwd: d},
		"nodejs":  &carNodejs.Car{Pwd: d},
		"os":      &carOs.Os{},
		"php":     &carPhp.Car{Pwd: d},
		"python":  &carPython.Car{Pwd: d},
		"ruby":    &carRuby.Car{Pwd: d},
		"status":  &carStatus.Status{},
		"time":    &carTime.Time{},
	}

	var carsToRender []carRenderer
	for _, car := range o {
		if trailers[car].CanShow() {
			carsToRender = append(carsToRender, trailers[car])
		}
	}

	return carsToRender
}

func lineEnding() string {
	u, e := user.Current()
	if e != nil {
		panic("Can't figure out current username.")
	}

	var l, c string
	if u.Username == "root" {
		if l = os.Getenv("BULLETTRAIN_PROMPT_CHAR_ROOT"); l == "" {
			l = "# "
		}

		if c = os.Getenv("BULLETTRAIN_PROMPT_CHAR_ROOT_PAINT"); c == "" {
			c = "red"
		}
	} else {
		if l = os.Getenv("BULLETTRAIN_PROMPT_CHAR"); l == "" {
			l = "$ "
		}

		if c = os.Getenv("BULLETTRAIN_PROMPT_CHAR_PAINT"); c == "" {
			c = "green"
		}
	}

	return ansi.Color(l, c)
}

// flipPaint flips the FG and BG setup in colour strings of cars for a separator.
// Use it as a closure.
func flipPaint() func(string, string) string {
	// foregroundColor+attributes:backgroundColor+attributes
	colourExp := regexp.MustCompile(`\w*\+?\w*:?(\w*)\+?\w?`)

	flipped := func(currentPaint, nextPaint string) string {
		currentParts := colourExp.FindStringSubmatch(currentPaint)
		nextParts := colourExp.FindStringSubmatch(nextPaint)

		newFg := "default"
		if len(currentParts) == 2 && currentParts[1] != "" {
			newFg = currentParts[1]
		}

		newBg := "default"
		if len(nextParts) == 2 && nextParts[1] != "" {
			newBg = nextParts[1]
		}

		return fmt.Sprintf("%s:%s", newFg, newBg)
	}

	return flipped
}

type carRenderer interface {
	// Render builds and passes the end product of a completely composed car onto
	// the channel.
	Render(out chan<- string)

	// GetPaint returns the calculated end paint string for the car.
	GetPaint() string

	// CanShow decides if this car needs to be displayed.
	CanShow() bool

	// GetSeparatorPaint overrides the Fg/Bg colours of the right hand side
	// separator through ENV variables.
	GetSeparatorPaint() string

	// GetSeparatorSymbol overrides the symbol of the right hand side
	// separator through ENV variables.
	GetSeparatorSymbol() string
}

type separator struct{}

func (s *separator) Render(out chan<- string, paint, symbolOverride string) {
	defer close(out)

	var symbol string
	if symbolOverride != "" {
		symbol = symbolOverride
	} else if symbol = os.Getenv("BULLETTRAIN_SEPARATOR_ICON"); symbol == "" {
		symbol = " "
	}

	out <- ansi.Color(symbol, paint)
}
<|endoftext|>


<commit_before>package geo_skeleton

import "fmt"

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {
	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return string(self.File)
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return string(self.Table)
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {

	fmt.Println(self.getTable())

	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<commit_msg>fixed geots<commit_after>package geo_skeleton

import "fmt"

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {
	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return string(self.File)
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return string(self.Table)
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {
	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<|endoftext|>


<commit_before>// Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rnd

import "github.com/cpmech/gosl/chk"

// DistType indicates the distribution to which a random variable appears to belong to
type DistType int

const (
	D_Normal    DistType = iota + 1 // normal
	D_Lognormal                     // lognormal
	D_Gumbel                        // Type I Extreme Value
	D_Frechet                       // Type II Extreme Value
)

// VarData implements data defining one random variable
type VarData struct {

	// input
	D DistType // type of distribution
	M float64  // mean
	S float64  // standard deviation

	// input: Frechet
	L float64 // location
	C float64 // scale
	A float64 // shape

	// derived
	distr Distribution // pointer to distribution
}

// Transform transform x into standard normal space
func (o *VarData) Transform(x float64) (y float64, invalid bool) {
	if o.D == D_Normal {
		y = (x - o.M) / o.S
		return
	}
	F := o.distr.Cdf(x)
	if F == 0 || F == 1 { // y = Φ⁻¹(F) → -∞ or +∞
		invalid = true
		return
	}
	y = StdInvPhi(F)
	return
}

// Variables implements a set of random variables
type Variables []*VarData

// Init initialises distributions in Variables
func (o *Variables) Init() (err error) {
	for _, d := range *o {
		d.distr, err = GetDistrib(d.D)
		if err != nil {
			chk.Err("cannot find distribution:\n%v", err)
			return
		}
		err = d.distr.Init(d)
		if err != nil {
			chk.Err("cannot initialise variables:\n%v", err)
			return
		}
	}
	return
}
<commit_msg>transform all variables re-added<commit_after>// Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rnd

import "github.com/cpmech/gosl/chk"

// DistType indicates the distribution to which a random variable appears to belong to
type DistType int

const (
	D_Normal    DistType = iota + 1 // normal
	D_Lognormal                     // lognormal
	D_Gumbel                        // Type I Extreme Value
	D_Frechet                       // Type II Extreme Value
)

// VarData implements data defining one random variable
type VarData struct {

	// input
	D DistType // type of distribution
	M float64  // mean
	S float64  // standard deviation

	// input: Frechet
	L float64 // location
	C float64 // scale
	A float64 // shape

	// derived
	distr Distribution // pointer to distribution
}

// Transform transform x into standard normal space
func (o *VarData) Transform(x float64) (y float64, invalid bool) {
	if o.D == D_Normal {
		y = (x - o.M) / o.S
		return
	}
	F := o.distr.Cdf(x)
	if F == 0 || F == 1 { // y = Φ⁻¹(F) → -∞ or +∞
		invalid = true
		return
	}
	y = StdInvPhi(F)
	return
}

// Variables implements a set of random variables
type Variables []*VarData

// Init initialises distributions in Variables
func (o *Variables) Init() (err error) {
	for _, d := range *o {
		d.distr, err = GetDistrib(d.D)
		if err != nil {
			chk.Err("cannot find distribution:\n%v", err)
			return
		}
		err = d.distr.Init(d)
		if err != nil {
			chk.Err("cannot initialise variables:\n%v", err)
			return
		}
	}
	return
}

// Transform transforms all variables
func (o Variables) Transform(x []float64) (y []float64, invalid bool) {
	y = make([]float64, len(x))
	for i, d := range o {
		y[i], invalid = d.Transform(x[i])
		if invalid {
			return
		}
	}
	return
}
<|endoftext|>


<commit_before>package immortal

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

func TestDaemonNewCtrl(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrl")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	cfg := &Config{
		Cwd:  dir,
		ctrl: true,
	}
	d, err := New(cfg)
	if err != nil {
		t.Error(err)
	}
	f, err := os.Stat(filepath.Join(dir, "supervise/control"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	f, err = os.Stat(filepath.Join(dir, "supervise/ok"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	if _, err = os.Stat(filepath.Join(dir, "supervise/lock")); err != nil {
		t.Error(err)
	}
	expect(t, uint32(0), d.lock)
	expect(t, uint32(0), d.lock_once)
	// test lock
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error: resource temporarily unavailable")
	}
}

func TestDaemonNewCtrlErr(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrlErr")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	os.Chmod(dir, 0000)
	cfg := &Config{
		Cwd:  dir,
		ctrl: true,
	}
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestDaemonNewCtrlCwd(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrlCwd")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	cwd, err := os.Getwd()
	if err != nil {
		t.Error(err)
	}
	defer os.Chdir(cwd)
	if err := os.Chdir(dir); err != nil {
		t.Error(err)
	}
	cfg := &Config{
		ctrl: true,
	}
	d, err := New(cfg)
	if err != nil {
		t.Error(err)
	}
	f, err := os.Stat(filepath.Join(dir, "supervise/control"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	f, err = os.Stat(filepath.Join(dir, "supervise/ok"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	if _, err = os.Stat(filepath.Join(dir, "supervise/lock")); err != nil {
		t.Error(err)
	}
	expect(t, uint32(0), d.lock)
	expect(t, uint32(0), d.lock_once)
	// test lock
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error: resource temporarily unavailable")
	}
}

func TestBadUid(t *testing.T) {
	cfg := &Config{
		command: []string{"--"},
		user:    &user.User{Uid: "uid", Gid: "0"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestBadGid(t *testing.T) {
	cfg := &Config{
		command: []string{"--"},
		user:    &user.User{Uid: "0", Gid: "gid"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestUser(t *testing.T) {
	cfg := &Config{
		command: []string{"go"},
		user:    &user.User{Uid: "0", Gid: "0"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestBadWritePidParent(t *testing.T) {
	var mylog bytes.Buffer
	log.SetOutput(&mylog)
	log.SetFlags(0)
	cfg := &Config{
		command: []string{"go"},
		Pid: Pid{
			Parent: "/dev/null/parent.pid",
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Fatal(err)
	}
	expect(t, "open /dev/null/parent.pid: not a directory", strings.TrimSpace(mylog.String()))
}

func TestBadWritePidChild(t *testing.T) {
	var mylog bytes.Buffer
	log.SetOutput(&mylog)
	log.SetFlags(0)
	cfg := &Config{
		command: []string{"go"},
		Pid: Pid{
			Child: "/dev/null/child.pid",
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Fatal(err)
	}
	expect(t, "open /dev/null/child.pid: not a directory", strings.TrimSpace(mylog.String()))
}

func TestHelperProcessSignalsUDOT(*testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
		return
	}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	select {
	case <-c:
		os.Exit(1)
	case <-time.After(10 * time.Second):
		os.Exit(0)
	default:
		fmt.Println("5D675098-45D7-4089-A72C-3628713EA5BA")
	}
}

func TestSignalsUDOT(t *testing.T) {
	base := filepath.Base(os.Args[0]) // "exec.test"
	dir := filepath.Dir(os.Args[0])   // "/tmp/go-buildNNNN/os/exec/_test"
	if dir == "." {
		t.Skip("skipping; running test at root somehow")
	}
	parentDir := filepath.Dir(dir) // "/tmp/go-buildNNNN/os/exec"
	dirBase := filepath.Base(dir)  // "_test"
	if dirBase == "." {
		t.Skipf("skipping; unexpected shallow dir of %q", dir)
	}
	tmpfile, err := ioutil.TempFile("", "TestLogFile")
	if err != nil {
		t.Error(err)
	}
	defer os.Remove(tmpfile.Name()) // clean up
	cfg := &Config{
		Env:     map[string]string{"GO_WANT_HELPER_PROCESS": "1"},
		command: []string{filepath.Join(dirBase, base), "-test.run=TestHelperProcessSignalsUDOT", "--"},
		Cwd:     parentDir,
		Pid: Pid{
			Parent: filepath.Join(parentDir, "parent.pid"),
			Child:  filepath.Join(parentDir, "child.pid"),
		},
		Log: Log{
			File: tmpfile.Name(),
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}

	np := NewProcess(cfg)
	expect(t, 0, np.Pid())
	p, err := d.Run(np)
	if err != nil {
		t.Error(err)
	}

	sup := &Sup{p}

	// check pids
	if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "parent.pid")); err != nil {
		t.Error(err)
	} else {
		expect(t, os.Getpid(), pid)
	}
	if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "child.pid")); err != nil {
		t.Error(err, pid)
	} else {
		expect(t, p.Pid(), pid)
	}

	// test "k", process should restart and get a new pid
	t.Log("testing k")
	current_pid := p.Pid()
	sup.HandleSignals("k", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: killed", err.Error())
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	if current_pid == p.Pid() {
		t.Fatalf("Expecting a new pid")
	}

	// test "d", (keep it down and don't restart)
	t.Log("testing d")
	sup.HandleSignals("d", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: terminated", err.Error())
	np = NewProcess(cfg)
	p, err = d.Run(np)
	if err == nil {
		t.Error("Expecting an error")
	} else {
		close(np.quit)
	}

	// test "u"
	t.Log("testing up")
	sup.HandleSignals("u", d)
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}

	// test "once", process should not restart after going down
	t.Log("testing once")
	sup.HandleSignals("o", d)
	sup.HandleSignals("k", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: killed", err.Error())
	np = NewProcess(cfg)
	p, err = d.Run(np)
	if err == nil {
		t.Error("Expecting an error")
	} else {
		close(np.quit)
	}
	sup = &Sup{p}

	// test "u"
	t.Log("testing u")
	sup.HandleSignals("u", d)
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	old_pid := p.Pid()

	// test "t"
	t.Log("testing t")
	sup.HandleSignals("t", d)
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: terminated", err.Error())
	// restart to get new pid
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	if old_pid == p.Pid() {
		t.Fatal("Expecting a new pid")
	}

	time.Sleep(time.Second)

	sup.HandleSignals("kill", d)
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: killed", err.Error())

	// test log content
	t.Log("testing logfile")
	content, err := ioutil.ReadFile(tmpfile.Name())
	if err != nil {
		t.Fatal(err)
	}
	lines := strings.Split(string(content), "\n")
	expect(t, true, strings.HasSuffix(lines[0], "5D675098-45D7-4089-A72C-3628713EA5BA"))
}
<commit_msg>fixed test expecting(t causing issues)<commit_after>package immortal

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

func TestDaemonNewCtrl(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrl")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	cfg := &Config{
		Cwd:  dir,
		ctrl: true,
	}
	d, err := New(cfg)
	if err != nil {
		t.Error(err)
	}
	f, err := os.Stat(filepath.Join(dir, "supervise/control"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	f, err = os.Stat(filepath.Join(dir, "supervise/ok"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	if _, err = os.Stat(filepath.Join(dir, "supervise/lock")); err != nil {
		t.Error(err)
	}
	expect(t, uint32(0), d.lock)
	expect(t, uint32(0), d.lock_once)
	// test lock
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error: resource temporarily unavailable")
	}
}

func TestDaemonNewCtrlErr(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrlErr")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	os.Chmod(dir, 0000)
	cfg := &Config{
		Cwd:  dir,
		ctrl: true,
	}
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestDaemonNewCtrlCwd(t *testing.T) {
	dir, err := ioutil.TempDir("", "TestDaemonNewCtrlCwd")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir)
	cwd, err := os.Getwd()
	if err != nil {
		t.Error(err)
	}
	defer os.Chdir(cwd)
	if err := os.Chdir(dir); err != nil {
		t.Error(err)
	}
	cfg := &Config{
		ctrl: true,
	}
	d, err := New(cfg)
	if err != nil {
		t.Error(err)
	}
	f, err := os.Stat(filepath.Join(dir, "supervise/control"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	f, err = os.Stat(filepath.Join(dir, "supervise/ok"))
	if f.Mode()&os.ModeType != os.ModeNamedPipe {
		t.Error("Expecting os.ModeNamePipe")
	}
	if _, err = os.Stat(filepath.Join(dir, "supervise/lock")); err != nil {
		t.Error(err)
	}
	expect(t, uint32(0), d.lock)
	expect(t, uint32(0), d.lock_once)
	// test lock
	_, err = New(cfg)
	if err == nil {
		t.Error("Expecting error: resource temporarily unavailable")
	}
}

func TestBadUid(t *testing.T) {
	cfg := &Config{
		command: []string{"--"},
		user:    &user.User{Uid: "uid", Gid: "0"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestBadGid(t *testing.T) {
	cfg := &Config{
		command: []string{"--"},
		user:    &user.User{Uid: "0", Gid: "gid"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestUser(t *testing.T) {
	cfg := &Config{
		command: []string{"go"},
		user:    &user.User{Uid: "0", Gid: "0"},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err == nil {
		t.Error("Expecting error")
	}
}

func TestBadWritePidParent(t *testing.T) {
	var mylog bytes.Buffer
	log.SetOutput(&mylog)
	log.SetFlags(0)
	cfg := &Config{
		command: []string{"go"},
		Pid: Pid{
			Parent: "/dev/null/parent.pid",
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Fatal(err)
	}
	expect(t, "open /dev/null/parent.pid: not a directory", strings.TrimSpace(mylog.String()))
}

func TestBadWritePidChild(t *testing.T) {
	var mylog bytes.Buffer
	log.SetOutput(&mylog)
	log.SetFlags(0)
	cfg := &Config{
		command: []string{"go"},
		Pid: Pid{
			Child: "/dev/null/child.pid",
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}
	_, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Fatal(err)
	}
	expect(t, "open /dev/null/child.pid: not a directory", strings.TrimSpace(mylog.String()))
}

func TestHelperProcessSignalsUDOT(*testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
		return
	}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	select {
	case <-c:
		os.Exit(1)
	case <-time.After(10 * time.Second):
		os.Exit(0)
	default:
		fmt.Println("5D675098-45D7-4089-A72C-3628713EA5BA")
	}
}

func TestSignalsUDOT(t *testing.T) {
	base := filepath.Base(os.Args[0]) // "exec.test"
	dir := filepath.Dir(os.Args[0])   // "/tmp/go-buildNNNN/os/exec/_test"
	if dir == "." {
		t.Skip("skipping; running test at root somehow")
	}
	parentDir := filepath.Dir(dir) // "/tmp/go-buildNNNN/os/exec"
	dirBase := filepath.Base(dir)  // "_test"
	if dirBase == "." {
		t.Skipf("skipping; unexpected shallow dir of %q", dir)
	}
	tmpfile, err := ioutil.TempFile("", "TestLogFile")
	if err != nil {
		t.Error(err)
	}
	defer os.Remove(tmpfile.Name()) // clean up
	cfg := &Config{
		Env:     map[string]string{"GO_WANT_HELPER_PROCESS": "1"},
		command: []string{filepath.Join(dirBase, base), "-test.run=TestHelperProcessSignalsUDOT", "--"},
		Cwd:     parentDir,
		Pid: Pid{
			Parent: filepath.Join(parentDir, "parent.pid"),
			Child:  filepath.Join(parentDir, "child.pid"),
		},
		Log: Log{
			File: tmpfile.Name(),
		},
	}
	d, err := New(cfg)
	if err != nil {
		t.Fatal(err)
	}

	np := NewProcess(cfg)
	expect(t, 0, np.Pid())
	p, err := d.Run(np)
	if err != nil {
		t.Error(err)
	}

	sup := &Sup{p}

	// check pids
	if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "parent.pid")); err != nil {
		t.Error(err)
	} else {
		expect(t, os.Getpid(), pid)
	}
	if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "child.pid")); err != nil {
		t.Error(err, pid)
	} else {
		expect(t, p.Pid(), pid)
	}

	// test "k", process should restart and get a new pid
	t.Log("testing k")
	current_pid := p.Pid()
	sup.HandleSignals("k", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: killed", err.Error())
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	if current_pid == p.Pid() {
		t.Fatalf("Expecting a new pid")
	}

	// test "d", (keep it down and don't restart)
	t.Log("testing d")
	sup.HandleSignals("d", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: terminated", err.Error())
	np = NewProcess(cfg)
	p, err = d.Run(np)
	if err == nil {
		t.Error("Expecting an error")
	} else {
		close(np.quit)
	}

	// test "u"
	t.Log("testing up")
	sup.HandleSignals("u", d)
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}

	// test "once", process should not restart after going down
	t.Log("testing once")
	sup.HandleSignals("o", d)
	sup.HandleSignals("k", d)
	// wait for process to finish
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: killed", err.Error())
	np = NewProcess(cfg)
	p, err = d.Run(np)
	if err == nil {
		t.Error("Expecting an error")
	} else {
		close(np.quit)
	}
	sup = &Sup{p}

	// test "u"
	t.Log("testing u")
	sup.HandleSignals("u", d)
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	old_pid := p.Pid()

	// test "t"
	t.Log("testing t")
	sup.HandleSignals("t", d)
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)
	expect(t, "signal: terminated", err.Error())
	// restart to get new pid
	p, err = d.Run(NewProcess(cfg))
	if err != nil {
		t.Error(err)
	}
	sup = &Sup{p}
	if old_pid == p.Pid() {
		t.Fatal("Expecting a new pid")
	}

	time.Sleep(time.Second)

	sup.HandleSignals("kill", d)
	err = <-p.errch
	atomic.StoreUint32(&d.lock, d.lock_once)

	// test log content
	t.Log("testing logfile")
	content, err := ioutil.ReadFile(tmpfile.Name())
	if err != nil {
		t.Fatal(err)
	}
	lines := strings.Split(string(content), "\n")
	expect(t, true, strings.HasSuffix(lines[0], "5D675098-45D7-4089-A72C-3628713EA5BA"))
}
<|endoftext|>


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

package network

import (
	"fmt"

	"github.com/softlayer/softlayer-go/datatypes"
	"github.com/softlayer/softlayer-go/services"
	"github.com/softlayer/softlayer-go/session"
)

// GetNadcLbVipByName Get a virtual ip address by name attached to a load balancer
// appliance like the Netscaler VPX. In the case of some load balancer appliances
// looking up the virtual ip address by name is necessary since they don't get
// assigned an id.
func GetNadcLbVipByName(sess *session.Session, nadcId int, vipName string, mask ...string) (*datatypes.Network_LoadBalancer_VirtualIpAddress, error) {
	service := services.GetNetworkApplicationDeliveryControllerService(sess)

	service = service.
		Id(nadcId)

	if len(mask) > 0 {
		service = service.Mask(mask[0])
	}

	vips, err := service.GetLoadBalancers()

	if err != nil {
		return nil, fmt.Errorf("Error getting NADC load balancers: %s", err)
	}

	for _, vip := range vips {
		if *vip.Name == vipName {
			return &vip, nil
		}
	}

	return nil, fmt.Errorf("Could not find any VIPs for NADC %d matching name %s", nadcId, vipName)
}

// GetNadcLbVipServiceByName Get a load balancer service by name attached to a load balancer
// appliance like the Netscaler VPX. In the case of some load balancer appliances
// looking up the virtual ip address by name is necessary since they don't get
// assigned an id.
func GetNadcLbVipServiceByName(
	sess *session.Session, nadcId int, vipName string, serviceName string, mask ...string,
) (*datatypes.Network_LoadBalancer_Service, error) {
	vipMask := "id,name,services[name,destinationIpAddress,destinationPort,weight,healthCheck,connectionLimit]"

	if len(mask) != 0 {
		vipMask = mask[0]
	}

	vip, err := GetNadcLbVipByName(sess, nadcId, vipName, vipMask)
	if err != nil {
		return nil, err
	}

	for _, service := range vip.Services {
		if *service.Name == serviceName {
			return &service, nil
		}
	}

	return nil, fmt.Errorf(
		"Could not find service %s in VIP %s for load balancer %d",
		serviceName, vipName, nadcId)
}
<commit_msg>Moving GetOsTypeByName to softlayer-go<commit_after>/**
 * Copyright 2016 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package network

import (
	"fmt"

	"github.com/softlayer/softlayer-go/datatypes"
	"github.com/softlayer/softlayer-go/filter"
	"github.com/softlayer/softlayer-go/services"
	"github.com/softlayer/softlayer-go/session"
)

// GetNadcLbVipByName Get a virtual ip address by name attached to a load balancer
// appliance like the Netscaler VPX. In the case of some load balancer appliances
// looking up the virtual ip address by name is necessary since they don't get
// assigned an id.
func GetNadcLbVipByName(sess *session.Session, nadcId int, vipName string, mask ...string) (*datatypes.Network_LoadBalancer_VirtualIpAddress, error) {
	service := services.GetNetworkApplicationDeliveryControllerService(sess)

	service = service.
		Id(nadcId)

	if len(mask) > 0 {
		service = service.Mask(mask[0])
	}

	vips, err := service.GetLoadBalancers()

	if err != nil {
		return nil, fmt.Errorf("Error getting NADC load balancers: %s", err)
	}

	for _, vip := range vips {
		if *vip.Name == vipName {
			return &vip, nil
		}
	}

	return nil, fmt.Errorf("Could not find any VIPs for NADC %d matching name %s", nadcId, vipName)
}

// GetNadcLbVipServiceByName Get a load balancer service by name attached to a load balancer
// appliance like the Netscaler VPX. In the case of some load balancer appliances
// looking up the virtual ip address by name is necessary since they don't get
// assigned an id.
func GetNadcLbVipServiceByName(
	sess *session.Session, nadcId int, vipName string, serviceName string, mask ...string,
) (*datatypes.Network_LoadBalancer_Service, error) {
	vipMask := "id,name,services[name,destinationIpAddress,destinationPort,weight,healthCheck,connectionLimit]"

	if len(mask) != 0 {
		vipMask = mask[0]
	}

	vip, err := GetNadcLbVipByName(sess, nadcId, vipName, vipMask)
	if err != nil {
		return nil, err
	}

	for _, service := range vip.Services {
		if *service.Name == serviceName {
			return &service, nil
		}
	}

	return nil, fmt.Errorf(
		"Could not find service %s in VIP %s for load balancer %d",
		serviceName, vipName, nadcId)
}

// GetOsTypeByName retrieves an object of type SoftLayer_Network_Storage_Iscsi_OS_Type.
// To order block storage, OS type is required as a mandatory input.
// GetOsTypeByName helps in getting the OS id and keyName
// Examples:
// id:6   name: Hyper-V  keyName: HYPER_V
// id:12  name: Linux    keyName: LINUX
// id:22  name: VMWare   keyName: VMWARE
// id:30  name: Xen      keyName: XEN
func GetOsTypeByName(sess *session.Session, name string, args ...interface{}) (datatypes.Network_Storage_Iscsi_OS_Type, error) {
	var mask string
	if len(args) > 0 {
		mask = args[0].(string)
	}

	osTypes, err := services.GetNetworkStorageIscsiOSTypeService(sess).
		Mask(mask).
		Filter(filter.New(filter.Path("name").Eq(name)).Build()).
		GetAllObjects()

	if err != nil {
		return datatypes.Network_Storage_Iscsi_OS_Type{}, err
	}

	// An empty filtered result set does not raise an error
	if len(osTypes) == 0 {
		return datatypes.Network_Storage_Iscsi_OS_Type{}, fmt.Errorf("No OS type found with name of %s", name)
	}

	return osTypes[0], nil
}
<|endoftext|>