<commit_before>// Big monolithic binding file.
// Binds a ton of things.

package middleware

import (
	"bufio"
	"crypto/tls"
	"encoding/base64"
	"errors"
	"fmt"
	"github.com/DeedleFake/Go-PhysicsFS/physfs"
	"github.com/carbonsrv/carbon/modules/glue"
	"github.com/carbonsrv/carbon/modules/helpers"
	"github.com/carbonsrv/carbon/modules/scheduler"
	"github.com/carbonsrv/carbon/modules/static"
	"github.com/fzzy/radix/redis"
	"github.com/gin-gonic/gin"
	"github.com/pmylund/go-cache"
	"github.com/shurcooL/github_flavored_markdown"
	"github.com/vifino/contrib/gzip"
	"github.com/vifino/golua/lua"
	"github.com/vifino/luar"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"time"
)

// Vars
var webroot string

func Bind(L *lua.State, root string) {
	webroot = root

	luar.Register(L, "var", luar.Map{ // Vars
		"root": root,
	})

	BindCarbon(L)
	BindMiddleware(L)
	BindRedis(L)
	BindKVStore(L)
	BindPhysFS(L)
	BindIOEnhancements(L)
	BindOSEnhancements(L)
	BindThread(L)
	BindNet(L)
	BindConversions(L)
	BindComs(L)
	BindMarkdown(L)
	BindOther(L)
}

func BindCarbon(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Carbon specific API
		"glue": glue.GetGlue,
	})
}

func BindEngine(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{
		"_gin_new": gin.New,
	})
}

func BindMiddleware(L *lua.State) {
	luar.Register(L, "mw", luar.Map{
		// Essentials
		"Logger":   gin.Logger,
		"Recovery": gin.Recovery,

		// Lua related stuff
		"Lua":       Lua,
		"DLR_NS":    DLR_NS,
		"DLR_RUS":   DLR_RUS,
		"DLRWS_NS":  DLRWS_NS,
		"DLRWS_RUS": DLRWS_RUS,

		// Custom sub-routers.
		"ExtRoute": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return ExtRoute(newplan)
		}),
		"VHOST": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return VHOST(newplan)
		}),
		"VHOST_Middleware": (func(plan map[string]interface{}) gin.HandlerFunc {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(gin.HandlerFunc)
			}
			return VHOST_Middleware(newplan)
		}),

		// To run or not to run, that is the question!
		"if_regex":       If_Regexp,
		"if_written":     If_Written,
		"if_status":      If_Status,
		"if_not_regex":   If_Not_Regexp,
		"if_not_written": If_Not_Written,
		"if_not_status":  If_Not_Status,

		// Modification stuff.
		"GZip": func() func(*gin.Context) {
			return gzip.Gzip(gzip.DefaultCompression)
		},

		// Basic
		"Echo":     EchoHTML,
		"EchoText": Echo,
	})
	luar.Register(L, "carbon", luar.Map{
		"_mw_CGI":         CGI,         // Run an CGI App!
		"_mw_CGI_Dynamic": CGI_Dynamic, // Run CGI Apps based on path!
		"_mw_combine": (func(middlewares []interface{}) func(*gin.Context) { // Combine routes, doesn't properly route like middleware or anything.
			newmiddlewares := make([]func(*gin.Context), len(middlewares))
			for k, v := range middlewares {
				newmiddlewares[k] = v.(func(*gin.Context))
			}
			return Combine(newmiddlewares)
		}),
	})
	L.DoString(glue.RouteGlue())
}
func BindStatic(L *lua.State, cfe *cache.Cache) {
	luar.Register(L, "carbon", luar.Map{
		"_staticserve": (func(path, prefix string) func(*gin.Context) {
			return staticServe.ServeCached(prefix, staticServe.PhysFS(path, prefix, true, true), cfe)
		}),
	})
}

func BindPhysFS(L *lua.State) {
	luar.Register(L, "fs", luar.Map{ // PhysFS
		"mount":       physfs.Mount,
		"exits":       physfs.Exists,
		"getFS":       physfs.FileSystem,
		"mkdir":       physfs.Mkdir,
		"umount":      physfs.RemoveFromSearchPath,
		"delete":      physfs.Delete,
		"setWriteDir": physfs.SetWriteDir,
		"getWriteDir": physfs.GetWriteDir,
	})
}

func BindIOEnhancements(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Small enhancements to the io stuff.
		"_io_list": (func(path string) ([]string, error) {
			files, err := ioutil.ReadDir(path)
			if err != nil {
				return make([]string, 1), err
			} else {
				list := make([]string, len(files))
				for i := range files {
					list[i] = files[i].Name()
				}
				return list, nil
			}
		}),
		"_io_glob": filepath.Glob,
		"_io_modtime": (func(path string) (int, error) {
			info, err := os.Stat(path)
			if err != nil {
				return -1, err
			} else {
				return int(info.ModTime().UTC().Unix()), nil
			}
		}),
	})
}

func BindOSEnhancements(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Small enhancements to the io stuff.
		"_os_exists": (func(path string) bool {
			if _, err := os.Stat(path); err == nil {
				return true
			} else {
				return false
			}
		}),
		"_os_sleep": (func(secs int64) {
			time.Sleep(time.Duration(secs) * time.Second)
		}),
		"_os_chdir":   os.Chdir,
		"_os_abspath": filepath.Abs,
		"_os_pwd":     os.Getwd,
	})
}

func BindRedis(L *lua.State) {
	luar.Register(L, "redis", luar.Map{
		"connectTimeout": (func(host string, timeout int) (*redis.Client, error) {
			return redis.DialTimeout("tcp", host, time.Duration(timeout)*time.Second)
		}),
		"connect": (func(host string) (*redis.Client, error) {
			return redis.Dial("tcp", host)
		}),
	})
}

func BindKVStore(L *lua.State) { // Thread safe Key Value Store that doesn't persist.
	luar.Register(L, "kvstore", luar.Map{
		"_set": (func(k string, v interface{}) {
			kvstore.Set(k, v, -1)
		}),
		"_del": (func(k string) {
			kvstore.Delete(k)
		}),
		"_get": (func(k string) interface{} {
			res, found := kvstore.Get(k)
			if found {
				return res
			} else {
				return nil
			}
		}),
		"_inc": (func(k string, n int64) error {
			return kvstore.Increment(k, n)
		}),
		"_dec": (func(k string, n int64) error {
			return kvstore.Decrement(k, n)
		}),
	})
}

func BindThread(L *lua.State) {
	luar.Register(L, "thread", luar.Map{
		"_spawn": (func(bcode string, dobind bool, vals map[string]interface{}, buffer int) (chan interface{}, error) {
			var ch chan interface{}
			if buffer == -1 {
				ch = make(chan interface{})
			} else {
				ch = make(chan interface{}, buffer)
			}

			L := luar.Init()
			Bind(L, webroot)
			err := L.DoString(glue.MainGlue())
			if err != nil {
				panic(err)
			}

			luar.Register(L, "", luar.Map{
				"threadcom": ch,
			})

			if dobind {
				luar.Register(L, "", vals)
			}

			if L.LoadBuffer(bcode, len(bcode), "thread") != 0 {
				return make(chan interface{}), errors.New(L.ToString(-1))
			}

			scheduler.Add(func() {
				if L.Pcall(0, 0, 0) != 0 { // != 0 means error in execution
					fmt.Println("thread error: " + L.ToString(-1))
				}
			})
			return ch, nil
		}),
	})
}

func BindComs(L *lua.State) {
	luar.Register(L, "com", luar.Map{
		"create": (func() chan interface{} {
			return make(chan interface{})
		}),
		"createBuffered": (func(buffer int) chan interface{} {
			return make(chan interface{}, buffer)
		}),
		"receive": (func(c chan interface{}) interface{} {
			return <-c
		}),
		"try_receive": (func(c chan interface{}) interface{} {
			select {
			case msg := <-c:
				return msg
			default:
				return nil
			}
		}),
		"send": (func(c chan interface{}, val interface{}) bool {
			c <- val
			return true
		}),
		"try_send": (func(c chan interface{}, val interface{}) bool {
			select {
			case c <- val:
				return true
			default:
				return false
			}
		}),
		"size": (func(c chan interface{}) int {
			return len(c)
		}),
		"cap": (func(c chan interface{}) int {
			return cap(c)
		}),
		"pipe": (func(a, b chan interface{}) {
			for {
				b <- <-a
			}
		}),
		"pipe_background": (func(a, b chan interface{}) {
			scheduler.Add(func() {
				for {
					b <- <-a
				}
			})
		}),
	})
}

func BindNet(L *lua.State) {
	luar.Register(L, "net", luar.Map{
		"dial": net.Dial,
		"dial_tls": func(proto, addr string) (net.Conn, error) {
			config := tls.Config{InsecureSkipVerify: true} // Because I'm not gonna bother with auth.
			return tls.Dial(proto, addr, &config)
		},
		"write": (func(con interface{}, str string) {
			fmt.Fprintf(con.(net.Conn), str)
		}),
		"readline": (func(con interface{}) (string, error) {
			return bufio.NewReader(con.(net.Conn)).ReadString('\n')
		}),
		"pipe_conn": (func(con interface{}, input, output chan interface{}) {
			go func() {
				reader := bufio.NewReader(con.(net.Conn))
				for {
					line, _ := reader.ReadString('\n')
					output <- line
				}
			}()
			for {
				line := <-input
				fmt.Fprintf(con.(net.Conn), line.(string))
			}
		}),
		"pipe_conn_background": (func(con interface{}, input, output chan interface{}) {
			scheduler.Add(func() {
				reader := bufio.NewReader(con.(net.Conn))
				for {
					line, _ := reader.ReadString('\n')
					output <- line
				}
			})
			scheduler.Add(func() {
				for {
					line := <-input
					fmt.Fprintf(con.(net.Conn), line.(string))
				}
			})
		}),
	})
}

func BindConversions(L *lua.State) {
	luar.Register(L, "convert", luar.Map{
		"stringtocharslice": (func(x string) []byte {
			return []byte(x)
		}),
		"charslicetostring": (func(x []byte) string {
			return string(x)
		}),
	})
}

func BindContext(L *lua.State, context *gin.Context) {
	luar.Register(L, "", luar.Map{
		"context": context,
		"req":     context.Request,

		"host":   context.Request.URL.Host,
		"path":   context.Request.URL.Path,
		"scheme": context.Request.URL.Scheme,
	})
	luar.Register(L, "carbon", luar.Map{
		"_header_set": context.Header,
		"_header_get": context.Request.Header.Get,
		"_paramfunc":  context.Param,
		"_formfunc":   context.PostForm,
		"_queryfunc":  context.Query,
	})
}

func BindEncoding(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{
		"_enc_base64_enc": (func(str string) string {
			return base64.StdEncoding.EncodeToString([]byte(str))
		}),
		"_enc_base64_dec": (func(str string, err error) string {
			data, err := base64.StdEncoding.DecodeString(str)
			return string(data), err
		}),
	})
}

func BindMarkdown(L *lua.State) {
	luar.Register(L, "markdown", luar.Map{
		"github": (func(source string) string {
			return string(github_flavored_markdown.Markdown([]byte(source)))
		}),
	})
}

func BindOther(L *lua.State) {
	luar.Register(L, "", luar.Map{
		"unixtime": (func() int {
			return int(time.Now().UTC().Unix())
		}),
		"regexp": regexp.Compile,
	})
	luar.Register(L, "carbon", luar.Map{
		"_syntaxhl": helpers.SyntaxHL,
	})
}
<commit_msg>If only I wouldn't derp so badly.<commit_after>// Big monolithic binding file.
// Binds a ton of things.

package middleware

import (
	"bufio"
	"crypto/tls"
	"encoding/base64"
	"errors"
	"fmt"
	"github.com/DeedleFake/Go-PhysicsFS/physfs"
	"github.com/carbonsrv/carbon/modules/glue"
	"github.com/carbonsrv/carbon/modules/helpers"
	"github.com/carbonsrv/carbon/modules/scheduler"
	"github.com/carbonsrv/carbon/modules/static"
	"github.com/fzzy/radix/redis"
	"github.com/gin-gonic/gin"
	"github.com/pmylund/go-cache"
	"github.com/shurcooL/github_flavored_markdown"
	"github.com/vifino/contrib/gzip"
	"github.com/vifino/golua/lua"
	"github.com/vifino/luar"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"time"
)

// Vars
var webroot string

func Bind(L *lua.State, root string) {
	webroot = root

	luar.Register(L, "var", luar.Map{ // Vars
		"root": root,
	})

	BindCarbon(L)
	BindMiddleware(L)
	BindRedis(L)
	BindKVStore(L)
	BindPhysFS(L)
	BindIOEnhancements(L)
	BindOSEnhancements(L)
	BindThread(L)
	BindNet(L)
	BindConversions(L)
	BindComs(L)
	BindMarkdown(L)
	BindOther(L)
}

func BindCarbon(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Carbon specific API
		"glue": glue.GetGlue,
	})
}

func BindEngine(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{
		"_gin_new": gin.New,
	})
}

func BindMiddleware(L *lua.State) {
	luar.Register(L, "mw", luar.Map{
		// Essentials
		"Logger":   gin.Logger,
		"Recovery": gin.Recovery,

		// Lua related stuff
		"Lua":       Lua,
		"DLR_NS":    DLR_NS,
		"DLR_RUS":   DLR_RUS,
		"DLRWS_NS":  DLRWS_NS,
		"DLRWS_RUS": DLRWS_RUS,

		// Custom sub-routers.
		"ExtRoute": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return ExtRoute(newplan)
		}),
		"VHOST": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return VHOST(newplan)
		}),
		"VHOST_Middleware": (func(plan map[string]interface{}) gin.HandlerFunc {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(gin.HandlerFunc)
			}
			return VHOST_Middleware(newplan)
		}),

		// To run or not to run, that is the question!
		"if_regex":       If_Regexp,
		"if_written":     If_Written,
		"if_status":      If_Status,
		"if_not_regex":   If_Not_Regexp,
		"if_not_written": If_Not_Written,
		"if_not_status":  If_Not_Status,

		// Modification stuff.
		"GZip": func() func(*gin.Context) {
			return gzip.Gzip(gzip.DefaultCompression)
		},

		// Basic
		"Echo":     EchoHTML,
		"EchoText": Echo,
	})
	luar.Register(L, "carbon", luar.Map{
		"_mw_CGI":         CGI,         // Run an CGI App!
		"_mw_CGI_Dynamic": CGI_Dynamic, // Run CGI Apps based on path!
		"_mw_combine": (func(middlewares []interface{}) func(*gin.Context) { // Combine routes, doesn't properly route like middleware or anything.
			newmiddlewares := make([]func(*gin.Context), len(middlewares))
			for k, v := range middlewares {
				newmiddlewares[k] = v.(func(*gin.Context))
			}
			return Combine(newmiddlewares)
		}),
	})
	L.DoString(glue.RouteGlue())
}
func BindStatic(L *lua.State, cfe *cache.Cache) {
	luar.Register(L, "carbon", luar.Map{
		"_staticserve": (func(path, prefix string) func(*gin.Context) {
			return staticServe.ServeCached(prefix, staticServe.PhysFS(path, prefix, true, true), cfe)
		}),
	})
}

func BindPhysFS(L *lua.State) {
	luar.Register(L, "fs", luar.Map{ // PhysFS
		"mount":       physfs.Mount,
		"exits":       physfs.Exists,
		"getFS":       physfs.FileSystem,
		"mkdir":       physfs.Mkdir,
		"umount":      physfs.RemoveFromSearchPath,
		"delete":      physfs.Delete,
		"setWriteDir": physfs.SetWriteDir,
		"getWriteDir": physfs.GetWriteDir,
	})
}

func BindIOEnhancements(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Small enhancements to the io stuff.
		"_io_list": (func(path string) ([]string, error) {
			files, err := ioutil.ReadDir(path)
			if err != nil {
				return make([]string, 1), err
			} else {
				list := make([]string, len(files))
				for i := range files {
					list[i] = files[i].Name()
				}
				return list, nil
			}
		}),
		"_io_glob": filepath.Glob,
		"_io_modtime": (func(path string) (int, error) {
			info, err := os.Stat(path)
			if err != nil {
				return -1, err
			} else {
				return int(info.ModTime().UTC().Unix()), nil
			}
		}),
	})
}

func BindOSEnhancements(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{ // Small enhancements to the io stuff.
		"_os_exists": (func(path string) bool {
			if _, err := os.Stat(path); err == nil {
				return true
			} else {
				return false
			}
		}),
		"_os_sleep": (func(secs int64) {
			time.Sleep(time.Duration(secs) * time.Second)
		}),
		"_os_chdir":   os.Chdir,
		"_os_abspath": filepath.Abs,
		"_os_pwd":     os.Getwd,
	})
}

func BindRedis(L *lua.State) {
	luar.Register(L, "redis", luar.Map{
		"connectTimeout": (func(host string, timeout int) (*redis.Client, error) {
			return redis.DialTimeout("tcp", host, time.Duration(timeout)*time.Second)
		}),
		"connect": (func(host string) (*redis.Client, error) {
			return redis.Dial("tcp", host)
		}),
	})
}

func BindKVStore(L *lua.State) { // Thread safe Key Value Store that doesn't persist.
	luar.Register(L, "kvstore", luar.Map{
		"_set": (func(k string, v interface{}) {
			kvstore.Set(k, v, -1)
		}),
		"_del": (func(k string) {
			kvstore.Delete(k)
		}),
		"_get": (func(k string) interface{} {
			res, found := kvstore.Get(k)
			if found {
				return res
			} else {
				return nil
			}
		}),
		"_inc": (func(k string, n int64) error {
			return kvstore.Increment(k, n)
		}),
		"_dec": (func(k string, n int64) error {
			return kvstore.Decrement(k, n)
		}),
	})
}

func BindThread(L *lua.State) {
	luar.Register(L, "thread", luar.Map{
		"_spawn": (func(bcode string, dobind bool, vals map[string]interface{}, buffer int) (chan interface{}, error) {
			var ch chan interface{}
			if buffer == -1 {
				ch = make(chan interface{})
			} else {
				ch = make(chan interface{}, buffer)
			}

			L := luar.Init()
			Bind(L, webroot)
			err := L.DoString(glue.MainGlue())
			if err != nil {
				panic(err)
			}

			luar.Register(L, "", luar.Map{
				"threadcom": ch,
			})

			if dobind {
				luar.Register(L, "", vals)
			}

			if L.LoadBuffer(bcode, len(bcode), "thread") != 0 {
				return make(chan interface{}), errors.New(L.ToString(-1))
			}

			scheduler.Add(func() {
				if L.Pcall(0, 0, 0) != 0 { // != 0 means error in execution
					fmt.Println("thread error: " + L.ToString(-1))
				}
			})
			return ch, nil
		}),
	})
}

func BindComs(L *lua.State) {
	luar.Register(L, "com", luar.Map{
		"create": (func() chan interface{} {
			return make(chan interface{})
		}),
		"createBuffered": (func(buffer int) chan interface{} {
			return make(chan interface{}, buffer)
		}),
		"receive": (func(c chan interface{}) interface{} {
			return <-c
		}),
		"try_receive": (func(c chan interface{}) interface{} {
			select {
			case msg := <-c:
				return msg
			default:
				return nil
			}
		}),
		"send": (func(c chan interface{}, val interface{}) bool {
			c <- val
			return true
		}),
		"try_send": (func(c chan interface{}, val interface{}) bool {
			select {
			case c <- val:
				return true
			default:
				return false
			}
		}),
		"size": (func(c chan interface{}) int {
			return len(c)
		}),
		"cap": (func(c chan interface{}) int {
			return cap(c)
		}),
		"pipe": (func(a, b chan interface{}) {
			for {
				b <- <-a
			}
		}),
		"pipe_background": (func(a, b chan interface{}) {
			scheduler.Add(func() {
				for {
					b <- <-a
				}
			})
		}),
	})
}

func BindNet(L *lua.State) {
	luar.Register(L, "net", luar.Map{
		"dial": net.Dial,
		"dial_tls": func(proto, addr string) (net.Conn, error) {
			config := tls.Config{InsecureSkipVerify: true} // Because I'm not gonna bother with auth.
			return tls.Dial(proto, addr, &config)
		},
		"write": (func(con interface{}, str string) {
			fmt.Fprintf(con.(net.Conn), str)
		}),
		"readline": (func(con interface{}) (string, error) {
			return bufio.NewReader(con.(net.Conn)).ReadString('\n')
		}),
		"pipe_conn": (func(con interface{}, input, output chan interface{}) {
			go func() {
				reader := bufio.NewReader(con.(net.Conn))
				for {
					line, _ := reader.ReadString('\n')
					output <- line
				}
			}()
			for {
				line := <-input
				fmt.Fprintf(con.(net.Conn), line.(string))
			}
		}),
		"pipe_conn_background": (func(con interface{}, input, output chan interface{}) {
			scheduler.Add(func() {
				reader := bufio.NewReader(con.(net.Conn))
				for {
					line, _ := reader.ReadString('\n')
					output <- line
				}
			})
			scheduler.Add(func() {
				for {
					line := <-input
					fmt.Fprintf(con.(net.Conn), line.(string))
				}
			})
		}),
	})
}

func BindConversions(L *lua.State) {
	luar.Register(L, "convert", luar.Map{
		"stringtocharslice": (func(x string) []byte {
			return []byte(x)
		}),
		"charslicetostring": (func(x []byte) string {
			return string(x)
		}),
	})
}

func BindContext(L *lua.State, context *gin.Context) {
	luar.Register(L, "", luar.Map{
		"context": context,
		"req":     context.Request,

		"host":   context.Request.URL.Host,
		"path":   context.Request.URL.Path,
		"scheme": context.Request.URL.Scheme,
	})
	luar.Register(L, "carbon", luar.Map{
		"_header_set": context.Header,
		"_header_get": context.Request.Header.Get,
		"_paramfunc":  context.Param,
		"_formfunc":   context.PostForm,
		"_queryfunc":  context.Query,
	})
}

func BindEncoding(L *lua.State) {
	luar.Register(L, "carbon", luar.Map{
		"_enc_base64_enc": (func(str string) string {
			return base64.StdEncoding.EncodeToString([]byte(str))
		}),
		"_enc_base64_dec": (func(str string) (string, error) {
			data, err := base64.StdEncoding.DecodeString(str)
			return string(data), err
		}),
	})
}

func BindMarkdown(L *lua.State) {
	luar.Register(L, "markdown", luar.Map{
		"github": (func(source string) string {
			return string(github_flavored_markdown.Markdown([]byte(source)))
		}),
	})
}

func BindOther(L *lua.State) {
	luar.Register(L, "", luar.Map{
		"unixtime": (func() int {
			return int(time.Now().UTC().Unix())
		}),
		"regexp": regexp.Compile,
	})
	luar.Register(L, "carbon", luar.Map{
		"_syntaxhl": helpers.SyntaxHL,
	})
}
<|endoftext|>


<commit_before>package convey

import (
	"github.com/smartystreets/goconvey/execution"
	"github.com/smartystreets/goconvey/printing"
	"github.com/smartystreets/goconvey/reporting"
)

func Convey(items ...interface{}) {
	name, action, test := parseRegistration(items)

	if test != nil {
		runner.Begin(test, name, action)
		runner.Run()
	} else {
		runner.Register(name, action)
	}
}

func Reset(action func()) {
	runner.RegisterReset(action)
}

func So(actual interface{}, match expectation, expected ...interface{}) {
	if result := match(actual, expected...); result == success {
		reporter.Report(reporting.NewSuccessReport())
	} else {
		reporter.Report(reporting.NewFailureReport(result))
	}
}

func init() {
	console := printing.NewConsole()
	printer := printing.NewPrinter(console)
	reporter = reporting.NewReporters(
		reporting.NewGoTestReporter(),
		reporting.NewDotReporter(printer), // TODO: or a dot reporter (-v)
		reporting.NewStatisticsReporter(printer))
	runner = execution.NewRunner()
	runner.UpgradeReporter(reporter)
}

var runner execution.Runner
var reporter reporting.Reporter
<commit_msg>go test -v now activates story output (default is dot output).<commit_after>package convey

import (
	"github.com/smartystreets/goconvey/execution"
	"github.com/smartystreets/goconvey/printing"
	"github.com/smartystreets/goconvey/reporting"
	"os"
)

func Convey(items ...interface{}) {
	name, action, test := parseRegistration(items)

	if test != nil {
		runner.Begin(test, name, action)
		runner.Run()
	} else {
		runner.Register(name, action)
	}
}

func Reset(action func()) {
	runner.RegisterReset(action)
}

func So(actual interface{}, match expectation, expected ...interface{}) {
	if result := match(actual, expected...); result == success {
		reporter.Report(reporting.NewSuccessReport())
	} else {
		reporter.Report(reporting.NewFailureReport(result))
	}
}

func init() {
	console := printing.NewConsole()
	printer := printing.NewPrinter(console)
	reporter = reporting.NewReporters(
		reporting.NewGoTestReporter(),
		consoleReporter(printer),
		reporting.NewStatisticsReporter(printer))
	runner = execution.NewRunner()
	runner.UpgradeReporter(reporter)
}
func consoleReporter(printer *printing.Printer) reporting.Reporter {
	for _, arg := range os.Args {
		if arg == "-test.v=true" {
			return reporting.NewStoryReporter(printer)
		}
	}
	return reporting.NewDotReporter(printer)
}

var runner execution.Runner
var reporter reporting.Reporter
<|endoftext|>


<commit_before>package stacktest

import (
	"encoding/json"
	"fmt"
	"net/url"
	"testing"

	"koding/api"
	"koding/kites/kloud/stack"
	"koding/remoteapi"
	"koding/tools/utils"

	"github.com/koding/kite"
	"github.com/koding/kite/dnode"
	"github.com/koding/logging"
	"golang.org/x/net/context"
)

// CLEANUP(rjeczalik): The following packages should be merged into one:
//
//   - kloud/stack
//   - kloud/stack/provider
//   - kloud/kloud
//
// To fix Base* types abstraction leak and also simplify types, control flow
// and enable testing of the kloud server.

// DefaultLog is a default logger used in FakeKloud.
var DefaultLog = logging.NewCustom("stacktest", testing.Verbose())

// NewRequest mocks new kite.Request for the following arguments.
func NewRequest(method, username string, arg interface{}) *kite.Request {
	p, err := json.Marshal([]interface{}{arg})
	if err != nil {
		panic(fmt.Errorf("unexpected error marshaling %T: %s", arg, err))
	}

	r := &kite.Request{
		Method:   method,
		Username: username,
		Args: &dnode.Partial{
			Raw: p,
		},
	}

	return r
}

// SpyStacker provides a stack.Stacker implementation that records
// all calls to Handle* methods.
type SpyStacker struct {
	Apply     []*stack.ApplyRequest
	Auth      []*stack.AuthenticateRequest
	Bootstrap []*stack.BootstrapRequest
	Plan      []*stack.PlanRequest
}

var (
	_ stack.Stacker  = (*SpyStacker)(nil)
	_ stack.Provider = (*SpyStacker)(nil)
)

func (*SpyStacker) VerifyCredential(*stack.Credential) error { return nil }
func (*SpyStacker) BootstrapTemplates(*stack.Credential) ([]*stack.Template, error) {
	return nil, nil
}
func (*SpyStacker) ApplyTemplate(*stack.Credential) (*stack.Template, error) { return nil, nil }
func (ss *SpyStacker) Stack(context.Context) (interface{}, error)            { return ss, nil }
func (*SpyStacker) Machine(context.Context, string) (interface{}, error)     { return nil, nil }
func (*SpyStacker) NewCredential() interface{}                               { return nil }
func (*SpyStacker) NewBootstrap() interface{}                                { return nil }

// HandleApply implements the stack.Stacker interface.
func (ss *SpyStacker) HandleApply(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.ApplyRequestKey).(*stack.ApplyRequest); ok {
		ss.Apply = append(ss.Apply, req)
	}

	return &stack.ControlResult{
		EventId: utils.StringN(12),
	}, nil
}

// HandleAuthenticate implements the stack.Stacker interface.
func (ss *SpyStacker) HandleAuthenticate(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.AuthenticateRequestKey).(*stack.AuthenticateRequest); ok {
		ss.Auth = append(ss.Auth, req)
	}

	return make(map[string]*stack.AuthenticateResult), nil
}

// HandleBootstrap implements the stack.Stacker interface.
func (ss *SpyStacker) HandleBootstrap(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.BootstrapRequestKey).(*stack.BootstrapRequest); ok {
		ss.Bootstrap = append(ss.Bootstrap, req)
	}

	return true, nil
}

// HandlePlan implements the stack.Stacker interface.
func (ss *SpyStacker) HandlePlan(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.PlanRequestKey).(*stack.PlanRequest); ok {
		ss.Plan = append(ss.Plan, req)
	}

	return make(stack.Machines), nil
}

// FakeKloud mocks stack.Kloud value, so it can be used
// safely in unittests.
//
// This is a best-effort attempt of providing a fake,
// it is not a general purpose fake - it may be not
// suitable for certain use-cases without further
// refactoring.
type FakeKloud struct {
	*stack.Kloud
	Stacker SpyStacker
}

// NewFakeKloud gives new FakeKloud value.
func NewFakeKloud(remoteapiURL string) *FakeKloud {
	u, err := url.Parse(remoteapiURL)
	if err != nil || remoteapiURL == "" {
		u = &url.URL{
			Scheme: "http",
			Host:   "127.0.0.1",
		}
	}

	fk := &FakeKloud{
		Kloud: stack.New(),
	}

	fk.Kloud.Log = DefaultLog
	fk.Kloud.AddProvider("test", &fk.Stacker)
	fk.Kloud.NewStack = func(*kite.Request, *stack.TeamRequest) (stack.Stacker, context.Context, error) {
		return &fk.Stacker, context.Background(), nil
	}
	fk.Kloud.RemoteClient = &remoteapi.Client{
		Endpoint: u,
		Transport: &api.Transport{
			AuthFunc: func(opts *api.AuthOptions) (*api.Session, error) {
				return &api.Session{
					ClientID: "mocked-client-id",
					User:     opts.User,
				}, nil
			},
			Log:   DefaultLog,
			Debug: true,
		},
	}

	return fk
}
<commit_msg>stacktest: use debug logging by default<commit_after>package stacktest

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

	"koding/api"
	"koding/kites/kloud/stack"
	"koding/remoteapi"
	"koding/tools/utils"

	"github.com/koding/kite"
	"github.com/koding/kite/dnode"
	"github.com/koding/logging"
	"golang.org/x/net/context"
)

// CLEANUP(rjeczalik): The following packages should be merged into one:
//
//   - kloud/stack
//   - kloud/stack/provider
//   - kloud/kloud
//
// To fix Base* types abstraction leak and also simplify types, control flow
// and enable testing of the kloud server.

// DefaultLog is a default logger used in FakeKloud.
var DefaultLog = logging.NewCustom("stacktest", true)

// NewRequest mocks new kite.Request for the following arguments.
func NewRequest(method, username string, arg interface{}) *kite.Request {
	p, err := json.Marshal([]interface{}{arg})
	if err != nil {
		panic(fmt.Errorf("unexpected error marshaling %T: %s", arg, err))
	}

	r := &kite.Request{
		Method:   method,
		Username: username,
		Args: &dnode.Partial{
			Raw: p,
		},
	}

	return r
}

// SpyStacker provides a stack.Stacker implementation that records
// all calls to Handle* methods.
type SpyStacker struct {
	Apply     []*stack.ApplyRequest
	Auth      []*stack.AuthenticateRequest
	Bootstrap []*stack.BootstrapRequest
	Plan      []*stack.PlanRequest
}

var (
	_ stack.Stacker  = (*SpyStacker)(nil)
	_ stack.Provider = (*SpyStacker)(nil)
)

func (*SpyStacker) VerifyCredential(*stack.Credential) error { return nil }
func (*SpyStacker) BootstrapTemplates(*stack.Credential) ([]*stack.Template, error) {
	return nil, nil
}
func (*SpyStacker) ApplyTemplate(*stack.Credential) (*stack.Template, error) { return nil, nil }
func (ss *SpyStacker) Stack(context.Context) (interface{}, error)            { return ss, nil }
func (*SpyStacker) Machine(context.Context, string) (interface{}, error)     { return nil, nil }
func (*SpyStacker) NewCredential() interface{}                               { return nil }
func (*SpyStacker) NewBootstrap() interface{}                                { return nil }

// HandleApply implements the stack.Stacker interface.
func (ss *SpyStacker) HandleApply(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.ApplyRequestKey).(*stack.ApplyRequest); ok {
		ss.Apply = append(ss.Apply, req)
	}

	return &stack.ControlResult{
		EventId: utils.StringN(12),
	}, nil
}

// HandleAuthenticate implements the stack.Stacker interface.
func (ss *SpyStacker) HandleAuthenticate(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.AuthenticateRequestKey).(*stack.AuthenticateRequest); ok {
		ss.Auth = append(ss.Auth, req)
	}

	return make(map[string]*stack.AuthenticateResult), nil
}

// HandleBootstrap implements the stack.Stacker interface.
func (ss *SpyStacker) HandleBootstrap(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.BootstrapRequestKey).(*stack.BootstrapRequest); ok {
		ss.Bootstrap = append(ss.Bootstrap, req)
	}

	return true, nil
}

// HandlePlan implements the stack.Stacker interface.
func (ss *SpyStacker) HandlePlan(ctx context.Context) (interface{}, error) {
	if req, ok := ctx.Value(stack.PlanRequestKey).(*stack.PlanRequest); ok {
		ss.Plan = append(ss.Plan, req)
	}

	return make(stack.Machines), nil
}

// FakeKloud mocks stack.Kloud value, so it can be used
// safely in unittests.
//
// This is a best-effort attempt of providing a fake,
// it is not a general purpose fake - it may be not
// suitable for certain use-cases without further
// refactoring.
type FakeKloud struct {
	*stack.Kloud
	Stacker SpyStacker
}

// NewFakeKloud gives new FakeKloud value.
func NewFakeKloud(remoteapiURL string) *FakeKloud {
	u, err := url.Parse(remoteapiURL)
	if err != nil || remoteapiURL == "" {
		u = &url.URL{
			Scheme: "http",
			Host:   "127.0.0.1",
		}
	}

	fk := &FakeKloud{
		Kloud: stack.New(),
	}

	fk.Kloud.Log = DefaultLog
	fk.Kloud.AddProvider("test", &fk.Stacker)
	fk.Kloud.NewStack = func(*kite.Request, *stack.TeamRequest) (stack.Stacker, context.Context, error) {
		return &fk.Stacker, context.Background(), nil
	}
	fk.Kloud.RemoteClient = &remoteapi.Client{
		Endpoint: u,
		Transport: &api.Transport{
			AuthFunc: func(opts *api.AuthOptions) (*api.Session, error) {
				return &api.Session{
					ClientID: "mocked-client-id",
					User:     opts.User,
				}, nil
			},
			Log:   DefaultLog,
			Debug: true,
		},
	}

	return fk
}
<|endoftext|>


<commit_before>package plugins

import (
	"strings"

	"fmt"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Sirupsen/logrus"
	"github.com/bwmarrin/discordgo"
)

type friendAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next friendAction)

type Friend struct{}

func (f *Friend) Commands() []string {
	return []string{
		"friend",
		"friends",
	}
}

func (f *Friend) Init(session *discordgo.Session) {

}

func (f *Friend) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	defer helpers.Recover()

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := f.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (f *Friend) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if len(args) < 1 {
		*out = f.newMsg("bot.arguments.too-few")
		return f.actionFinish
	}

	switch args[0] {
	case "list":
		return f.actionList
	case "invite":
		return f.actionInvite
	}

	*out = f.newMsg("bot.arguments.invalid")
	return f.actionFinish
}

func (f *Friend) actionInvite(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if helpers.IsAdmin(in) == false {
		*out = f.newMsg(helpers.GetText("mod.no_permission"))
		return f.actionFinish
	}

	channel, err := helpers.GetChannel(in.ChannelID)
	f.Relax(err)

	if cache.GetFriend(channel.GuildID) != nil {
		*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-already-on-server"))
		return f.actionFinish
	}

	friend, err := helpers.InviteFriend()
	if err != nil {
		if strings.Contains(err.Error(), "No friend with free slots available, please add more friends!") {
			f.logger().Error(err.Error())
			*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-no-friend-available"))
			return f.actionFinish
		} else {
			f.Relax(err)
		}
	}

	guild, err := helpers.GetGuild(channel.GuildID)
	f.Relax(err)

	var invite *discordgo.Invite
	for _, guildChannel := range guild.Channels {
		invite, err = cache.GetSession().ChannelInviteCreate(guildChannel.ID, discordgo.Invite{
			MaxAge:    60 * 15,
			MaxUses:   1,
			Temporary: false,
		})
		if err == nil {
			break
		}
	}

	if invite == nil {
		*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-invite-creation-failed"))
		return f.actionFinish
	}

	response, err := helpers.FriendRequest(friend, "POST", "invites/"+invite.Code)
	f.Relax(err)

	if response.StatusCode != 200 {
		f.logger().Error(fmt.Sprintf(
			"Unexpected status code trying to invite Friend %s (#%s) to Guild %s (#%s): %d",
			friend.State.User.Username, friend.State.User.ID,
			guild.Name, guild.ID,
			response.StatusCode,
		))
		*out = f.newMsg(helpers.GetTextF("plugins.friends.invite-error-accept-invite-invalid-statuscode"))
		return f.actionFinish
	}

	*out = f.newMsg(helpers.GetTextF("plugins.friends.invite-success", friend.State.User.Username))
	return f.actionFinish
}

func (f *Friend) actionList(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if helpers.IsRobyulMod(in.Author.ID) == false {
		*out = f.newMsg(helpers.GetText("robyulmod.no_permission"))
		return f.actionFinish
	}

	message := "__**Robyul's friends**__\n"
	friends := cache.GetFriends()
	totalGuilds := 0

	for _, friend := range friends {
		message += fmt.Sprintf(
			"**%s** `(#%s)` (on %d guilds)\n",
			friend.State.User.Username, friend.State.User.ID, len(friend.State.Guilds))
		totalGuilds += len(friend.State.Guilds)
	}

	message += fmt.Sprintf("_in total %d friends on %d guilds_\n", len(friends), totalGuilds)

	*out = f.newMsg(message)
	return f.actionFinish
}

func (f *Friend) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	_, err := cache.GetSession().ChannelMessageSendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (f *Friend) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (f *Friend) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (f *Friend) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "friends")
}
<commit_msg>[friends] invite staff only<commit_after>package plugins

import (
	"strings"

	"fmt"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Sirupsen/logrus"
	"github.com/bwmarrin/discordgo"
)

type friendAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next friendAction)

type Friend struct{}

func (f *Friend) Commands() []string {
	return []string{
		"friend",
		"friends",
	}
}

func (f *Friend) Init(session *discordgo.Session) {

}

func (f *Friend) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	defer helpers.Recover()

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := f.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (f *Friend) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if len(args) < 1 {
		*out = f.newMsg("bot.arguments.too-few")
		return f.actionFinish
	}

	switch args[0] {
	case "list":
		return f.actionList
	case "invite":
		return f.actionInvite
	}

	*out = f.newMsg("bot.arguments.invalid")
	return f.actionFinish
}

func (f *Friend) actionInvite(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if helpers.IsRobyulMod(in.Author.ID) == false {
		*out = f.newMsg(helpers.GetText("robyulmod.no_permission"))
		return f.actionFinish
	}

	channel, err := helpers.GetChannel(in.ChannelID)
	f.Relax(err)

	if cache.GetFriend(channel.GuildID) != nil {
		*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-already-on-server"))
		return f.actionFinish
	}

	friend, err := helpers.InviteFriend()
	if err != nil {
		if strings.Contains(err.Error(), "No friend with free slots available, please add more friends!") {
			f.logger().Error(err.Error())
			*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-no-friend-available"))
			return f.actionFinish
		} else {
			f.Relax(err)
		}
	}

	guild, err := helpers.GetGuild(channel.GuildID)
	f.Relax(err)

	var invite *discordgo.Invite
	for _, guildChannel := range guild.Channels {
		invite, err = cache.GetSession().ChannelInviteCreate(guildChannel.ID, discordgo.Invite{
			MaxAge:    60 * 15,
			MaxUses:   1,
			Temporary: false,
		})
		if err == nil {
			break
		}
	}

	if invite == nil {
		*out = f.newMsg(helpers.GetText("plugins.friends.invite-error-invite-creation-failed"))
		return f.actionFinish
	}

	response, err := helpers.FriendRequest(friend, "POST", "invites/"+invite.Code)
	f.Relax(err)

	if response.StatusCode != 200 {
		f.logger().Error(fmt.Sprintf(
			"Unexpected status code trying to invite Friend %s (#%s) to Guild %s (#%s): %d",
			friend.State.User.Username, friend.State.User.ID,
			guild.Name, guild.ID,
			response.StatusCode,
		))
		*out = f.newMsg(helpers.GetTextF("plugins.friends.invite-error-accept-invite-invalid-statuscode"))
		return f.actionFinish
	}

	*out = f.newMsg(helpers.GetTextF("plugins.friends.invite-success", friend.State.User.Username))
	return f.actionFinish
}

func (f *Friend) actionList(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	if helpers.IsRobyulMod(in.Author.ID) == false {
		*out = f.newMsg(helpers.GetText("robyulmod.no_permission"))
		return f.actionFinish
	}

	message := "__**Robyul's friends**__\n"
	friends := cache.GetFriends()
	totalGuilds := 0

	for _, friend := range friends {
		message += fmt.Sprintf(
			"**%s** `(#%s)` (on %d guilds)\n",
			friend.State.User.Username, friend.State.User.ID, len(friend.State.Guilds))
		totalGuilds += len(friend.State.Guilds)
	}

	message += fmt.Sprintf("_in total %d friends on %d guilds_\n", len(friends), totalGuilds)

	*out = f.newMsg(message)
	return f.actionFinish
}

func (f *Friend) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) friendAction {
	_, err := cache.GetSession().ChannelMessageSendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (f *Friend) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (f *Friend) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (f *Friend) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "friends")
}
<|endoftext|>


<commit_before>package sous

import (
	"fmt"
	"strings"

	"github.com/samsalisbury/semv"
	"golang.org/x/text/unicode/norm"
)

type (
	// RepoURL is a URL to a source code repository.
	RepoURL string
	// RepoOffset is a path within a repository containing a single piece of
	// software.
	RepoOffset string
	// SourceID identifies a specific snapshot of a body of source code,
	// including its location and version.
	SourceID struct {
		RepoURL    RepoURL
		Version    semv.Version
		RepoOffset RepoOffset `yaml:",omitempty"`
	}

	//MissingRepo indicates that Sous couldn't determine which repo was intended for this SL
	MissingRepo struct {
		parsing string
	}

	//MissingVersion indicates that Sous couldn't determine what version was intended for this SL
	MissingVersion struct {
		repo    string
		parsing string
	}

	//MissingPath indicates that Sous couldn't determine what repo offset was intended for this SL
	MissingPath struct {
		repo    string
		parsing string
	}

	//IncludesVersion indicates that Sous couldn't determine what version was intended for this SL
	IncludesVersion struct {
		parsing string
	}
)

func (sv SourceID) String() string {
	if sv.RepoOffset == "" {
		return fmt.Sprintf("%s %s", sv.RepoURL, sv.Version)
	}
	return fmt.Sprintf("%s:%s %s", sv.RepoURL, sv.RepoOffset, sv.Version)
}

// RevID returns the revision id for this SourceID.
func (sv SourceID) RevID() string {
	return sv.Version.Meta
}

// TagName returns the tag name for this SourceID.
func (sv SourceID) TagName() string {
	return sv.Version.Format("M.m.p-?")
}

// SourceLocation returns the location component of this SourceID
func (sv SourceID) SourceLocation() SourceLocation {
	return SourceLocation{
		RepoURL:    sv.RepoURL,
		RepoOffset: sv.RepoOffset,
	}
}

// Equal tests the equality between this SV and another
func (sv SourceID) Equal(o SourceID) bool {
	return sv.RepoURL == o.RepoURL && sv.RepoOffset == o.RepoOffset && sv.Version.Equals(o.Version)
}

// Repo returns the repository URL for this SV
func (sv SourceID) Repo() RepoURL {
	return sv.RepoURL
}

// DefaultDelim is a comma
const DefaultDelim = ","

func (err *IncludesVersion) Error() string {
	return fmt.Sprintf("Three parts found (includes a version?) in a canonical name: %q", err.parsing)
}

func (err *MissingRepo) Error() string {
	return fmt.Sprintf("No repository found in %q", err.parsing)
}

func (err *MissingVersion) Error() string {
	return fmt.Sprintf("No version found in %q (did find repo: %q)", err.parsing, err.repo)
}

func (err *MissingPath) Error() string {
	return fmt.Sprintf("No path found in %q (did find repo: %q)", err.parsing, err.repo)
}

func parseChunks(sourceStr string) []string {
	source := norm.NFC.String(sourceStr)

	delim := DefaultDelim
	if !('A' <= source[0] && source[0] <= 'Z') && !('a' <= source[0] && source[0] <= 'z') {
		delim = source[0:1]
		source = source[1:]
	}

	return strings.Split(source, delim)
}

func sourceVersionFromChunks(source string, chunks []string) (sv SourceID, err error) {
	if len(chunks[0]) == 0 {
		err = &MissingRepo{source}
		return
	}

	sv.RepoURL = RepoURL(chunks[0])

	sv.Version, err = semv.Parse(string(chunks[1]))
	if err != nil {
		return
	}
	if len(chunks) < 3 {
		sv.RepoOffset = ""
	} else {
		sv.RepoOffset = RepoOffset(chunks[2])
	}

	return
}

func sourceLocationFromChunks(source string, chunks []string) (sl SourceLocation, err error) {
	if len(chunks) > 2 {
		err = &IncludesVersion{source}
		return
	}

	if len(chunks[0]) == 0 {
		err = &MissingRepo{source}
		return
	}
	sl.RepoURL = RepoURL(chunks[0])

	if len(chunks) < 2 {
		sl.RepoOffset = ""
	} else {
		sl.RepoOffset = RepoOffset(chunks[1])
	}

	return
}

// ParseSourceID parses an entire SourceID.
func ParseSourceID(source string) (SourceID, error) {
	chunks := parseChunks(source)
	return sourceVersionFromChunks(source, chunks)
}

// ParseSourceLocation parses an entire SourceLocation.
func ParseSourceLocation(source string) (SourceLocation, error) {
	chunks := parseChunks(source)
	return sourceLocationFromChunks(source, chunks)
}
<commit_msg>source id: code cleanup<commit_after>package sous

import (
	"fmt"
	"strings"

	"github.com/samsalisbury/semv"
	"golang.org/x/text/unicode/norm"
)

type (
	// RepoURL is a URL to a source code repository.
	RepoURL string
	// RepoOffset is a path within a repository containing a single piece of
	// software.
	RepoOffset string
	// SourceID identifies a specific snapshot of a body of source code,
	// including its location and version.
	SourceID struct {
		RepoURL    RepoURL
		Version    semv.Version
		RepoOffset RepoOffset `yaml:",omitempty"`
	}

	//MissingRepo indicates that Sous couldn't determine which repo was intended for this SL
	MissingRepo struct {
		parsing string
	}

	//MissingVersion indicates that Sous couldn't determine what version was intended for this SL
	MissingVersion struct {
		repo    string
		parsing string
	}

	//MissingPath indicates that Sous couldn't determine what repo offset was intended for this SL
	MissingPath struct {
		repo    string
		parsing string
	}

	//IncludesVersion indicates that Sous couldn't determine what version was intended for this SL
	IncludesVersion struct {
		parsing string
	}
)

func (sv SourceID) String() string {
	if sv.RepoOffset == "" {
		return fmt.Sprintf("%s %s", sv.RepoURL, sv.Version)
	}
	return fmt.Sprintf("%s:%s %s", sv.RepoURL, sv.RepoOffset, sv.Version)
}

// RevID returns the revision id for this SourceID.
func (sv SourceID) RevID() string {
	return sv.Version.Meta
}

// TagName returns the tag name for this SourceID.
func (sv SourceID) TagName() string {
	return sv.Version.Format("M.m.p-?")
}

// SourceLocation returns the location component of this SourceID
func (sv SourceID) SourceLocation() SourceLocation {
	return SourceLocation{
		RepoURL:    sv.RepoURL,
		RepoOffset: sv.RepoOffset,
	}
}

// Equal tests the equality between this SV and another
func (sv SourceID) Equal(o SourceID) bool {
	return sv.RepoURL == o.RepoURL && sv.RepoOffset == o.RepoOffset && sv.Version.Equals(o.Version)
}

// Repo returns the repository URL for this SV
func (sv SourceID) Repo() RepoURL {
	return sv.RepoURL
}

// DefaultDelim is a comma
const DefaultDelim = ","

func (err *IncludesVersion) Error() string {
	return fmt.Sprintf("Three parts found (includes a version?) in a canonical name: %q", err.parsing)
}

func (err *MissingRepo) Error() string {
	return fmt.Sprintf("No repository found in %q", err.parsing)
}

func (err *MissingVersion) Error() string {
	return fmt.Sprintf("No version found in %q (did find repo: %q)", err.parsing, err.repo)
}

func (err *MissingPath) Error() string {
	return fmt.Sprintf("No path found in %q (did find repo: %q)", err.parsing, err.repo)
}

func parseChunks(sourceStr string) []string {
	source := norm.NFC.String(sourceStr)

	delim := DefaultDelim
	if !('A' <= source[0] && source[0] <= 'Z') && !('a' <= source[0] && source[0] <= 'z') {
		delim = source[0:1]
		source = source[1:]
	}

	return strings.Split(source, delim)
}

func sourceIDFromChunks(source string, chunks []string) (SourceID, error) {
	if len(chunks[0]) == 0 {
		return SourceID{}, &MissingRepo{source}
	}
	repoURL := RepoURL(chunks[0])
	version, err := semv.Parse(string(chunks[1]))
	if err != nil {
		return SourceID{}, err
	}
	repoOffset := RepoOffset("")
	if len(chunks) > 2 {
		repoOffset = RepoOffset(chunks[2])
	}
	return SourceID{
		Version:    version,
		RepoURL:    repoURL,
		RepoOffset: repoOffset,
	}, nil
}

func sourceLocationFromChunks(source string, chunks []string) (SourceLocation, error) {
	if len(chunks) > 2 {
		return SourceLocation{}, &IncludesVersion{source}
	}
	if len(chunks[0]) == 0 {
		return SourceLocation{}, &MissingRepo{source}
	}
	repoURL := RepoURL(chunks[0])
	repoOffset := RepoOffset("")
	if len(chunks) > 1 {
		repoOffset = RepoOffset(chunks[1])
	}
	return SourceLocation{RepoURL: repoURL, RepoOffset: repoOffset}, nil
}

// ParseSourceID parses an entire SourceID.
func ParseSourceID(s string) (SourceID, error) {
	chunks := parseChunks(s)
	return sourceIDFromChunks(s, chunks)
}

// ParseSourceLocation parses an entire SourceLocation.
func ParseSourceLocation(s string) (SourceLocation, error) {
	chunks := parseChunks(s)
	return sourceLocationFromChunks(s, chunks)
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 @ z3q.net.
 * name : aftersales_service.go
 * author : jarryliu
 * date : 2016-07-18 17:16
 * description :
 * history :
 */
package dps

import (
	"github.com/jsix/gof/db"
	"go2o/core/domain/interface/after-sales"
	"go2o/core/domain/interface/order"
	"go2o/core/dto"
	"go2o/core/infrastructure/format"
	"go2o/core/query"
)

type afterSalesService struct {
	_orderRep order.IOrderRep
	_rep      afterSales.IAfterSalesRep
	_query    *query.AfterSalesQuery
	db.Connector
}

func NewAfterSalesService(rep afterSales.IAfterSalesRep,
	q *query.AfterSalesQuery, orderRep order.IOrderRep) *afterSalesService {
	return &afterSalesService{
		_rep:      rep,
		_orderRep: orderRep,
		_query:    q,
	}
}

// 提交售后单
func (a *afterSalesService) SubmitAfterSalesOrder(orderId int, asType int,
	snapshotId int, quantity int, reason string, img string) (int, error) {
	ro := a._rep.CreateAfterSalesOrder(&afterSales.AfterSalesOrder{
		// 订单编号
		OrderId: orderId,
		// 类型，退货、换货、维修
		Type: asType,
		// 售后原因
		Reason:        reason,
		ReturnSpImage: img,
	})
	err := ro.SetItem(snapshotId, quantity)
	if err == nil {
		return ro.Submit()
	}
	return 0, err
}

// 获取订单的所有售后单
func (a *afterSalesService) GetAllAfterSalesOrderOfSaleOrder(orderId int) []afterSales.AfterSalesOrder {
	list := a._rep.GetAllOfSaleOrder(orderId)
	arr := make([]afterSales.AfterSalesOrder, len(list))
	for i, v := range list {
		arr[i] = v.Value()
		arr[i].StateText = afterSales.Stat(arr[i].State).String()
	}
	return arr
}

// 获取会员的分页售后单
func (a *afterSalesService) QueryPagerAfterSalesOrderOfMember(memberId, begin,
	size int, where string) (int, []*dto.PagedMemberAfterSalesOrder) {
	return a._query.QueryPagerAfterSalesOrderOfMember(memberId, begin, size, where)
}

// 获取商户的分页售后单
func (a *afterSalesService) QueryPagerAfterSalesOrderOfVendor(vendorId, begin,
	size int, where string) (int, []*dto.PagedVendorAfterSalesOrder) {
	return a._query.QueryPagerAfterSalesOrderOfVendor(vendorId, begin, size, where)
}

//根据order_id获得订单号
func (a *afterSalesService) GetAfterSalesOrder(order_id int) int {
	id := 0
	a.Connector.ExecScalar("SSELECT order_no FROM sale_order WHERE id=?", &id, order_id)
	return id
}

// 获取售后单
func (a *afterSalesService) GetAfterSaleOrder(id int) *afterSales.AfterSalesOrder {
	as := a._rep.GetAfterSalesOrder(id)
	if as != nil {
		v := as.Value()
		v.StateText = afterSales.Stat(v.State).String()
		v.ReturnSpImage = format.GetResUrl(v.ReturnSpImage)
		return &v
	}
	return nil
}

// 同意售后
func (a *afterSalesService) AgreeAfterSales(id int, remark string) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Agree()
}

// 拒绝售后
func (a *afterSalesService) DeclineAfterSales(id int, reason string) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Decline(reason)
}

// 申请调解
func (a *afterSalesService) RequestIntercede(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.RequestIntercede()
}

// 系统确认
func (a *afterSalesService) ConfirmAfterSales(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Confirm()
}

// 系统退回
func (a *afterSalesService) RejectAfterSales(id int, remark string) error {
	as := a._rep.GetAfterSalesOrder(id)
	if as == nil {
		return afterSales.ErrNoSuchOrder
	}

	return as.Reject(remark)
}

// 处理退款/退货完成,一般是系统自动调用
func (a *afterSalesService) ProcessAfterSalesOrder(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	if as == nil {
		return afterSales.ErrNoSuchOrder
	}
	v := as.Value()
	switch v.State {
	case afterSales.TypeRefund:
		return as.Process()
	case afterSales.TypeReturn:
		return as.Process()
	}
	return afterSales.ErrAutoProcess
}

// 售后收货
func (a *afterSalesService) ReceiveReturnShipment(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	err := as.ReturnReceive()
	if err == nil {
		if as.Value().State != afterSales.TypeExchange {
			err = as.Process()
		}
	}
	return err
}

// 换货发货
func (a *afterSalesService) ExchangeShipment(id int, spName string, spOrder string) error {
	ex := a._rep.GetAfterSalesOrder(id).(afterSales.IExchangeOrder)
	return ex.ExchangeShip(spName, spOrder)
}

// 换货收货
func (a *afterSalesService) ReceiveExchange(id int) error {
	ex := a._rep.GetAfterSalesOrder(id).(afterSales.IExchangeOrder)
	return ex.ExchangeReceive()
}
<commit_msg>aftersales_service.go<commit_after>/**
 * Copyright 2015 @ z3q.net.
 * name : aftersales_service.go
 * author : jarryliu
 * date : 2016-07-18 17:16
 * description :
 * history :
 */
package dps

import (
	"github.com/jsix/gof/db"
	"go2o/core/domain/interface/after-sales"
	"go2o/core/domain/interface/order"
	"go2o/core/dto"
	"go2o/core/infrastructure/format"
	"go2o/core/query"
	"github.com/labstack/gommon/log"
)

type afterSalesService struct {
	_orderRep order.IOrderRep
	_rep      afterSales.IAfterSalesRep
	_query    *query.AfterSalesQuery
	db.Connector
}

func NewAfterSalesService(rep afterSales.IAfterSalesRep,
	q *query.AfterSalesQuery, orderRep order.IOrderRep) *afterSalesService {
	return &afterSalesService{
		_rep:      rep,
		_orderRep: orderRep,
		_query:    q,
	}
}

// 提交售后单
func (a *afterSalesService) SubmitAfterSalesOrder(orderId int, asType int,
	snapshotId int, quantity int, reason string, img string) (int, error) {
	ro := a._rep.CreateAfterSalesOrder(&afterSales.AfterSalesOrder{
		// 订单编号
		OrderId: orderId,
		// 类型，退货、换货、维修
		Type: asType,
		// 售后原因
		Reason:        reason,
		ReturnSpImage: img,
	})
	err := ro.SetItem(snapshotId, quantity)
	if err == nil {
		return ro.Submit()
	}
	return 0, err
}

// 获取订单的所有售后单
func (a *afterSalesService) GetAllAfterSalesOrderOfSaleOrder(orderId int) []afterSales.AfterSalesOrder {
	list := a._rep.GetAllOfSaleOrder(orderId)
	arr := make([]afterSales.AfterSalesOrder, len(list))
	for i, v := range list {
		arr[i] = v.Value()
		arr[i].StateText = afterSales.Stat(arr[i].State).String()
	}
	return arr
}

// 获取会员的分页售后单
func (a *afterSalesService) QueryPagerAfterSalesOrderOfMember(memberId, begin,
	size int, where string) (int, []*dto.PagedMemberAfterSalesOrder) {
	return a._query.QueryPagerAfterSalesOrderOfMember(memberId, begin, size, where)
}

// 获取商户的分页售后单
func (a *afterSalesService) QueryPagerAfterSalesOrderOfVendor(vendorId, begin,
	size int, where string) (int, []*dto.PagedVendorAfterSalesOrder) {
	return a._query.QueryPagerAfterSalesOrderOfVendor(vendorId, begin, size, where)
}

//根据order_id获得订单号
func (a *afterSalesService) GetAfterSalesOrder(order_id int) int {
	id := 0
	a.Connector.ExecScalar("SSELECT order_no FROM sale_order WHERE id=?", &id, order_id)
	return id
}

// 获取售后单
func (a *afterSalesService) GetAfterSaleOrder(id int) *afterSales.AfterSalesOrder {
	as := a._rep.GetAfterSalesOrder(id)
	if as != nil {
		v := as.Value()
		v.StateText = afterSales.Stat(v.State).String()
		v.ReturnSpImage = format.GetResUrl(v.ReturnSpImage)
		return &v
	}
	return nil
}

// 同意售后
func (a *afterSalesService) AgreeAfterSales(id int, remark string) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Agree()
}

// 拒绝售后
func (a *afterSalesService) DeclineAfterSales(id int, reason string) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Decline(reason)
}

// 申请调解
func (a *afterSalesService) RequestIntercede(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.RequestIntercede()
}

// 系统确认
func (a *afterSalesService) ConfirmAfterSales(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	return as.Confirm()
}

// 系统退回
func (a *afterSalesService) RejectAfterSales(id int, remark string) error {
	as := a._rep.GetAfterSalesOrder(id)
	if as == nil {
		return afterSales.ErrNoSuchOrder
	}

	return as.Reject(remark)
}

// 处理退款/退货完成,一般是系统自动调用
func (a *afterSalesService) ProcessAfterSalesOrder(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	if as == nil {
		return afterSales.ErrNoSuchOrder
	}
	v := as.Value()
	log.Print("========================================%d",v.State)
	switch v.Type {
	case afterSales.TypeRefund:
		return as.Process()
	case afterSales.TypeReturn:
		return as.Process()
	}
	return afterSales.ErrAutoProcess
}

// 售后收货
func (a *afterSalesService) ReceiveReturnShipment(id int) error {
	as := a._rep.GetAfterSalesOrder(id)
	err := as.ReturnReceive()
	if err == nil {
		if as.Value().State != afterSales.TypeExchange {
			err = as.Process()
		}
	}
	return err
}

// 换货发货
func (a *afterSalesService) ExchangeShipment(id int, spName string, spOrder string) error {
	ex := a._rep.GetAfterSalesOrder(id).(afterSales.IExchangeOrder)
	return ex.ExchangeShip(spName, spOrder)
}

// 换货收货
func (a *afterSalesService) ReceiveExchange(id int) error {
	ex := a._rep.GetAfterSalesOrder(id).(afterSales.IExchangeOrder)
	return ex.ExchangeReceive()
}
<|endoftext|>


<commit_before>package jail

import (
	"os"

	"github.com/robertkrimen/otto"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/jail/console"
	"github.com/status-im/status-go/geth/node"
	"github.com/status-im/status-go/geth/signal"
)

// signals
const (
	EventSignal = "jail.signal"

	// EventConsoleLog defines the event type for the console.log call.
	eventConsoleLog = "vm.console.log"
)

// registerHandlers augments and transforms a given jail cell's underlying VM,
// by adding and replacing method handlers.
func registerHandlers(jail *Jail, cell common.JailCell, chatID string) error {
	jeth, err := cell.Get("jeth")
	if err != nil {
		return err
	}

	registerHandler := jeth.Object().Set

	if err = registerHandler("console", map[string]interface{}{
		"log": func(fn otto.FunctionCall) otto.Value {
			return console.Write(fn, os.Stdout, eventConsoleLog)
		},
	}); err != nil {
		return err
	}

	// register send handler
	if err = registerHandler("send", makeSendHandler(jail, cell)); err != nil {
		return err
	}

	// register sendAsync handler
	if err = registerHandler("sendAsync", makeAsyncSendHandler(jail, cell)); err != nil {
		return err
	}

	// register isConnected handler
	if err = registerHandler("isConnected", makeJethIsConnectedHandler(jail, cell)); err != nil {
		return err
	}

	// register sendMessage/showSuggestions handlers
	if err = cell.Set("statusSignals", struct{}{}); err != nil {
		return err
	}
	statusSignals, err := cell.Get("statusSignals")
	if err != nil {
		return err
	}
	registerHandler = statusSignals.Object().Set
	if err = registerHandler("sendSignal", makeSignalHandler(chatID)); err != nil {
		return err
	}

	return nil
}

// makeAsyncSendHandler returns jeth.sendAsync() handler.
func makeAsyncSendHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) otto.Value {
	// FIXME(tiabc): Get rid of this.
	cell := cellInt.(*Cell)
	return func(call otto.FunctionCall) otto.Value {
		go func() {
			response := jail.Send(call)

			// run callback asyncronously with args (error, response)
			callback := call.Argument(1)
			err := otto.NullValue()
			cell.CallAsync(callback, err, response)
		}()
		return otto.UndefinedValue()
	}
}

// makeSendHandler returns jeth.send() and jeth.sendAsync() handler
// TODO(tiabc): get rid of an extra parameter.
func makeSendHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) otto.Value {
	return func(call otto.FunctionCall) otto.Value {
		return jail.Send(call)
	}
}

// makeJethIsConnectedHandler returns jeth.isConnected() handler
func makeJethIsConnectedHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) (response otto.Value) {
	// FIXME(tiabc): Get rid of this.
	cell := cellInt.(*Cell)
	return func(call otto.FunctionCall) otto.Value {
		client := jail.nodeManager.RPCClient()

		var netListeningResult bool
		if err := client.Call(&netListeningResult, "net_listening"); err != nil {
			return newErrorResponseOtto(cell.VM, err.Error(), nil)
		}

		if !netListeningResult {
			return newErrorResponseOtto(cell.VM, node.ErrNoRunningNode.Error(), nil)
		}

		return newResultResponse(call.Otto, true)
	}
}

// SignalEvent wraps Jail send signals
type SignalEvent struct {
	ChatID string `json:"chat_id"`
	Data   string `json:"data"`
}

func makeSignalHandler(chatID string) func(call otto.FunctionCall) otto.Value {
	return func(call otto.FunctionCall) otto.Value {
		message := call.Argument(0).String()

		signal.Send(signal.Envelope{
			Type: EventSignal,
			Event: SignalEvent{
				ChatID: chatID,
				Data:   message,
			},
		})

		return newResultResponse(call.Otto, true)
	}
}
<commit_msg>Check for callback in makeAsyncHandler (#395)<commit_after>package jail

import (
	"os"

	"github.com/robertkrimen/otto"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/jail/console"
	"github.com/status-im/status-go/geth/node"
	"github.com/status-im/status-go/geth/signal"
)

// signals
const (
	EventSignal = "jail.signal"

	// EventConsoleLog defines the event type for the console.log call.
	eventConsoleLog = "vm.console.log"
)

// registerHandlers augments and transforms a given jail cell's underlying VM,
// by adding and replacing method handlers.
func registerHandlers(jail *Jail, cell common.JailCell, chatID string) error {
	jeth, err := cell.Get("jeth")
	if err != nil {
		return err
	}

	registerHandler := jeth.Object().Set

	if err = registerHandler("console", map[string]interface{}{
		"log": func(fn otto.FunctionCall) otto.Value {
			return console.Write(fn, os.Stdout, eventConsoleLog)
		},
	}); err != nil {
		return err
	}

	// register send handler
	if err = registerHandler("send", makeSendHandler(jail, cell)); err != nil {
		return err
	}

	// register sendAsync handler
	if err = registerHandler("sendAsync", makeAsyncSendHandler(jail, cell)); err != nil {
		return err
	}

	// register isConnected handler
	if err = registerHandler("isConnected", makeJethIsConnectedHandler(jail, cell)); err != nil {
		return err
	}

	// register sendMessage/showSuggestions handlers
	if err = cell.Set("statusSignals", struct{}{}); err != nil {
		return err
	}
	statusSignals, err := cell.Get("statusSignals")
	if err != nil {
		return err
	}
	registerHandler = statusSignals.Object().Set
	if err = registerHandler("sendSignal", makeSignalHandler(chatID)); err != nil {
		return err
	}

	return nil
}

// makeAsyncSendHandler returns jeth.sendAsync() handler.
func makeAsyncSendHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) otto.Value {
	// FIXME(tiabc): Get rid of this.
	cell := cellInt.(*Cell)
	return func(call otto.FunctionCall) otto.Value {
		go func() {
			response := jail.Send(call)

			callback := call.Argument(1)
			if callback.Class() == "Function" {
				// run callback asyncronously with args (error, response)
				err := otto.NullValue()
				cell.CallAsync(callback, err, response)
			}
		}()
		return otto.UndefinedValue()
	}
}

// makeSendHandler returns jeth.send() and jeth.sendAsync() handler
// TODO(tiabc): get rid of an extra parameter.
func makeSendHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) otto.Value {
	return func(call otto.FunctionCall) otto.Value {
		return jail.Send(call)
	}
}

// makeJethIsConnectedHandler returns jeth.isConnected() handler
func makeJethIsConnectedHandler(jail *Jail, cellInt common.JailCell) func(call otto.FunctionCall) (response otto.Value) {
	// FIXME(tiabc): Get rid of this.
	cell := cellInt.(*Cell)
	return func(call otto.FunctionCall) otto.Value {
		client := jail.nodeManager.RPCClient()

		var netListeningResult bool
		if err := client.Call(&netListeningResult, "net_listening"); err != nil {
			return newErrorResponseOtto(cell.VM, err.Error(), nil)
		}

		if !netListeningResult {
			return newErrorResponseOtto(cell.VM, node.ErrNoRunningNode.Error(), nil)
		}

		return newResultResponse(call.Otto, true)
	}
}

// SignalEvent wraps Jail send signals
type SignalEvent struct {
	ChatID string `json:"chat_id"`
	Data   string `json:"data"`
}

func makeSignalHandler(chatID string) func(call otto.FunctionCall) otto.Value {
	return func(call otto.FunctionCall) otto.Value {
		message := call.Argument(0).String()

		signal.Send(signal.Envelope{
			Type: EventSignal,
			Event: SignalEvent{
				ChatID: chatID,
				Data:   message,
			},
		})

		return newResultResponse(call.Otto, true)
	}
}
<|endoftext|>


<commit_before>package pingdumb

import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"
)

const (
	timeout = 5 * time.Second
)

var DefaultResolvers = []*net.Resolver{
	net.DefaultResolver,
	&net.Resolver{
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   timeout,
				KeepAlive: timeout,
				DualStack: true,
			}
			return dialer.DialContext(ctx, "tcp", "8.8.8.8:53")
		},
	},
	&net.Resolver{
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   timeout,
				KeepAlive: timeout,
				DualStack: true,
			}
			return dialer.DialContext(ctx, "tcp", "8.8.4.4:53")
		},
	},
}

type Check struct {
	Start    time.Time
	Stop     time.Time
	Addr     string
	Response *http.Response
	err      error
}

func (c *Check) Err() error {
	if c.err != nil {
		return c.err
	}
	if c.Response == nil {
		return errors.New("no response object returned")
	}
	return nil
}

type Report struct {
	Start  time.Time
	Stop   time.Time
	Checks []*Check
	Target string
}

func (r *Report) Failures() []*Check {
	failures := []*Check{}
	for _, check := range r.Checks {
		if check.Err() != nil {
			failures = append(failures, check)
		}
	}
	return failures
}

func (r *Report) OK() bool {
	failures := r.Failures()
	return len(failures) == 0
}

// doRequest makes an HTTP GET request to target but dials the IP specified by addr
func doRequest(target string, addr string) (*http.Response, error) {
	dialer := &net.Dialer{
		Timeout:   timeout,
		KeepAlive: timeout,
		DualStack: true,
	}
	client := http.Client{
		Transport: &http.Transport{
			DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
				return dialer.DialContext(ctx, network, addr)
			},
			TLSClientConfig:       &tls.Config{},
			DisableKeepAlives:     true,
			IdleConnTimeout:       timeout,
			TLSHandshakeTimeout:   timeout,
			ExpectContinueTimeout: 1 * time.Second,
		},
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	req, err := http.NewRequest("HEAD", target, nil)
	if err != nil {
		return nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return resp, err
	}
	return resp, err
}

// lookupAddrs finds as many IP addresses as possible for the target url
// * Use multiple resolvers (google, local, whatever) to attempt to work around
//   "clever" responses as much as possible
// * de-duplicate any addrs
func lookupAddrs(target string, resolvers []*net.Resolver) ([]string, error) {
	uri, err := url.Parse(target)
	if err != nil {
		return nil, err
	}
	port := uri.Port()
	if port == "" {
		switch uri.Scheme {
		case "http":
			port = "80"
		case "https":
			port = "443"
		default:
			return nil, fmt.Errorf("bad target URL: %s", target)
		}
	}
	uniqueAddrs := map[string]bool{}
	for _, resolver := range resolvers {
		ips, err := resolver.LookupIPAddr(context.TODO(), uri.Hostname())
		if err != nil {
			return nil, err
		}
		for _, ip := range ips {
			addr := ip.String()
			if addr == "<nil>" {
				continue
			}
			if strings.Contains(addr, ":") {
				addr = "[" + addr + "]"
			}
			if err != nil {
				return nil, err
			}
			addr = fmt.Sprintf("%s:%s", addr, port)
			uniqueAddrs[addr] = true
		}
	}
	addrs := []string{}
	for addr, _ := range uniqueAddrs {
		addrs = append(addrs, addr)
	}
	return addrs, nil
}

// getReport makes multiple HTTP GET requests to a target url (one request
// per IP addr found from DNS lookup)
func GetReport(target string, resolvers []*net.Resolver) (*Report, error) {
	addrs, err := lookupAddrs(target, resolvers)
	if err != nil {
		return nil, err
	}
	var wg sync.WaitGroup
	r := &Report{
		Start:  time.Now(),
		Target: target,
	}
	for _, addr := range addrs {
		check := &Check{
			Addr: addr,
		}
		wg.Add(1)
		go func(check *Check) {
			defer wg.Done()
			check.Start = time.Now()
			check.Response, check.err = doRequest(target, check.Addr)
			check.Stop = time.Now()
		}(check)
		r.Checks = append(r.Checks, check)
	}
	wg.Wait()
	r.Stop = time.Now()
	return r, nil
}
<commit_msg>Ignore TLS validation for ELB node checks<commit_after>package pingdumb

import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"
)

const (
	timeout = 5 * time.Second
)

var DefaultResolvers = []*net.Resolver{
	net.DefaultResolver,
	&net.Resolver{
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   timeout,
				KeepAlive: timeout,
				DualStack: true,
			}
			return dialer.DialContext(ctx, "tcp", "8.8.8.8:53")
		},
	},
	&net.Resolver{
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   timeout,
				KeepAlive: timeout,
				DualStack: true,
			}
			return dialer.DialContext(ctx, "tcp", "8.8.4.4:53")
		},
	},
}

type Check struct {
	Start    time.Time
	Stop     time.Time
	Addr     string
	Response *http.Response
	err      error
}

func (c *Check) Err() error {
	if c.err != nil {
		return c.err
	}
	if c.Response == nil {
		return errors.New("no response object returned")
	}
	return nil
}

type Report struct {
	Start  time.Time
	Stop   time.Time
	Checks []*Check
	Target string
}

func (r *Report) Failures() []*Check {
	failures := []*Check{}
	for _, check := range r.Checks {
		if check.Err() != nil {
			failures = append(failures, check)
		}
	}
	return failures
}

func (r *Report) OK() bool {
	failures := r.Failures()
	return len(failures) == 0
}

// doRequest makes an HTTP GET request to target but dials the IP specified by addr
func doRequest(target string, addr string) (*http.Response, error) {
	dialer := &net.Dialer{
		Timeout:   timeout,
		KeepAlive: timeout,
		DualStack: true,
	}
	client := http.Client{
		Transport: &http.Transport{
			DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
				return dialer.DialContext(ctx, network, addr)
			},
			TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives:     true,
			IdleConnTimeout:       timeout,
			TLSHandshakeTimeout:   timeout,
			ExpectContinueTimeout: 1 * time.Second,
		},
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	req, err := http.NewRequest("HEAD", target, nil)
	if err != nil {
		return nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return resp, err
	}
	return resp, err
}

// lookupAddrs finds as many IP addresses as possible for the target url
// * Use multiple resolvers (google, local, whatever) to attempt to work around
//   "clever" responses as much as possible
// * de-duplicate any addrs
func lookupAddrs(target string, resolvers []*net.Resolver) ([]string, error) {
	uri, err := url.Parse(target)
	if err != nil {
		return nil, err
	}
	port := uri.Port()
	if port == "" {
		switch uri.Scheme {
		case "http":
			port = "80"
		case "https":
			port = "443"
		default:
			return nil, fmt.Errorf("bad target URL: %s", target)
		}
	}
	uniqueAddrs := map[string]bool{}
	for _, resolver := range resolvers {
		ips, err := resolver.LookupIPAddr(context.TODO(), uri.Hostname())
		if err != nil {
			return nil, err
		}
		for _, ip := range ips {
			addr := ip.String()
			if addr == "<nil>" {
				continue
			}
			if strings.Contains(addr, ":") {
				addr = "[" + addr + "]"
			}
			if err != nil {
				return nil, err
			}
			addr = fmt.Sprintf("%s:%s", addr, port)
			uniqueAddrs[addr] = true
		}
	}
	addrs := []string{}
	for addr, _ := range uniqueAddrs {
		addrs = append(addrs, addr)
	}
	return addrs, nil
}

// getReport makes multiple HTTP GET requests to a target url (one request
// per IP addr found from DNS lookup)
func GetReport(target string, resolvers []*net.Resolver) (*Report, error) {
	addrs, err := lookupAddrs(target, resolvers)
	if err != nil {
		return nil, err
	}
	var wg sync.WaitGroup
	r := &Report{
		Start:  time.Now(),
		Target: target,
	}
	for _, addr := range addrs {
		check := &Check{
			Addr: addr,
		}
		wg.Add(1)
		go func(check *Check) {
			defer wg.Done()
			check.Start = time.Now()
			check.Response, check.err = doRequest(target, check.Addr)
			check.Stop = time.Now()
		}(check)
		r.Checks = append(r.Checks, check)
	}
	wg.Wait()
	r.Stop = time.Now()
	return r, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Intel Corporation
//
// 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 main

import (
	"github.com/golang/glog"

	"github.com/ciao-project/ciao/ciao-controller/types"
	"github.com/ciao-project/ciao/payloads"
	"github.com/ciao-project/ciao/uuid"
)

func validateVMWorkload(req types.Workload) error {
	// FWType must be either EFI or legacy.
	if req.FWType != string(payloads.EFI) && req.FWType != payloads.Legacy {
		return types.ErrBadRequest
	}

	// Must have storage for VMs
	if len(req.Storage) == 0 {
		return types.ErrBadRequest
	}

	return nil
}

func validateContainerWorkload(req types.Workload) error {
	// we should reject anything with ImageID set, but
	// we'll just ignore it.
	if req.ImageName == "" {
		return types.ErrBadRequest
	}

	return nil
}

func validateWorkloadStorage(req types.Workload) error {
	bootableCount := 0
	for i := range req.Storage {
		// check that a workload type is specified
		if req.Storage[i].SourceType == "" {
			return types.ErrBadRequest
		}

		// you may not request a bootable empty volume.
		if req.Storage[i].Bootable && req.Storage[i].SourceType == types.Empty {
			return types.ErrBadRequest
		}

		if req.Storage[i].ID != "" {
			// validate that the id is at least valid
			// uuid4.
			_, err := uuid.Parse(req.Storage[i].ID)
			if err != nil {
				return types.ErrBadRequest
			}

			// If we have an ID we must have a type to get it from
			if req.Storage[i].SourceType != types.Empty {
				return types.ErrBadRequest
			}
		}

		if req.Storage[i].SourceID == "" {
			// you may only use no source id with empty type
			if req.Storage[i].SourceType != types.Empty {
				return types.ErrBadRequest
			}
		}

		if req.Storage[i].Bootable {
			bootableCount++
		}
	}

	// must be at least one bootable volume
	if req.VMType == payloads.QEMU && bootableCount == 0 {
		return types.ErrBadRequest
	}

	return nil
}

// this is probably an insufficient amount of checking.
func validateWorkloadRequest(req types.Workload) error {
	// ID must be blank.
	if req.ID != "" {
		glog.V(2).Info("Invalid workload request: ID is not blank")
		return types.ErrBadRequest
	}

	// we don't validate the TenantID right now - it is passed
	// in via the ciao api, and it has passed the regex input
	// validation already. there's also a conflict with ssntp's uuid.Parse()
	// function where they assume you are using a uuid4 with '-' as
	// separator, and keystone doesn't use the '-' separator for
	// uuids.

	if req.VMType == payloads.QEMU {
		err := validateVMWorkload(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid VM workload")
			return err
		}
	} else {
		err := validateContainerWorkload(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid container workload")
			return err
		}
	}

	if req.Config == "" {
		glog.V(2).Info("Invalid workload request: config is blank")
		return types.ErrBadRequest
	}

	if len(req.Storage) > 0 {
		err := validateWorkloadStorage(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid storage")
			return err
		}
	}

	return nil
}

func (c *controller) CreateWorkload(req types.Workload) (types.Workload, error) {
	err := validateWorkloadRequest(req)
	if err != nil {
		return req, err
	}

	err = c.confirmTenant(req.TenantID)
	if err != nil {
		return req, err
	}

	req.ID = uuid.Generate().String()

	err = c.ds.AddWorkload(req)
	return req, err
}

func (c *controller) DeleteWorkload(tenantID string, workloadID string) error {
	return c.ds.DeleteWorkload(tenantID, workloadID)
}

func (c *controller) ShowWorkload(tenantID string, workloadID string) (types.Workload, error) {
	return c.ds.GetWorkload(tenantID, workloadID)
}

func (c *controller) ListWorkloads(tenantID string) ([]types.Workload, error) {
	return c.ds.GetWorkloads(tenantID)
}
<commit_msg>ciao-controller: as part of workload validation check image/volume<commit_after>// Copyright (c) 2016 Intel Corporation
//
// 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 main

import (
	"github.com/golang/glog"

	"github.com/ciao-project/ciao/ciao-controller/types"
	"github.com/ciao-project/ciao/payloads"
	"github.com/ciao-project/ciao/uuid"
)

func validateVMWorkload(req types.Workload) error {
	// FWType must be either EFI or legacy.
	if req.FWType != string(payloads.EFI) && req.FWType != payloads.Legacy {
		return types.ErrBadRequest
	}

	// Must have storage for VMs
	if len(req.Storage) == 0 {
		return types.ErrBadRequest
	}

	return nil
}

func validateContainerWorkload(req types.Workload) error {
	// we should reject anything with ImageID set, but
	// we'll just ignore it.
	if req.ImageName == "" {
		return types.ErrBadRequest
	}

	return nil
}

func (c *controller) validateWorkloadStorageSourceID(storage *types.StorageResource, tenantID string) error {
	if storage.SourceID == "" {
		// you may only use no source id with empty type
		if storage.SourceType != types.Empty {
			return types.ErrBadRequest
		}
	}

	if storage.SourceType == types.ImageService {
		_, err := c.GetImage(tenantID, storage.SourceID)
		if err != nil {
			return types.ErrBadRequest
		}
	}

	if storage.SourceType == types.VolumeService {
		_, err := c.ShowVolumeDetails(tenantID, storage.SourceID)
		if err != nil {
			return types.ErrBadRequest
		}
	}
	return nil
}

func (c *controller) validateWorkloadStorage(req types.Workload) error {
	bootableCount := 0
	for i := range req.Storage {
		// check that a workload type is specified
		if req.Storage[i].SourceType == "" {
			return types.ErrBadRequest
		}

		// you may not request a bootable empty volume.
		if req.Storage[i].Bootable && req.Storage[i].SourceType == types.Empty {
			return types.ErrBadRequest
		}

		if req.Storage[i].ID != "" {
			// validate that the id is at least valid
			// uuid4.
			_, err := uuid.Parse(req.Storage[i].ID)
			if err != nil {
				return types.ErrBadRequest
			}

			// If we have an ID we must have a type to get it from
			if req.Storage[i].SourceType != types.Empty {
				return types.ErrBadRequest
			}
		}

		err := c.validateWorkloadStorageSourceID(&req.Storage[i], req.TenantID)
		if err != nil {
			return err
		}

		if req.Storage[i].Bootable {
			bootableCount++
		}
	}

	// must be at least one bootable volume
	if req.VMType == payloads.QEMU && bootableCount == 0 {
		return types.ErrBadRequest
	}

	return nil
}

// this is probably an insufficient amount of checking.
func (c *controller) validateWorkloadRequest(req types.Workload) error {
	// ID must be blank.
	if req.ID != "" {
		glog.V(2).Info("Invalid workload request: ID is not blank")
		return types.ErrBadRequest
	}

	// we don't validate the TenantID right now - it is passed
	// in via the ciao api, and it has passed the regex input
	// validation already. there's also a conflict with ssntp's uuid.Parse()
	// function where they assume you are using a uuid4 with '-' as
	// separator, and keystone doesn't use the '-' separator for
	// uuids.

	if req.VMType == payloads.QEMU {
		err := validateVMWorkload(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid VM workload")
			return err
		}
	} else {
		err := validateContainerWorkload(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid container workload")
			return err
		}
	}

	if req.Config == "" {
		glog.V(2).Info("Invalid workload request: config is blank")
		return types.ErrBadRequest
	}

	if len(req.Storage) > 0 {
		err := c.validateWorkloadStorage(req)
		if err != nil {
			glog.V(2).Info("Invalid workload request: invalid storage")
			return err
		}
	}

	return nil
}

func (c *controller) CreateWorkload(req types.Workload) (types.Workload, error) {
	err := c.validateWorkloadRequest(req)
	if err != nil {
		return req, err
	}

	err = c.confirmTenant(req.TenantID)
	if err != nil {
		return req, err
	}

	req.ID = uuid.Generate().String()

	err = c.ds.AddWorkload(req)
	return req, err
}

func (c *controller) DeleteWorkload(tenantID string, workloadID string) error {
	return c.ds.DeleteWorkload(tenantID, workloadID)
}

func (c *controller) ShowWorkload(tenantID string, workloadID string) (types.Workload, error) {
	return c.ds.GetWorkload(tenantID, workloadID)
}

func (c *controller) ListWorkloads(tenantID string) ([]types.Workload, error) {
	return c.ds.GetWorkloads(tenantID)
}
<|endoftext|>


<commit_before>// Copyright 2017 Authors of Cilium
//
// 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 cmd

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/pkg/endpoint"

	"github.com/go-openapi/swag"
	"github.com/spf13/cobra"
)

var noHeaders bool

// endpointListCmd represents the endpoint_list command
var endpointListCmd = &cobra.Command{
	Use:   "list",
	Short: "List all endpoints",
	Run: func(cmd *cobra.Command, args []string) {
		listEndpoints()
	},
}

func init() {
	endpointCmd.AddCommand(endpointListCmd)
	endpointListCmd.Flags().BoolVar(&noHeaders, "no-headers", false, "Do not print headers")
	AddMultipleOutput(endpointListCmd)
}

func listEndpoint(w *tabwriter.Writer, ep *models.Endpoint, id string, label string) {
	var isPolicyEnabled string
	if swag.BoolValue(ep.PolicyEnabled) {
		isPolicyEnabled = "Enabled"
	} else {
		isPolicyEnabled = "Disabled"
	}
	fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
		ep.ID, isPolicyEnabled, id, label, ep.Addressing.IPV6, ep.Addressing.IPV4, ep.State)
}

func listEndpoints() {
	eps, err := client.EndpointList()
	if err != nil {
		Fatalf("cannot get endpoint list: %s\n", err)
	}

	endpoint.OrderEndpointAsc(eps)

	w := tabwriter.NewWriter(os.Stdout, 5, 0, 3, ' ', 0)

	const (
		labelsIDTitle    = "IDENTITY"
		labelsDesTitle   = "LABELS (source:key[=value])"
		ipv6Title        = "IPv6"
		ipv4Title        = "IPv4"
		endpointTitle    = "ENDPOINT"
		statusTitle      = "STATUS"
		policyTitle      = "POLICY"
		enforcementTitle = "ENFORCEMENT"
	)

	if !noHeaders {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
			endpointTitle, policyTitle, labelsIDTitle, labelsDesTitle, ipv6Title, ipv4Title, statusTitle)
		fmt.Fprintf(w, "\t%s\t\t\t\t\t\t\n", enforcementTitle)
	}

	if len(dumpOutput) > 0 {
		if err := OutputPrinter(eps); err != nil {
			os.Exit(1)
		}
		return
	}

	for _, ep := range eps {
		if ep.Identity == nil {
			listEndpoint(w, ep, "<no label id>", "")
		} else {
			id := fmt.Sprintf("%d", ep.Identity.ID)

			if len(ep.Identity.Labels) == 0 {
				listEndpoint(w, ep, id, "no labels")
			} else {
				first := true
				lbls := []string(ep.Identity.Labels)
				sort.Strings(lbls)
				for _, lbl := range lbls {
					if first {
						listEndpoint(w, ep, id, lbl)
						first = false
					} else {
						fmt.Fprintf(w, "\t\t\t%s\t\t\t\t\n", lbl)
					}
				}
			}
		}

	}
	w.Flush()
}
<commit_msg>cli: Report assigned labels instead of identity labels<commit_after>// Copyright 2017 Authors of Cilium
//
// 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 cmd

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/pkg/endpoint"

	"github.com/go-openapi/swag"
	"github.com/spf13/cobra"
)

var noHeaders bool

// endpointListCmd represents the endpoint_list command
var endpointListCmd = &cobra.Command{
	Use:   "list",
	Short: "List all endpoints",
	Run: func(cmd *cobra.Command, args []string) {
		listEndpoints()
	},
}

func init() {
	endpointCmd.AddCommand(endpointListCmd)
	endpointListCmd.Flags().BoolVar(&noHeaders, "no-headers", false, "Do not print headers")
	AddMultipleOutput(endpointListCmd)
}

func listEndpoint(w *tabwriter.Writer, ep *models.Endpoint, id string, label string) {
	var isPolicyEnabled string
	if swag.BoolValue(ep.PolicyEnabled) {
		isPolicyEnabled = "Enabled"
	} else {
		isPolicyEnabled = "Disabled"
	}
	fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
		ep.ID, isPolicyEnabled, id, label, ep.Addressing.IPV6, ep.Addressing.IPV4, ep.State)
}

func listEndpoints() {
	eps, err := client.EndpointList()
	if err != nil {
		Fatalf("cannot get endpoint list: %s\n", err)
	}

	endpoint.OrderEndpointAsc(eps)

	w := tabwriter.NewWriter(os.Stdout, 5, 0, 3, ' ', 0)

	const (
		labelsIDTitle    = "IDENTITY"
		labelsDesTitle   = "LABELS (source:key[=value])"
		ipv6Title        = "IPv6"
		ipv4Title        = "IPv4"
		endpointTitle    = "ENDPOINT"
		statusTitle      = "STATUS"
		policyTitle      = "POLICY"
		enforcementTitle = "ENFORCEMENT"
	)

	if !noHeaders {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
			endpointTitle, policyTitle, labelsIDTitle, labelsDesTitle, ipv6Title, ipv4Title, statusTitle)
		fmt.Fprintf(w, "\t%s\t\t\t\t\t\t\n", enforcementTitle)
	}

	if len(dumpOutput) > 0 {
		if err := OutputPrinter(eps); err != nil {
			os.Exit(1)
		}
		return
	}

	for _, ep := range eps {
		id := "<no label id>"
		if ep.Identity != nil {
			id = fmt.Sprintf("%d", ep.Identity.ID)
		}

		if len(ep.Labels.OrchestrationIdentity) == 0 {
			listEndpoint(w, ep, id, "no labels")
		} else {

			first := true
			lbls := ep.Labels.OrchestrationIdentity
			sort.Strings(lbls)
			for _, lbl := range lbls {
				if first {
					listEndpoint(w, ep, id, lbl)
					first = false
				} else {
					fmt.Fprintf(w, "\t\t\t%s\t\t\t\t\n", lbl)
				}
			}
		}

	}
	w.Flush()
}
<|endoftext|>


<commit_before>package libcomfo

import (
	"bufio"
	"io"
	"sync"
	"time"
)

var (
	// Package-wide serial connection Mutex
	pm = &sync.Mutex{}
)

// WaitTimeout takes a channel and a timer. If the channel reads before
// the timer expires, true is returned. If the timer expires, false is returned.
func WaitTimeout(wait <-chan bool, timeout *time.Timer) (success bool, err error) {
	select {
	case result := <-wait:
		// Operation succeeded
		return result, nil
	case <-timeout.C:
		// Time out the transaction
		return false, errTimeout
	}
}

// ScanTimeout advances the given scanner until the timer expires.
// All output found on the way is returned.
func ScanTimeout(scanner *bufio.Scanner, timer *time.Timer) (out []byte, err error) {

	done := make(chan bool)

	// Advance the scanner past one delimiter
	go func() { done <- scanner.Scan() }()

	// Wait for delimiter to appear, or time out
	if _, err := WaitTimeout(done, timer); err != nil {
		return out, err
	}

	// Return all characters found on the way to the delimiter
	out = scanner.Bytes()

	return
}

// ReadPacket scans a connection for 3 escape sequences - ack, start and end
// A Packet structure is extracted from the connection.
func ReadPacket(conn io.Reader, timer *time.Timer, expect bool) (out Packet, err error) {

	// Read the first byte in the stream
	scanner := bufio.NewScanner(conn)

	// Split function with configurable
	splitFunc := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		for i := 0; i < len(data); i++ {
			// Look for escape characters
			if data[i] == esc {
				// Look for the given byte following the escape character within bounds
				if i+1 < len(data) {
					char := data[i+1]
					switch char {
					case ack, start, end:
						// Advance the pointer past the 2nd command character
						return i + 2, data[:i], nil
					case esc:
						// Ignore double 0x07
						return i + 2, nil, nil
					default:
					}
				}
			}
		}
		return
	}

	scanner.Split(splitFunc)

	// Read until first escape sequence (ACK)
	pr, err := ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Found bytes before ACK
	if len(pr) != 0 {
		return out, errScanInput
	}

	// We're not expecting data (only ACK), return
	if !expect {
		return
	}
	// Read second escape sequence (start)
	pr, err = ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Found bytes between ACK and packet start
	if len(pr) != 0 {
		return out, errScanInput
	}

	// Read second escape sequence (data + stop)
	pr, err = ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Abort on invalid input
	if len(pr) > 0 && len(pr) < 4 {
		return out, errTooShort
	}

	// Decode the payload
	if len(pr) >= 4 {
		out, err = UnmarshalPacket(pr)
		if err != nil {
			return out, err
		}
	}

	return
}

// WritePacket serializes a Packet into wire representation, wrapped
// in start and end sequences, and writes to the given connection.
func WritePacket(in Packet, conn io.Writer) (out bool, err error) {

	// Get wire representation of the given Packet
	// TODO: Wrap original error and return errMarshalPacket to the caller
	pb, err := MarshalPacket(in)
	if err != nil {
		return out, err
	}

	// Wrap start and end escape sequences
	wr := append(pktStart, pb...)
	wr = append(wr, pktEnd...)

	// Write slice to connection
	// TODO: Wrap original error and return errWrite to the caller
	_, err = conn.Write(wr)
	if err != nil {
		return false, err
	}

	return true, nil
}

// WriteAck writes an ACK response to a connection.
func WriteAck(conn io.Writer) (out bool, err error) {
	num, err := conn.Write(pktAck)
	if err != nil {
		return false, err
	}

	if num != len(pktAck) {
		return false, errAck
	}

	return
}

// QueryPacket locks the package-wide mutex, writes the given packet to
// the connection, starts the timeout timer, reads the response back from
// the connection, validates the response sequence (command) number and sends
// an ACK to the remote.
func QueryPacket(in Packet, conn io.ReadWriter) (out Packet, err error) {

	// Take out lock - start critical section
	pm.Lock()
	defer pm.Unlock()

	// Write the Packet to the connection
	if _, err := WritePacket(in, conn); err != nil {
		return out, err
	}

	// Start a query-scoped timeout
	timer := time.NewTimer(time.Second)

	// Read packet from the remote
	out, err = ReadPacket(conn, timer, in.Expect)
	if err != nil {
		return out, err
	}

	// Check for the correct response command (request command + 1)
	if in.Expect && out.Command != in.Command+1 {
		return out, errInvalidResponse
	}

	// Send ACK
	_, err = WriteAck(conn)

	// Return query result
	return out, err
}
<commit_msg>libcomfo - ScanTimeout: correctly skip double 0x07 in splitFunc<commit_after>package libcomfo

import (
	"bufio"
	"io"
	"sync"
	"time"
)

var (
	// Package-wide serial connection Mutex
	pm = &sync.Mutex{}
)

// WaitTimeout takes a channel and a timer. If the channel reads before
// the timer expires, true is returned. If the timer expires, false is returned.
func WaitTimeout(wait <-chan bool, timeout *time.Timer) (success bool, err error) {
	select {
	case result := <-wait:
		// Operation succeeded
		return result, nil
	case <-timeout.C:
		// Time out the transaction
		return false, errTimeout
	}
}

// ScanTimeout advances the given scanner until the timer expires.
// All output found on the way is returned.
func ScanTimeout(scanner *bufio.Scanner, timer *time.Timer) (out []byte, err error) {

	done := make(chan bool)

	// Advance the scanner past one delimiter
	go func() { done <- scanner.Scan() }()

	// Wait for delimiter to appear, or time out
	if _, err := WaitTimeout(done, timer); err != nil {
		return out, err
	}

	// Return all characters found on the way to the delimiter
	out = scanner.Bytes()

	return
}

// ReadPacket scans a connection for 3 escape sequences - ack, start and end
// A Packet structure is extracted from the connection.
func ReadPacket(conn io.Reader, timer *time.Timer, expect bool) (out Packet, err error) {

	scanner := bufio.NewScanner(conn)

	// Split function for splitting a byte slice on ACK, start and end sequences.
	// Double 0x07 characters (escaped 0x07 values) are ignored here.
	splitFunc := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		for i := 0; i < len(data); i++ {
			// Look for escape characters
			if data[i] == esc {
				// Look for the given byte following the escape character within bounds
				if i+1 < len(data) {
					char := data[i+1]
					switch char {
					case ack, start, end:
						// Advance the pointer past the 2nd command character
						return i + 2, data[:i], nil
					default:
					}
				}
			}
		}
		return
	}

	scanner.Split(splitFunc)

	// Read until first escape sequence (ACK)
	pr, err := ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Found bytes before ACK
	if len(pr) != 0 {
		return out, errScanInput
	}

	// We're not expecting data (only ACK), return
	if !expect {
		return
	}

	// Read second escape sequence (start)
	pr, err = ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Found bytes between ACK and packet start
	if len(pr) != 0 {
		return out, errScanInput
	}

	// Read second escape sequence (data + stop)
	pr, err = ScanTimeout(scanner, timer)
	if err != nil {
		return out, err
	}

	// Abort on invalid input
	if len(pr) > 0 && len(pr) < 4 {
		return out, errTooShort
	}

	// Decode the payload
	if len(pr) >= 4 {
		out, err = UnmarshalPacket(pr)
		if err != nil {
			return out, err
		}
	}

	return
}

// WritePacket serializes a Packet into wire representation, wrapped
// in start and end sequences, and writes to the given connection.
func WritePacket(in Packet, conn io.Writer) (out bool, err error) {

	// Get wire representation of the given Packet
	// TODO: Wrap original error and return errMarshalPacket to the caller
	pb, err := MarshalPacket(in)
	if err != nil {
		return out, err
	}

	// Wrap start and end escape sequences
	wr := append(pktStart, pb...)
	wr = append(wr, pktEnd...)

	// Write slice to connection
	// TODO: Wrap original error and return errWrite to the caller
	_, err = conn.Write(wr)
	if err != nil {
		return false, err
	}

	return true, nil
}

// WriteAck writes an ACK response to a connection.
func WriteAck(conn io.Writer) (out bool, err error) {
	num, err := conn.Write(pktAck)
	if err != nil {
		return false, err
	}

	if num != len(pktAck) {
		return false, errAck
	}

	return
}

// QueryPacket locks the package-wide mutex, writes the given packet to
// the connection, starts the timeout timer, reads the response back from
// the connection, validates the response sequence (command) number and sends
// an ACK to the remote.
func QueryPacket(in Packet, conn io.ReadWriter) (out Packet, err error) {

	// Take out lock - start critical section
	pm.Lock()
	defer pm.Unlock()

	// Write the Packet to the connection
	if _, err := WritePacket(in, conn); err != nil {
		return out, err
	}

	// Start a query-scoped timeout
	timer := time.NewTimer(time.Second)

	// Read packet from the remote
	out, err = ReadPacket(conn, timer, in.Expect)
	if err != nil {
		return out, err
	}

	// Check for the correct response command (request command + 1)
	if in.Expect && out.Command != in.Command+1 {
		return out, errInvalidResponse
	}

	// Send ACK
	_, err = WriteAck(conn)

	// Return query result
	return out, err
}
<|endoftext|>