<commit_before>package ninja

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	TOKEN_ADD                 = "add"
	TOKEN_ASSIGN              = "assign"
	TOKEN_COLON               = "colon"
	TOKEN_COMMA               = "comma"
	TOKEN_DIV                 = "div"
	TOKEN_DOT                 = "dot"
	TOKEN_EQ                  = "eq"
	TOKEN_FLOORDIV            = "floordiv"
	TOKEN_GT                  = "gt"
	TOKEN_GTEQ                = "gteq"
	TOKEN_LBRACE              = "lbrace"
	TOKEN_LBRACKET            = "lbracket"
	TOKEN_LPAREN              = "lparen"
	TOKEN_LT                  = "lt"
	TOKEN_LTEQ                = "lteq"
	TOKEN_MOD                 = "mod"
	TOKEN_MUL                 = "mul"
	TOKEN_NE                  = "ne"
	TOKEN_PIPE                = "pipe"
	TOKEN_POW                 = "pow"
	TOKEN_RBRACE              = "rbrace"
	TOKEN_RBRACKET            = "rbracket"
	TOKEN_RPAREN              = "rparen"
	TOKEN_SEMICOLON           = "semicolon"
	TOKEN_SUB                 = "sub"
	TOKEN_TILDE               = "tilde"
	TOKEN_WHITESPACE          = "whitespace"
	TOKEN_FLOAT               = "float"
	TOKEN_INTEGER             = "integer"
	TOKEN_NAME                = "name"
	TOKEN_STRING              = "string"
	TOKEN_OPERATOR            = "operator"
	TOKEN_BLOCK_BEGIN         = "block_begin"
	TOKEN_BLOCK_END           = "block_end"
	TOKEN_VARIABLE_BEGIN      = "variable_begin"
	TOKEN_VARIABLE_END        = "variable_end"
	TOKEN_RAW_BEGIN           = "raw_begin"
	TOKEN_RAW_END             = "raw_end"
	TOKEN_COMMENT_BEGIN       = "comment_begin"
	TOKEN_COMMENT_END         = "comment_end"
	TOKEN_COMMENT             = "comment"
	TOKEN_LINESTATEMENT_BEGIN = "linestatement_begin"
	TOKEN_LINESTATEMENT_END   = "linestatement_end"
	TOKEN_LINECOMMENT_BEGIN   = "linecomment_begin"
	TOKEN_LINECOMMENT_END     = "linecomment_end"
	TOKEN_LINECOMMENT         = "linecomment"
	TOKEN_DATA                = "data"
	TOKEN_INITIAL             = "initial"
	TOKEN_EOF                 = "eof"
)

var operators = map[string]string{
	`\+`:   TOKEN_ADD,
	`\-`:   TOKEN_SUB,
	`\/`:   TOKEN_DIV,
	`\/\/`: TOKEN_FLOORDIV,
	`\*`:   TOKEN_MUL,
	`\%`:   TOKEN_MOD,
	`\*\*`: TOKEN_POW,
	`\~`:   TOKEN_TILDE,
	`\[`:   TOKEN_LBRACKET,
	`\]`:   TOKEN_RBRACKET,
	`\(`:   TOKEN_LPAREN,
	`\)`:   TOKEN_RPAREN,
	`\{`:   TOKEN_LBRACE,
	`\}`:   TOKEN_RBRACE,
	`\=\=`: TOKEN_EQ,
	`\!\=`: TOKEN_NE,
	`\>`:   TOKEN_GT,
	`\>\=`: TOKEN_GTEQ,
	`\<`:   TOKEN_LT,
	`\<\=`: TOKEN_LTEQ,
	`\=`:   TOKEN_ASSIGN,
	`\.`:   TOKEN_DOT,
	`\:`:   TOKEN_COLON,
	`\|`:   TOKEN_PIPE,
	`\,`:   TOKEN_COMMA,
	`\;`:   TOKEN_SEMICOLON,
}

func compile(x string) *regexp.Regexp {
	x = `(?ms)^` + x
	r, _ := regexp.Compile(x)
	return r
}

type Token struct {
	lineno int
	tp     string
	value  string
}

type StateToken struct {
	regex    *regexp.Regexp
	tokens   []string
	newState string
}

type TokenStream struct {
}

type Lexer struct {
	rules map[string][]*StateToken
}

func NewLexer() *Lexer {
	lexer := new(Lexer)

	whitespaceRe, _ := regexp.Compile(`^\s+`)
	floatRe, _ := regexp.Compile(`^\d+\.\d+`)
	integerRe, _ := regexp.Compile(`^\d+`)
	nameRe, _ := regexp.Compile(`^\b[a-zA-Z_][a-zA-Z0-9_]*\b`)
	stringRe, _ := regexp.Compile(`(?s)^('([^'\\]*(?:\\.[^'\\]*)*)'|"([^"\\]*(?:\\.[^"\\]*)*)")`)
	keyArray := make([]string, 0)
	for k, _ := range operators {
		keyArray = append(keyArray, k)
	}
	operatorRe, _ := regexp.Compile(fmt.Sprintf("^(%s)", strings.Join(keyArray, "|")))

	tagRules := []*StateToken{
		&StateToken{whitespaceRe, []string{TOKEN_WHITESPACE}, "nil"},
		&StateToken{floatRe, []string{TOKEN_FLOAT}, "nil"},
		&StateToken{integerRe, []string{TOKEN_INTEGER}, "nil"},
		&StateToken{nameRe, []string{TOKEN_NAME}, "nil"},
		&StateToken{stringRe, []string{TOKEN_STRING}, "nil"},
		&StateToken{operatorRe, []string{TOKEN_OPERATOR}, "nil"},
	}

	//lstripRe := `^[ \t]*`
	//noLstripRe := `+`
	//blockPrefixRe := fmt.Sprintf(`%s{%|{%\+?`, lstripRe)

	lexer.rules = make(map[string][]*StateToken)

	rootTagRules := map[string]string{
		"comment":  "{#",
		"block":    "{%",
		"variable": "{{",
	}
	regexArray := []string{}
	regexArray = append(regexArray, `(?P<raw_begin>(?:{%)\s*raw\s*(?:%}))`)
	for n, r := range rootTagRules {
		regex := fmt.Sprintf(`(?P<%s_begin>%s)`, n, r)
		regexArray = append(regexArray, regex)
	}
	lexer.rules["root"] = []*StateToken{
		&StateToken{
			compile(fmt.Sprintf(`(.*?)(?:%s)`, strings.Join(regexArray, `|`))),
			[]string{TOKEN_DATA, "#bygroup"},
			"#bygroup",
		},
		&StateToken{
			compile(".+"),
			[]string{TOKEN_DATA},
			"nil",
		},
	}

	lexer.rules[TOKEN_COMMENT_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)((?:#}))`),
			[]string{TOKEN_COMMENT, TOKEN_COMMENT_END},
			"#pop",
		},
		&StateToken{
			compile("(.)"),
			[]string{"Failure"},
			"nil",
		},
	}

	lexer.rules[TOKEN_BLOCK_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`(?:%})`),
			[]string{TOKEN_BLOCK_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_VARIABLE_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`}}`),
			[]string{TOKEN_VARIABLE_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_RAW_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)((?:{%)\s*endraw\s*(?:%}))`),
			[]string{TOKEN_DATA, TOKEN_RAW_END},
			"#pop",
		},
		&StateToken{
			compile("(.)"),
			[]string{"Failure"},
			"nil",
		},
	}

	lexer.rules[TOKEN_LINESTATEMENT_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`\s*(\n|$)`),
			[]string{TOKEN_LINESTATEMENT_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_LINECOMMENT_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)()(?:\n|$)`),
			[]string{TOKEN_LINECOMMENT, TOKEN_LINECOMMENT_END},
			"#pop",
		},
	}

	return lexer
}

func (lexer *Lexer) tokeniter(source string) chan *Token {
	c := make(chan *Token)

	go func() {
		lines := strings.Split(source, "\n")
		if lines[len(lines)-1] == "" {
			lines = lines[0 : len(lines)-1]
		}
		source = strings.Join(lines, "\n")
		pos := 0
		lineno := 1
		stack := []string{"root"}
		//state := "root"
		// stack = append(stack, "en")
		stateTokens := lexer.rules[stack[len(stack)-1]]
		//sourceLength := len(source)

		balancingStack := make([]string, 0)

		for {
			breaked := false
			for _, stateToken := range stateTokens {
				regex, tokens, newState := stateToken.regex, stateToken.tokens, stateToken.newState
				m := regex.MatchString(source)
				index := regex.FindStringIndex(source)
				if m == false {
					continue
				}
				if len(balancingStack) > 0 && (tokens[0] == "variable_end" || tokens[0] == "block_end" || tokens[0] == "linestatement_end") {
					continue
				}

				if len(tokens) > 1 {
					for idx, token := range tokens {
						if token == "#bygroup" {
							subMap := FindStringSubmatchMap(regex, source)
							for key, value := range subMap {
								c <- &Token{lineno, key, value}
								lineno += strings.Count(value, "\n")
								break
							}
						} else {
							data := regex.FindStringSubmatch(source)[idx+1]
							if data != "" || (token != TOKEN_WHITESPACE && token != TOKEN_DATA && token != TOKEN_COMMENT && token != TOKEN_LINECOMMENT) {
								c <- &Token{lineno, token, data}
							}
							lineno += strings.Count(data, "\n")
						}
					}
				} else {
					token := tokens[0]
					data := regex.FindStringSubmatch(source)[0]
					if token == "operator" {
						if data == "{" {
							balancingStack = append(balancingStack, "}")
						} else if data == "(" {
							balancingStack = append(balancingStack, ")")
						} else if data == "[" {
							balancingStack = append(balancingStack, "]")
						} else if data == "}" || data == ")" || data == "]" {
							balancingStack = balancingStack[:len(balancingStack)-1]
						}
					}
					if data != "" || (token != TOKEN_WHITESPACE && token != TOKEN_DATA && token != TOKEN_COMMENT && token != TOKEN_LINECOMMENT) {
						c <- &Token{lineno, token, data}
					}
					lineno += strings.Count(data, "\n")
				}

				pos2 := index[1]

				if newState != "nil" {
					if newState == "#pop" {
						stack = stack[:len(stack)-1]
					} else if newState == "#bygroup" {
						subMap := FindStringSubmatchMap(regex, source)
						for key, _ := range subMap {
							stack = append(stack, key)
							break
						}
					} else {
						stack = append(stack, newState)
					}
					stateTokens = lexer.rules[stack[len(stack)-1]]
				}

				pos = pos2
				source = source[pos:]
				breaked = true
				break
			}
			if !breaked {
				break
				//panic("weird")
			}
		}
		close(c)
	}()

	return c
}

func (lexer *Lexer) tokenize(source string) chan *Token {
	stream := lexer.tokeniter(source)
	return stream
}
<commit_msg>Improved lexer<commit_after>package ninja

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	TOKEN_ADD                 = "add"
	TOKEN_ASSIGN              = "assign"
	TOKEN_COLON               = "colon"
	TOKEN_COMMA               = "comma"
	TOKEN_DIV                 = "div"
	TOKEN_DOT                 = "dot"
	TOKEN_EQ                  = "eq"
	TOKEN_FLOORDIV            = "floordiv"
	TOKEN_GT                  = "gt"
	TOKEN_GTEQ                = "gteq"
	TOKEN_LBRACE              = "lbrace"
	TOKEN_LBRACKET            = "lbracket"
	TOKEN_LPAREN              = "lparen"
	TOKEN_LT                  = "lt"
	TOKEN_LTEQ                = "lteq"
	TOKEN_MOD                 = "mod"
	TOKEN_MUL                 = "mul"
	TOKEN_NE                  = "ne"
	TOKEN_PIPE                = "pipe"
	TOKEN_POW                 = "pow"
	TOKEN_RBRACE              = "rbrace"
	TOKEN_RBRACKET            = "rbracket"
	TOKEN_RPAREN              = "rparen"
	TOKEN_SEMICOLON           = "semicolon"
	TOKEN_SUB                 = "sub"
	TOKEN_TILDE               = "tilde"
	TOKEN_WHITESPACE          = "whitespace"
	TOKEN_FLOAT               = "float"
	TOKEN_INTEGER             = "integer"
	TOKEN_NAME                = "name"
	TOKEN_STRING              = "string"
	TOKEN_OPERATOR            = "operator"
	TOKEN_BLOCK_BEGIN         = "block_begin"
	TOKEN_BLOCK_END           = "block_end"
	TOKEN_VARIABLE_BEGIN      = "variable_begin"
	TOKEN_VARIABLE_END        = "variable_end"
	TOKEN_RAW_BEGIN           = "raw_begin"
	TOKEN_RAW_END             = "raw_end"
	TOKEN_COMMENT_BEGIN       = "comment_begin"
	TOKEN_COMMENT_END         = "comment_end"
	TOKEN_COMMENT             = "comment"
	TOKEN_LINESTATEMENT_BEGIN = "linestatement_begin"
	TOKEN_LINESTATEMENT_END   = "linestatement_end"
	TOKEN_LINECOMMENT_BEGIN   = "linecomment_begin"
	TOKEN_LINECOMMENT_END     = "linecomment_end"
	TOKEN_LINECOMMENT         = "linecomment"
	TOKEN_DATA                = "data"
	TOKEN_INITIAL             = "initial"
	TOKEN_EOF                 = "eof"
)

var operators_map = map[string]string{
	`\+`:   TOKEN_ADD,
	`\-`:   TOKEN_SUB,
	`\/`:   TOKEN_DIV,
	`\/\/`: TOKEN_FLOORDIV,
	`\*`:   TOKEN_MUL,
	`\%`:   TOKEN_MOD,
	`\*\*`: TOKEN_POW,
	`\~`:   TOKEN_TILDE,
	`\[`:   TOKEN_LBRACKET,
	`\]`:   TOKEN_RBRACKET,
	`\(`:   TOKEN_LPAREN,
	`\)`:   TOKEN_RPAREN,
	`\{`:   TOKEN_LBRACE,
	`\}`:   TOKEN_RBRACE,
	`\=\=`: TOKEN_EQ,
	`\!\=`: TOKEN_NE,
	`\>`:   TOKEN_GT,
	`\>\=`: TOKEN_GTEQ,
	`\<`:   TOKEN_LT,
	`\<\=`: TOKEN_LTEQ,
	`\=`:   TOKEN_ASSIGN,
	`\.`:   TOKEN_DOT,
	`\:`:   TOKEN_COLON,
	`\|`:   TOKEN_PIPE,
	`\,`:   TOKEN_COMMA,
	`\;`:   TOKEN_SEMICOLON,
}

var operatorsArray = []string{`\/\/`, `\*\*`, `\=\=`, `\!\=`, `\>\=`, `\<\=`, `\+`, `\-`, `\/`, `\*`, `\%`, `\~`, `\[`, `\]`, `\(`, `\)`, `\{`, `\}`, `\>`, `\<`, `\=`, `\.`, `\:`, `\|`, `\,`, `\;`}

var ignoredTokens = map[string]bool{
	TOKEN_COMMENT_BEGIN:     true,
	TOKEN_COMMENT:           true,
	TOKEN_COMMENT_END:       true,
	TOKEN_WHITESPACE:        true,
	TOKEN_LINECOMMENT_BEGIN: true,
	TOKEN_LINECOMMENT_END:   true,
	TOKEN_LINECOMMENT:       true,
}

var ignoreIfEmpty = map[string]bool{
	TOKEN_WHITESPACE:  true,
	TOKEN_DATA:        true,
	TOKEN_COMMENT:     true,
	TOKEN_LINECOMMENT: true,
}

func compile(x string) *regexp.Regexp {
	x = `(?ms)^` + x
	r := regexp.MustCompile(x)
	return r
}

type Token struct {
	lineno int
	tp     string
	value  string
}

type StateToken struct {
	regex    *regexp.Regexp
	tokens   []string
	newState string
}

type TokenStream struct {
}

type Lexer struct {
	rules map[string][]*StateToken
}

func NewLexer() *Lexer {
	lexer := new(Lexer)

	whitespaceRe := regexp.MustCompile(`^\s+`)
	floatRe := regexp.MustCompile(`^\d+\.\d+`)
	integerRe := regexp.MustCompile(`^\d+`)
	nameRe := regexp.MustCompile(`^\b[a-zA-Z_][a-zA-Z0-9_]*\b`)
	stringRe := regexp.MustCompile(`(?s)^('([^'\\]*(?:\\.[^'\\]*)*)'|"([^"\\]*(?:\\.[^"\\]*)*)")`)
	operatorRe := regexp.MustCompile(fmt.Sprintf("^(%s)", strings.Join(operatorsArray, "|")))

	tagRules := []*StateToken{
		&StateToken{whitespaceRe, []string{TOKEN_WHITESPACE}, "nil"},
		&StateToken{floatRe, []string{TOKEN_FLOAT}, "nil"},
		&StateToken{integerRe, []string{TOKEN_INTEGER}, "nil"},
		&StateToken{nameRe, []string{TOKEN_NAME}, "nil"},
		&StateToken{stringRe, []string{TOKEN_STRING}, "nil"},
		&StateToken{operatorRe, []string{TOKEN_OPERATOR}, "nil"},
	}

	//lstripRe := `^[ \t]*`
	//noLstripRe := `+`
	//blockPrefixRe := fmt.Sprintf(`%s{%|{%\+?`, lstripRe)

	lexer.rules = make(map[string][]*StateToken)

	rootTagRules := map[string]string{
		"comment":  "{#",
		"block":    "{%",
		"variable": "{{",
	}
	regexArray := []string{}
	regexArray = append(regexArray, `(?P<raw_begin>(?:{%)\s*raw\s*(?:%}))`)
	for n, r := range rootTagRules {
		regex := fmt.Sprintf(`(?P<%s_begin>%s)`, n, r)
		regexArray = append(regexArray, regex)
	}
	lexer.rules["root"] = []*StateToken{
		&StateToken{
			compile(fmt.Sprintf(`(.*?)(?:%s)`, strings.Join(regexArray, `|`))),
			[]string{TOKEN_DATA, "#bygroup"},
			"#bygroup",
		},
		&StateToken{
			compile(".+"),
			[]string{TOKEN_DATA},
			"nil",
		},
	}

	lexer.rules[TOKEN_COMMENT_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)((?:#}))`),
			[]string{TOKEN_COMMENT, TOKEN_COMMENT_END},
			"#pop",
		},
		&StateToken{
			compile("(.)"),
			[]string{"Failure: Missing end of comment tag"},
			"nil",
		},
	}

	lexer.rules[TOKEN_BLOCK_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`(?:%})`),
			[]string{TOKEN_BLOCK_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_VARIABLE_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`}}`),
			[]string{TOKEN_VARIABLE_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_RAW_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)((?:{%)\s*endraw\s*(?:%}))`),
			[]string{TOKEN_DATA, TOKEN_RAW_END},
			"#pop",
		},
		&StateToken{
			compile("(.)"),
			[]string{"Failure: Missing end of raw directive"},
			"nil",
		},
	}

	lexer.rules[TOKEN_LINESTATEMENT_BEGIN] = append([]*StateToken{
		&StateToken{
			compile(`\s*(\n|$)`),
			[]string{TOKEN_LINESTATEMENT_END},
			"#pop",
		},
	}, tagRules...)

	lexer.rules[TOKEN_LINECOMMENT_BEGIN] = []*StateToken{
		&StateToken{
			compile(`(.*?)()(?:\n|$)`),
			[]string{TOKEN_LINECOMMENT, TOKEN_LINECOMMENT_END},
			"#pop",
		},
	}

	return lexer
}

func (lexer *Lexer) tokeniter(source string) chan *Token {
	c := make(chan *Token)

	go func() {
		lines := strings.Split(source, "\n")
		if lines[len(lines)-1] == "" {
			lines = lines[0 : len(lines)-1]
		}
		source = strings.Join(lines, "\n")
		pos := 0
		lineno := 1
		stack := []string{"root"}
		//state := "root"
		// stack = append(stack, "en")
		stateTokens := lexer.rules[stack[len(stack)-1]]
		//sourceLength := len(source)

		balancingStack := make([]string, 0)

		for {
			breaked := false
			for _, stateToken := range stateTokens {
				regex, tokens, newState := stateToken.regex, stateToken.tokens, stateToken.newState
				m := regex.MatchString(source)
				index := regex.FindStringIndex(source)
				if m == false {
					continue
				}
				if len(balancingStack) > 0 && (tokens[0] == "variable_end" || tokens[0] == "block_end" || tokens[0] == "linestatement_end") {
					continue
				}

				if len(tokens) > 1 {
					for idx, token := range tokens {
						if token == "#bygroup" {
							subMap := FindStringSubmatchMap(regex, source)
							if len(subMap) <= 0 {
								panic("Can't resolve token, no group matched")
							}
							for key, value := range subMap {
								c <- &Token{lineno, key, value}
								lineno += strings.Count(value, "\n")
								break
							}
						} else {
							data := regex.FindStringSubmatch(source)[idx+1]
							if data != "" || !ignoreIfEmpty[token] {
								c <- &Token{lineno, token, data}
							}
							lineno += strings.Count(data, "\n")
						}
					}
				} else {
					token := tokens[0]
					if strings.HasPrefix(token, "Failure") {
						panic(token)
					}
					data := regex.FindString(source)
					if token == "operator" {
						if data == "{" {
							balancingStack = append(balancingStack, "}")
						} else if data == "(" {
							balancingStack = append(balancingStack, ")")
						} else if data == "[" {
							balancingStack = append(balancingStack, "]")
						} else if data == "}" || data == ")" || data == "]" {
							if len(balancingStack) <= 0 {
								panic("unexpected '" + data + "'")
							}
							expectedOp := balancingStack[len(balancingStack)-1]
							if expectedOp != data {
								panic(fmt.Sprintf("unexpected '%s', expected '%s'", data, expectedOp))
							}
							balancingStack = balancingStack[:len(balancingStack)-1]
						}
					}
					if data != "" || !ignoreIfEmpty[token] {
						c <- &Token{lineno, token, data}
					}
					lineno += strings.Count(data, "\n")
				}

				pos2 := index[1]

				if newState != "nil" {
					if newState == "#pop" {
						stack = stack[:len(stack)-1]
					} else if newState == "#bygroup" {
						subMap := FindStringSubmatchMap(regex, source)
						if len(subMap) <= 0 {
							panic("Can't resolve new state, no group matched")
						}
						for key, _ := range subMap {
							stack = append(stack, key)
							break
						}
					} else {
						stack = append(stack, newState)
					}
					stateTokens = lexer.rules[stack[len(stack)-1]]
				} else if pos2 == pos {
					panic("empty string yielded and without stack change")
				}

				pos = pos2
				source = source[pos:]
				breaked = true
				break
			}
			if !breaked {
				if len(source) <= 0 {
					break
				}
				panic(fmt.Sprintf("unexpected char %s at %d", source[0], lineno))
			}
		}
		close(c)
	}()

	return c
}

func (lexer *Lexer) tokenize(source string) chan *Token {
	stream := lexer.tokeniter(source)
	return stream
}
<|endoftext|>


<commit_before>// Copyright 2018 The gVisor Authors.
//
// 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.

// +build race

package filter

import (
	"syscall"

	"gvisor.dev/gvisor/pkg/log"
	"gvisor.dev/gvisor/pkg/seccomp"
)

// instrumentationFilters returns additional filters for syscalls used by TSAN.
func instrumentationFilters() seccomp.SyscallRules {
	log.Warningf("*** SECCOMP WARNING: TSAN is enabled: syscall filters less restrictive!")
	return seccomp.SyscallRules{
		syscall.SYS_BRK:             {},
		syscall.SYS_CLONE:           {},
		syscall.SYS_FUTEX:           {},
		syscall.SYS_MADVISE:         {},
		syscall.SYS_MMAP:            {},
		syscall.SYS_MUNLOCK:         {},
		syscall.SYS_NANOSLEEP:       {},
		syscall.SYS_OPEN:            {},
		syscall.SYS_SET_ROBUST_LIST: {},
		// Used within glibc's malloc.
		syscall.SYS_TIME: {},
	}
}
<commit_msg>Add openat() to list of permitted syscalls in gotsan runs.<commit_after>// Copyright 2018 The gVisor Authors.
//
// 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.

// +build race

package filter

import (
	"syscall"

	"gvisor.dev/gvisor/pkg/log"
	"gvisor.dev/gvisor/pkg/seccomp"
)

// instrumentationFilters returns additional filters for syscalls used by TSAN.
func instrumentationFilters() seccomp.SyscallRules {
	log.Warningf("*** SECCOMP WARNING: TSAN is enabled: syscall filters less restrictive!")
	return seccomp.SyscallRules{
		syscall.SYS_BRK:             {},
		syscall.SYS_CLONE:           {},
		syscall.SYS_FUTEX:           {},
		syscall.SYS_MADVISE:         {},
		syscall.SYS_MMAP:            {},
		syscall.SYS_MUNLOCK:         {},
		syscall.SYS_NANOSLEEP:       {},
		syscall.SYS_OPEN:            {},
		syscall.SYS_OPENAT:          {},
		syscall.SYS_SET_ROBUST_LIST: {},
		// Used within glibc's malloc.
		syscall.SYS_TIME: {},
	}
}
<|endoftext|>


<commit_before>package capture_output

// TODO: Capture artifacts too

import (
	git "github.com/libgit2/git2go"
	"github.com/tbd-ci/tbd/git/tmpdir"
	"os/exec"
	"strings"
	"testing"
)

func testHarness(
	cmd *exec.Cmd,
	cb func(*git.Repository, *git.Tree),
) {
	err := git_tmpdir.GitTmpDir("tbd-capture-test", func(repo *git.Repository) {
		cap := Capture{
			Cmd:        cmd,
			Repository: repo,
		}
		treeOid := cap.Worktree()

		tree, err := repo.LookupTree(treeOid)
		if err != nil {
			panic(err)
		}
		cb(repo, tree)
	})
	if err != nil {
		panic(err)
	}
}

// Test that a process can have output captured
func TestCapture(t *testing.T) {
	runner := `
		echo 'stdout'
		echo 'stderr' 1>&2
		sleep 0.1
		echo 'stdout'
		echo 'stderr' 1>&2
	`
	testHarness(
		exec.Command("bash", "-c", runner),
		func(repo *git.Repository, tree *git.Tree) {
			eq(
				t,
				string(lookup(repo, tree.EntryByName("STDOUT").Id).Contents()),
				"stdout\nstdout\n",
			)
			eq(
				t,
				string(lookup(repo, tree.EntryByName("STDERR").Id).Contents()),
				"stderr\nstderr\n",
			)
			contents := string(lookup(repo, tree.EntryByName("OUTPUT").Id).Contents())
			outs := strings.Count(contents, "stdout")
			if outs != 2 {
				t.Errorf(
					"Expected %s to have 2 copies of %s, had %d",
					contents,
					"stdout",
					outs,
				)
			}
			errs := strings.Count(contents, "stderr")
			if errs != 2 {
				t.Errorf(
					"Expected %s to have 2 copies of %s, had %d",
					contents,
					"stderr",
					errs,
				)
			}
		},
	)
}

func lookup(repo *git.Repository, id *git.Oid) *git.Blob {
	combined, err := repo.LookupBlob(id)
	if err != nil {
		panic(err)
	}
	return combined
}

func eq(t *testing.T, actual, expected string) {
	if actual != expected {
		t.Errorf("Expected '%s' to be '%s'", actual, expected)
	}
}
<commit_msg>Clarify what capture_output *shouldn’t* do<commit_after>package capture_output

// TODO: Capture artifacts too (no, not in this package)

import (
	git "github.com/libgit2/git2go"
	"github.com/tbd-ci/tbd/git/tmpdir"
	"os/exec"
	"strings"
	"testing"
)

func testHarness(
	cmd *exec.Cmd,
	cb func(*git.Repository, *git.Tree),
) {
	err := git_tmpdir.GitTmpDir("tbd-capture-test", func(repo *git.Repository) {
		cap := Capture{
			Cmd:        cmd,
			Repository: repo,
		}
		treeOid := cap.Worktree()

		tree, err := repo.LookupTree(treeOid)
		if err != nil {
			panic(err)
		}
		cb(repo, tree)
	})
	if err != nil {
		panic(err)
	}
}

// Test that a process can have output captured
func TestCapture(t *testing.T) {
	runner := `
		echo 'stdout'
		echo 'stderr' 1>&2
		sleep 0.1
		echo 'stdout'
		echo 'stderr' 1>&2
	`
	testHarness(
		exec.Command("bash", "-c", runner),
		func(repo *git.Repository, tree *git.Tree) {
			eq(
				t,
				string(lookup(repo, tree.EntryByName("STDOUT").Id).Contents()),
				"stdout\nstdout\n",
			)
			eq(
				t,
				string(lookup(repo, tree.EntryByName("STDERR").Id).Contents()),
				"stderr\nstderr\n",
			)
			contents := string(lookup(repo, tree.EntryByName("OUTPUT").Id).Contents())
			outs := strings.Count(contents, "stdout")
			if outs != 2 {
				t.Errorf(
					"Expected %s to have 2 copies of %s, had %d",
					contents,
					"stdout",
					outs,
				)
			}
			errs := strings.Count(contents, "stderr")
			if errs != 2 {
				t.Errorf(
					"Expected %s to have 2 copies of %s, had %d",
					contents,
					"stderr",
					errs,
				)
			}
		},
	)
}

func lookup(repo *git.Repository, id *git.Oid) *git.Blob {
	combined, err := repo.LookupBlob(id)
	if err != nil {
		panic(err)
	}
	return combined
}

func eq(t *testing.T, actual, expected string) {
	if actual != expected {
		t.Errorf("Expected '%s' to be '%s'", actual, expected)
	}
}
<|endoftext|>


<commit_before>package paypal

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	NVP_SANDBOX_URL         = "https://api-3t.sandbox.paypal.com/nvp"
	NVP_PRODUCTION_URL      = "https://api-3t.paypal.com/nvp"
	CHECKOUT_SANDBOX_URL    = "https://www.sandbox.paypal.com/cgi-bin/webscr"
	CHECKOUT_PRODUCTION_URL = "https://www.paypal.com/cgi-bin/webscr"
	NVP_VERSION             = "84"
)

type PayPalClient struct {
	username    string
	password    string
	signature   string
	endpoint    string
	usesSandbox bool
	client      *http.Client
}

type PayPalDigitalGood struct {
	Name     string
	Amount   float64
	Quantity int16
}

type PayPalResponse struct {
	Ack           string
	CorrelationId string
	Timestamp     string
	Version       string
	Build         string
	Values        url.Values
	usedSandbox   bool
}

type PayPalError struct {
	Ack          string
	ErrorCode    string
	ShortMessage string
	LongMessage  string
	SeverityCode string
}

func (e *PayPalError) Error() string {
	var message string
	if len(e.ErrorCode) != 0 && len(e.ShortMessage) != 0 {
		message = "PayPal Error " + e.ErrorCode + ": " + e.ShortMessage
	} else if len(e.Ack) != 0 {
		message = e.Ack
	} else {
		message = "PayPal is undergoing maintenance.\nPlease try again later."
	}

	return message
}

func (r *PayPalResponse) CheckoutUrl() string {
	query := url.Values{}
	query.Set("cmd", "_express-checkout")
	query.Add("token", r.Values["TOKEN"][0])
	checkoutUrl := CHECKOUT_PRODUCTION_URL
	if r.usedSandbox {
		checkoutUrl = CHECKOUT_SANDBOX_URL
	}
	return fmt.Sprintf("%s?%s", checkoutUrl, query.Encode())
}

func SumPayPalDigitalGoodAmounts(goods *[]PayPalDigitalGood) (sum float64) {
	for _, dg := range *goods {
		sum += dg.Amount * float64(dg.Quantity)
	}
	return
}

func NewDefaultClient(username, password, signature string, usesSandbox bool) *PayPalClient {
	var endpoint = NVP_PRODUCTION_URL
	if usesSandbox {
		endpoint = NVP_SANDBOX_URL
	}

	return &PayPalClient{
		username:    username,
		password:    password,
		signature:   signature,
		endpoint:    endpoint,
		usesSandbox: usesSandbox,
		client:      new(http.Client),
	}
}

func NewClient(username, password, signature string, usesSandbox bool, client *http.Client) *PayPalClient {
	var endpoint = NVP_PRODUCTION_URL
	if usesSandbox {
		endpoint = NVP_SANDBOX_URL
	}

	return &PayPalClient{
		username:    username,
		password:    password,
		signature:   signature,
		endpoint:    endpoint,
		usesSandbox: usesSandbox,
		client:      client,
	}
}

func (pClient *PayPalClient) PerformRequest(values url.Values) (*PayPalResponse, error) {
	values.Add("USER", pClient.username)
	values.Add("PWD", pClient.password)
	values.Add("SIGNATURE", pClient.signature)
	values.Add("VERSION", NVP_VERSION)

	formResponse, err := pClient.client.PostForm(pClient.endpoint, values)
	if err != nil {
		return nil, err
	}
	defer formResponse.Body.Close()

	body, err := ioutil.ReadAll(formResponse.Body)
	if err != nil {
		return nil, err
	}

	responseValues, err := url.ParseQuery(string(body))
	response := &PayPalResponse{usedSandbox: pClient.usesSandbox}
	if err == nil {
		response.Ack = responseValues.Get("ACK")
		response.CorrelationId = responseValues.Get("CORRELATIONID")
		response.Timestamp = responseValues.Get("TIMESTAMP")
		response.Version = responseValues.Get("VERSION")
		response.Build = responseValues.Get("2975009")
		response.Values = responseValues

		errorCode := responseValues.Get("L_ERRORCODE0")
		if len(errorCode) != 0 || strings.ToLower(response.Ack) == "failure" || strings.ToLower(response.Ack) == "failurewithwarning" {
			pError := new(PayPalError)
			pError.Ack = response.Ack
			pError.ErrorCode = errorCode
			pError.ShortMessage = responseValues.Get("L_SHORTMESSAGE0")
			pError.LongMessage = responseValues.Get("L_LONGMESSAGE0")
			pError.SeverityCode = responseValues.Get("L_SEVERITYCODE0")

			err = pError
		}
	}

	return response, err
}

func (pClient *PayPalClient) SetExpressCheckoutDigitalGoods(paymentAmount float64, currencyCode string, returnURL, cancelURL string, goods []PayPalDigitalGood) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "SetExpressCheckout")
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", paymentAmount))
	values.Add("PAYMENTREQUEST_0_PAYMENTACTION", "Sale")
	values.Add("PAYMENTREQUEST_0_CURRENCYCODE", currencyCode)
	values.Add("RETURNURL", returnURL)
	values.Add("CANCELURL", cancelURL)
	values.Add("REQCONFIRMSHIPPING", "0")
	values.Add("NOSHIPPING", "1")
	values.Add("SOLUTIONTYPE", "Sole")

	for i := 0; i < len(goods); i++ {
		good := goods[i]

		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_NAME", i), good.Name)
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_AMT", i), fmt.Sprintf("%.2f", good.Amount))
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_QTY", i), fmt.Sprintf("%d", good.Quantity))
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_ITEMCATEGORY", i), "Digital")
	}

	return pClient.PerformRequest(values)
}

// Convenience function for Sale (Charge)
func (pClient *PayPalClient) DoExpressCheckoutSale(token, payerId, currencyCode string, finalPaymentAmount float64) (*PayPalResponse, error) {
	return pClient.DoExpressCheckoutPayment(token, payerId, "Sale", currencyCode, finalPaymentAmount)
}

// paymentType can be "Sale" or "Authorization" or "Order" (ship later)
func (pClient *PayPalClient) DoExpressCheckoutPayment(token, payerId, paymentType, currencyCode string, finalPaymentAmount float64) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "DoExpressCheckoutPayment")
	values.Add("TOKEN", token)
	values.Add("PAYERID", payerId)
	values.Add("PAYMENTREQUEST_0_PAYMENTACTION", paymentType)
	values.Add("PAYMENTREQUEST_0_CURRENCYCODE", currencyCode)
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", finalPaymentAmount))

	return pClient.PerformRequest(values)
}

func (pClient *PayPalClient) GetExpressCheckoutDetails(token string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Add("TOKEN", token)
	values.Set("METHOD", "GetExpressCheckoutDetails")
	return pClient.PerformRequest(values)
}

//----------------------------------------------------------
// Forked
//----------------------------------------------------------

func (pClient *PayPalClient) CreateRecurringPaymentsProfile(token string, params map[string]string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Add("TOKEN", token)
	values.Set("METHOD", "CreateRecurringPaymentsProfile")

	if params != nil {
		for key, value := range params {
			values.Add(key, value)
		}
	}

	return pClient.PerformRequest(values)
}

func (pClient *PayPalClient) BillOutstandingAmount(profileId string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "BillOutstandingAmount")
	values.Set("PROFILEID", profileId)

	return pClient.PerformRequest(values)
}

func NewDigitalGood(name string, amount float64) *PayPalDigitalGood {
	return &PayPalDigitalGood{
		Name:     name,
		Amount:   amount,
		Quantity: 1,
	}
}

type ExpressCheckoutSingleArgs struct {
	Amount                             float64
	CurrencyCode, ReturnURL, CancelURL string
	Recurring                          bool
	Item                               *PayPalDigitalGood
}

func NewExpressCheckoutSingleArgs() *ExpressCheckoutSingleArgs {
	return &ExpressCheckoutSingleArgs{
		Amount:       0,
		CurrencyCode: "USD",
		Recurring:    true,
	}
}

func (pClient *PayPalClient) SetExpressCheckoutSingle(args *ExpressCheckoutSingleArgs) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "SetExpressCheckout")
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", args.Amount))
	values.Add("NOSHIPPING", "1")

	values.Add("L_BILLINGTYPE0", "RecurringPayments")
	values.Add("L_BILLINGAGREEMENTDESCRIPTION0", args.Item.Name)

	values.Add("RETURNURL", args.ReturnURL)
	values.Add("CANCELURL", args.CancelURL)

	return pClient.PerformRequest(values)
}
<commit_msg>payment: update paypal library<commit_after>package paypal

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	NVP_SANDBOX_URL         = "https://api-3t.sandbox.paypal.com/nvp"
	NVP_PRODUCTION_URL      = "https://api-3t.paypal.com/nvp"
	CHECKOUT_SANDBOX_URL    = "https://www.sandbox.paypal.com/cgi-bin/webscr"
	CHECKOUT_PRODUCTION_URL = "https://www.paypal.com/cgi-bin/webscr"
	NVP_VERSION             = "84"
)

type PayPalClient struct {
	username    string
	password    string
	signature   string
	endpoint    string
	usesSandbox bool
	client      *http.Client
}

type PayPalDigitalGood struct {
	Name     string
	Amount   float64
	Quantity int16
}

type PayPalResponse struct {
	Ack           string
	CorrelationId string
	Timestamp     string
	Version       string
	Build         string
	Values        url.Values
	usedSandbox   bool
}

type PayPalError struct {
	Ack          string
	ErrorCode    string
	ShortMessage string
	LongMessage  string
	SeverityCode string
}

func (e *PayPalError) Error() string {
	var message string
	if len(e.ErrorCode) != 0 && len(e.ShortMessage) != 0 {
		message = "PayPal Error " + e.ErrorCode + ": " + e.ShortMessage
	} else if len(e.Ack) != 0 {
		message = e.Ack
	} else {
		message = "PayPal is undergoing maintenance.\nPlease try again later."
	}

	return message
}

func (r *PayPalResponse) CheckoutUrl() string {
	query := url.Values{}
	query.Set("cmd", "_express-checkout")
	query.Add("token", r.Values["TOKEN"][0])
	checkoutUrl := CHECKOUT_PRODUCTION_URL
	if r.usedSandbox {
		checkoutUrl = CHECKOUT_SANDBOX_URL
	}
	return fmt.Sprintf("%s?%s", checkoutUrl, query.Encode())
}

func SumPayPalDigitalGoodAmounts(goods *[]PayPalDigitalGood) (sum float64) {
	for _, dg := range *goods {
		sum += dg.Amount * float64(dg.Quantity)
	}
	return
}

func NewDefaultClientEndpoint(username, password, signature, endpoint string, usesSandbox bool) *PayPalClient {
	return &PayPalClient{
		username:    username,
		password:    password,
		signature:   signature,
		endpoint:    endpoint,
		usesSandbox: usesSandbox,
		client:      new(http.Client),
	}
}

func NewDefaultClient(username, password, signature string, usesSandbox bool) *PayPalClient {
	var endpoint = NVP_PRODUCTION_URL
	if usesSandbox {
		endpoint = NVP_SANDBOX_URL
	}

	return &PayPalClient{
		username:    username,
		password:    password,
		signature:   signature,
		endpoint:    endpoint,
		usesSandbox: usesSandbox,
		client:      new(http.Client),
	}
}

func NewClient(username, password, signature string, usesSandbox bool, client *http.Client) *PayPalClient {
	var endpoint = NVP_PRODUCTION_URL
	if usesSandbox {
		endpoint = NVP_SANDBOX_URL
	}

	return &PayPalClient{
		username:    username,
		password:    password,
		signature:   signature,
		endpoint:    endpoint,
		usesSandbox: usesSandbox,
		client:      client,
	}
}

func (pClient *PayPalClient) PerformRequest(values url.Values) (*PayPalResponse, error) {
	values.Add("USER", pClient.username)
	values.Add("PWD", pClient.password)
	values.Add("SIGNATURE", pClient.signature)
	values.Add("VERSION", NVP_VERSION)

	formResponse, err := pClient.client.PostForm(pClient.endpoint, values)
	if err != nil {
		return nil, err
	}
	defer formResponse.Body.Close()

	body, err := ioutil.ReadAll(formResponse.Body)
	if err != nil {
		return nil, err
	}

	responseValues, err := url.ParseQuery(string(body))
	response := &PayPalResponse{usedSandbox: pClient.usesSandbox}
	if err == nil {
		response.Ack = responseValues.Get("ACK")
		response.CorrelationId = responseValues.Get("CORRELATIONID")
		response.Timestamp = responseValues.Get("TIMESTAMP")
		response.Version = responseValues.Get("VERSION")
		response.Build = responseValues.Get("2975009")
		response.Values = responseValues

		errorCode := responseValues.Get("L_ERRORCODE0")
		if len(errorCode) != 0 || strings.ToLower(response.Ack) == "failure" || strings.ToLower(response.Ack) == "failurewithwarning" {
			pError := new(PayPalError)
			pError.Ack = response.Ack
			pError.ErrorCode = errorCode
			pError.ShortMessage = responseValues.Get("L_SHORTMESSAGE0")
			pError.LongMessage = responseValues.Get("L_LONGMESSAGE0")
			pError.SeverityCode = responseValues.Get("L_SEVERITYCODE0")

			err = pError
		}
	}

	return response, err
}

func (pClient *PayPalClient) SetExpressCheckoutDigitalGoods(paymentAmount float64, currencyCode string, returnURL, cancelURL string, goods []PayPalDigitalGood) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "SetExpressCheckout")
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", paymentAmount))
	values.Add("PAYMENTREQUEST_0_PAYMENTACTION", "Sale")
	values.Add("PAYMENTREQUEST_0_CURRENCYCODE", currencyCode)
	values.Add("RETURNURL", returnURL)
	values.Add("CANCELURL", cancelURL)
	values.Add("REQCONFIRMSHIPPING", "0")
	values.Add("NOSHIPPING", "1")
	values.Add("SOLUTIONTYPE", "Sole")

	for i := 0; i < len(goods); i++ {
		good := goods[i]

		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_NAME", i), good.Name)
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_AMT", i), fmt.Sprintf("%.2f", good.Amount))
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_QTY", i), fmt.Sprintf("%d", good.Quantity))
		values.Add(fmt.Sprintf("%s%d", "L_PAYMENTREQUEST_0_ITEMCATEGORY", i), "Digital")
	}

	return pClient.PerformRequest(values)
}

// Convenience function for Sale (Charge)
func (pClient *PayPalClient) DoExpressCheckoutSale(token, payerId, currencyCode string, finalPaymentAmount float64) (*PayPalResponse, error) {
	return pClient.DoExpressCheckoutPayment(token, payerId, "Sale", currencyCode, finalPaymentAmount)
}

// paymentType can be "Sale" or "Authorization" or "Order" (ship later)
func (pClient *PayPalClient) DoExpressCheckoutPayment(token, payerId, paymentType, currencyCode string, finalPaymentAmount float64) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "DoExpressCheckoutPayment")
	values.Add("TOKEN", token)
	values.Add("PAYERID", payerId)
	values.Add("PAYMENTREQUEST_0_PAYMENTACTION", paymentType)
	values.Add("PAYMENTREQUEST_0_CURRENCYCODE", currencyCode)
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", finalPaymentAmount))

	return pClient.PerformRequest(values)
}

func (pClient *PayPalClient) GetExpressCheckoutDetails(token string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Add("TOKEN", token)
	values.Set("METHOD", "GetExpressCheckoutDetails")
	return pClient.PerformRequest(values)
}

//----------------------------------------------------------
// Forked
//----------------------------------------------------------

func (pClient *PayPalClient) CreateRecurringPaymentsProfile(token string, params map[string]string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Add("TOKEN", token)
	values.Set("METHOD", "CreateRecurringPaymentsProfile")

	if params != nil {
		for key, value := range params {
			values.Add(key, value)
		}
	}

	return pClient.PerformRequest(values)
}

func (pClient *PayPalClient) BillOutstandingAmount(profileId string) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "BillOutstandingAmount")
	values.Set("PROFILEID", profileId)

	return pClient.PerformRequest(values)
}

func NewDigitalGood(name string, amount float64) *PayPalDigitalGood {
	return &PayPalDigitalGood{
		Name:     name,
		Amount:   amount,
		Quantity: 1,
	}
}

type ExpressCheckoutSingleArgs struct {
	Amount                             float64
	CurrencyCode, ReturnURL, CancelURL string
	Recurring                          bool
	Item                               *PayPalDigitalGood
}

func NewExpressCheckoutSingleArgs() *ExpressCheckoutSingleArgs {
	return &ExpressCheckoutSingleArgs{
		Amount:       0,
		CurrencyCode: "USD",
		Recurring:    true,
	}
}

func (pClient *PayPalClient) SetExpressCheckoutSingle(args *ExpressCheckoutSingleArgs) (*PayPalResponse, error) {
	values := url.Values{}
	values.Set("METHOD", "SetExpressCheckout")
	values.Add("PAYMENTREQUEST_0_AMT", fmt.Sprintf("%.2f", args.Amount))
	values.Add("NOSHIPPING", "1")

	values.Add("L_BILLINGTYPE0", "RecurringPayments")
	values.Add("L_BILLINGAGREEMENTDESCRIPTION0", args.Item.Name)

	values.Add("RETURNURL", args.ReturnURL)
	values.Add("CANCELURL", args.CancelURL)

	return pClient.PerformRequest(values)
}
<|endoftext|>


<commit_before>package koding

import (
	"bytes"
	"errors"
	"sort"
	"strconv"
	"strings"
	"time"

	"koding/kites/kloud/kloud"
	"koding/kites/kloud/machinestate"
	"koding/kites/kloud/protocol"
	"koding/kites/kloud/provider/amazon"

	"github.com/dgrijalva/jwt-go"
	kiteprotocol "github.com/koding/kite/protocol"
	"github.com/mitchellh/goamz/ec2"
	"github.com/nu7hatch/gouuid"
	"gopkg.in/yaml.v2"
)

var (
	DefaultCustomAMITag = "koding-stable" // Only use AMI's that have this tag
	DefaultInstanceType = "t2.micro"
)

const (
	DefaultApachePort = 80
	DefaultKitePort   = 3000
)

func (p *Provider) Build(m *protocol.Machine) (resArt *protocol.Artifact, err error) {
	a, err := p.NewClient(m)
	if err != nil {
		return nil, err
	}

	return p.build(a, m, &pushValues{Start: 10, Finish: 90})
}

func (p *Provider) build(a *amazon.AmazonClient, m *protocol.Machine, v *pushValues) (resArt *protocol.Artifact, err error) {
	// returns the normalized step according to the initial start and finish
	// values. i.e for a start,finish pair of (10,90) percentages of
	// 0,15,20,50,80,100 will be according to the function: 10,18,26,50,74,90
	normalize := func(percentage int) int {
		base := v.Finish - v.Start
		step := float64(base) * (float64(percentage) / 100)
		normalized := float64(v.Start) + step
		return int(normalized)
	}

	// Check for total amachine allowance
	checker, err := p.PlanChecker(m)
	if err != nil {
		return nil, err
	}

	p.Log.Info("[%s] checking machine limit for user '%s'", m.Id, m.Username)
	if err := checker.Total(); err != nil {
		return nil, err
	}

	p.Log.Info("[%s] checking alwaysOn limit for user '%s'", m.Id, m.Username)
	if err := checker.AlwaysOn(); err != nil {
		return nil, err
	}

	instanceName := m.Builder["instanceName"].(string)

	a.Push("Initializing data", normalize(10), machinestate.Building)

	infoLog := p.GetCustomLogger(m.Id, "info")
	errLog := p.GetCustomLogger(m.Id, "error")

	a.InfoLog = infoLog

	// this can happen when an Info method is called on a terminated instance.
	// This updates the DB records with the name that EC2 gives us, which is a
	// "terminated-instance"
	if instanceName == "terminated-instance" {
		instanceName = "user-" + m.Username + "-" + strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
		infoLog("Instance name is an artifact (terminated), changing to %s", instanceName)
	}

	a.Push("Checking network requirements", normalize(20), machinestate.Building)

	// get all subnets belonging to Kloud
	kloudKeyName := "Kloud"
	infoLog("Searching for subnets with tag-key %s", kloudKeyName)
	subnets, err := a.SubnetsWithTag(kloudKeyName)
	if err != nil {
		errLog("Searching subnet err: %v", err)
		return nil, errors.New("searching network configuration failed")
	}

	// sort and get the lowest
	infoLog("Searching a subnet with most IPs amongst '%d' subnets", len(subnets))
	subnet := subnetWithMostIPs(subnets)

	infoLog("Using subnet id %s, which has %d available IPs", subnet.SubnetId, subnet.AvailableIpAddressCount)
	a.Builder.SubnetId = subnet.SubnetId

	infoLog("Checking if security group for VPC id %s exists.", subnet.VpcId)
	group, err := a.SecurityGroupFromVPC(subnet.VpcId, kloudKeyName)
	if err != nil {
		errLog("Checking security group err: %v", err)
		return nil, errors.New("checking security requirements failed")
	}

	// add now our security group
	a.Builder.SecurityGroupId = group.Id

	// Use koding plans instead of those later
	a.Builder.InstanceType = DefaultInstanceType

	infoLog("Check if user is allowed to create instance type %s", a.Builder.InstanceType)
	// check if the user is egligible to create a vm with this size
	if err := checker.AllowedInstances(instances[a.Builder.InstanceType]); err != nil {
		return nil, err
	}

	a.Push("Checking base build image", normalize(30), machinestate.Building)

	infoLog("Checking if AMI with tag '%s' exists", DefaultCustomAMITag)
	image, err := a.ImageByTag(DefaultCustomAMITag)
	if err != nil {
		errLog("Checking ami tag failed err: %v", err)
		return nil, errors.New("checking base image failed")
	}

	// Use this ami id, which is going to be a stable one
	a.Builder.SourceAmi = image.Id

	storageSize := 3 // default AMI 3GB size
	if a.Builder.StorageSize != 0 && a.Builder.StorageSize > 3 {
		storageSize = a.Builder.StorageSize
	}

	infoLog("Check if user is allowed to create machine with '%dGB' storage", storageSize)
	// check if the user is egligible to create a vm with this size
	if err := checker.Storage(storageSize); err != nil {
		return nil, err
	}

	// Increase storage if it's passed to us, otherwise the default 3GB is
	// created already with the default AMI
	if a.Builder.StorageSize != 0 {
		for _, device := range image.BlockDevices {
			a.Builder.BlockDeviceMapping = &ec2.BlockDeviceMapping{
				DeviceName:          device.DeviceName,
				VirtualName:         device.VirtualName,
				SnapshotId:          device.SnapshotId,
				VolumeType:          device.VolumeType,
				VolumeSize:          int64(a.Builder.StorageSize),
				DeleteOnTermination: true,
				Encrypted:           false,
			}

			break
		}
	}

	kiteId, err := uuid.NewV4()
	if err != nil {
		panic(err)
	}

	kiteKey, err := p.createKey(m.Username, kiteId.String())
	if err != nil {
		return nil, err
	}

	latestKlientPath, err := p.Bucket.LatestDeb()
	if err != nil {
		errLog("Checking klient S3 path failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [1]")
	}

	latestKlientUrl := p.Bucket.URL(latestKlientPath)

	// Use cloud-init for initial configuration of the VM
	cloudInitConfig := &CloudInitConfig{
		Username:        m.Username,
		UserDomain:      m.Domain.Name,
		Hostname:        m.Username, // no typo here. hostname = username
		KiteKey:         kiteKey,
		LatestKlientURL: latestKlientUrl,
		ApachePort:      DefaultApachePort,
		KitePort:        DefaultKitePort,
		Test:            p.Test,
	}

	// check if the user has some keys
	if keyData, ok := m.Builder["user_ssh_keys"]; ok {
		if keys, ok := keyData.([]string); ok && len(keys) > 0 {
			cloudInitConfig.UserSSHKeys = keys
		}
	}

	cloudInitConfig.setupMigrateScript()

	var userdata bytes.Buffer
	err = cloudInitTemplate.Funcs(funcMap).Execute(&userdata, *cloudInitConfig)
	if err != nil {
		errLog("Template execution failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [2]")
	}

	// validate the userdata first before sending
	if err = yaml.Unmarshal(userdata.Bytes(), struct{}{}); err != nil {
		errLog("Cloudinit template is not a valid YAML file: %v", err)
		return nil, errors.New("Cloudinit template is not a valid YAML file.")
	}

	// user data is now ready!
	a.Builder.UserData = userdata.Bytes()

	// add our Koding keypair
	a.Builder.KeyPair = p.KeyName

	// build now our instance!!
	buildArtifact, err := a.Build(instanceName, normalize(45), normalize(60))
	if err != nil {
		return nil, err
	}
	buildArtifact.MachineId = m.Id

	// cleanup build if something goes wrong here
	defer func() {
		if err != nil {
			p.Log.Warning("[%s] Cleaning up instance. Terminating instance: %s",
				m.Id, buildArtifact.InstanceId)

			if _, err := a.Client.TerminateInstances([]string{buildArtifact.InstanceId}); err != nil {
				p.Log.Warning("[%s] Cleaning up instance failed: %v", m.Id, err)
			}
		}
	}()

	a.Push("Updating/Creating domain", normalize(70), machinestate.Building)
	if err := p.UpdateDomain(buildArtifact.IpAddress, m.Domain.Name, m.Username); err != nil {
		return nil, err
	}

	defer func() {
		if err != nil {
			p.Log.Warning("[%s] Cleaning up domain record. Deleting domain record: %s",
				m.Id, m.Domain.Name)
			if err := p.DNS.DeleteDomain(m.Domain.Name, buildArtifact.IpAddress); err != nil {
				p.Log.Warning("[%s] Cleaning up domain failed: %v", m.Id, err)
			}

		}
	}()

	tags := []ec2.Tag{
		{Key: "Name", Value: buildArtifact.InstanceName},
		{Key: "koding-user", Value: m.Username},
		{Key: "koding-env", Value: p.Kite.Config.Environment},
		{Key: "koding-machineId", Value: m.Id},
		{Key: "koding-domain", Value: m.Domain.Name},
	}

	infoLog("Adding user tags %v", tags)
	if err := a.AddTags(buildArtifact.InstanceId, tags); err != nil {
		errLog("Adding tags failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [3]")
	}

	buildArtifact.DomainName = m.Domain.Name

	query := kiteprotocol.Kite{ID: kiteId.String()}
	buildArtifact.KiteQuery = query.String()

	a.Push("Checking connectivity", normalize(75), machinestate.Building)
	infoLog("Connecting to remote Klient instance")
	if p.IsKlientReady(query.String()) {
		p.Log.Info("[%s] klient is ready.", m.Id)
	} else {
		p.Log.Warning("[%s] klient is not ready. I couldn't connect to it.", m.Id)
	}

	return buildArtifact, nil
}

// CreateKey signs a new key and returns the token back
func (p *Provider) createKey(username, kiteId string) (string, error) {
	if username == "" {
		return "", kloud.NewError(kloud.ErrSignUsernameEmpty)
	}

	if p.KontrolURL == "" {
		return "", kloud.NewError(kloud.ErrSignKontrolURLEmpty)
	}

	if p.KontrolPrivateKey == "" {
		return "", kloud.NewError(kloud.ErrSignPrivateKeyEmpty)
	}

	if p.KontrolPublicKey == "" {
		return "", kloud.NewError(kloud.ErrSignPublicKeyEmpty)
	}

	token := jwt.New(jwt.GetSigningMethod("RS256"))

	token.Claims = map[string]interface{}{
		"iss":        "koding",                              // Issuer, should be the same username as kontrol
		"sub":        username,                              // Subject
		"iat":        time.Now().UTC().Unix(),               // Issued At
		"jti":        kiteId,                                // JWT ID
		"kontrolURL": p.KontrolURL,                          // Kontrol URL
		"kontrolKey": strings.TrimSpace(p.KontrolPublicKey), // Public key of kontrol
	}

	return token.SignedString([]byte(p.KontrolPrivateKey))
}

type ByMostIP []ec2.Subnet

func (a ByMostIP) Len() int      { return len(a) }
func (a ByMostIP) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByMostIP) Less(i, j int) bool {
	return a[i].AvailableIpAddressCount > a[j].AvailableIpAddressCount
}

func subnetWithMostIPs(subnets []ec2.Subnet) ec2.Subnet {
	sort.Sort(ByMostIP(subnets))
	return subnets[0]
}
<commit_msg>kloud: improve cloudinit logs<commit_after>package koding

import (
	"bytes"
	"errors"
	"io/ioutil"
	"sort"
	"strconv"
	"strings"
	"time"

	"koding/kites/kloud/kloud"
	"koding/kites/kloud/machinestate"
	"koding/kites/kloud/protocol"
	"koding/kites/kloud/provider/amazon"

	"github.com/dgrijalva/jwt-go"
	kiteprotocol "github.com/koding/kite/protocol"
	"github.com/mitchellh/goamz/ec2"
	"github.com/nu7hatch/gouuid"
	"gopkg.in/yaml.v2"
)

var (
	DefaultCustomAMITag = "koding-stable" // Only use AMI's that have this tag
	DefaultInstanceType = "t2.micro"
)

const (
	DefaultApachePort = 80
	DefaultKitePort   = 3000
)

func (p *Provider) Build(m *protocol.Machine) (resArt *protocol.Artifact, err error) {
	a, err := p.NewClient(m)
	if err != nil {
		return nil, err
	}

	return p.build(a, m, &pushValues{Start: 10, Finish: 90})
}

func (p *Provider) build(a *amazon.AmazonClient, m *protocol.Machine, v *pushValues) (resArt *protocol.Artifact, err error) {
	// returns the normalized step according to the initial start and finish
	// values. i.e for a start,finish pair of (10,90) percentages of
	// 0,15,20,50,80,100 will be according to the function: 10,18,26,50,74,90
	normalize := func(percentage int) int {
		base := v.Finish - v.Start
		step := float64(base) * (float64(percentage) / 100)
		normalized := float64(v.Start) + step
		return int(normalized)
	}

	// Check for total amachine allowance
	checker, err := p.PlanChecker(m)
	if err != nil {
		return nil, err
	}

	p.Log.Info("[%s] checking machine limit for user '%s'", m.Id, m.Username)
	if err := checker.Total(); err != nil {
		return nil, err
	}

	p.Log.Info("[%s] checking alwaysOn limit for user '%s'", m.Id, m.Username)
	if err := checker.AlwaysOn(); err != nil {
		return nil, err
	}

	instanceName := m.Builder["instanceName"].(string)

	a.Push("Initializing data", normalize(10), machinestate.Building)

	infoLog := p.GetCustomLogger(m.Id, "info")
	errLog := p.GetCustomLogger(m.Id, "error")

	a.InfoLog = infoLog

	// this can happen when an Info method is called on a terminated instance.
	// This updates the DB records with the name that EC2 gives us, which is a
	// "terminated-instance"
	if instanceName == "terminated-instance" {
		instanceName = "user-" + m.Username + "-" + strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
		infoLog("Instance name is an artifact (terminated), changing to %s", instanceName)
	}

	a.Push("Checking network requirements", normalize(20), machinestate.Building)

	// get all subnets belonging to Kloud
	kloudKeyName := "Kloud"
	infoLog("Searching for subnets with tag-key %s", kloudKeyName)
	subnets, err := a.SubnetsWithTag(kloudKeyName)
	if err != nil {
		errLog("Searching subnet err: %v", err)
		return nil, errors.New("searching network configuration failed")
	}

	// sort and get the lowest
	infoLog("Searching a subnet with most IPs amongst '%d' subnets", len(subnets))
	subnet := subnetWithMostIPs(subnets)

	infoLog("Using subnet id %s, which has %d available IPs", subnet.SubnetId, subnet.AvailableIpAddressCount)
	a.Builder.SubnetId = subnet.SubnetId

	infoLog("Checking if security group for VPC id %s exists.", subnet.VpcId)
	group, err := a.SecurityGroupFromVPC(subnet.VpcId, kloudKeyName)
	if err != nil {
		errLog("Checking security group err: %v", err)
		return nil, errors.New("checking security requirements failed")
	}

	// add now our security group
	a.Builder.SecurityGroupId = group.Id

	// Use koding plans instead of those later
	a.Builder.InstanceType = DefaultInstanceType

	infoLog("Check if user is allowed to create instance type %s", a.Builder.InstanceType)
	// check if the user is egligible to create a vm with this size
	if err := checker.AllowedInstances(instances[a.Builder.InstanceType]); err != nil {
		return nil, err
	}

	a.Push("Checking base build image", normalize(30), machinestate.Building)

	infoLog("Checking if AMI with tag '%s' exists", DefaultCustomAMITag)
	image, err := a.ImageByTag(DefaultCustomAMITag)
	if err != nil {
		errLog("Checking ami tag failed err: %v", err)
		return nil, errors.New("checking base image failed")
	}

	// Use this ami id, which is going to be a stable one
	a.Builder.SourceAmi = image.Id

	storageSize := 3 // default AMI 3GB size
	if a.Builder.StorageSize != 0 && a.Builder.StorageSize > 3 {
		storageSize = a.Builder.StorageSize
	}

	infoLog("Check if user is allowed to create machine with '%dGB' storage", storageSize)
	// check if the user is egligible to create a vm with this size
	if err := checker.Storage(storageSize); err != nil {
		return nil, err
	}

	// Increase storage if it's passed to us, otherwise the default 3GB is
	// created already with the default AMI
	if a.Builder.StorageSize != 0 {
		for _, device := range image.BlockDevices {
			a.Builder.BlockDeviceMapping = &ec2.BlockDeviceMapping{
				DeviceName:          device.DeviceName,
				VirtualName:         device.VirtualName,
				SnapshotId:          device.SnapshotId,
				VolumeType:          device.VolumeType,
				VolumeSize:          int64(a.Builder.StorageSize),
				DeleteOnTermination: true,
				Encrypted:           false,
			}

			break
		}
	}

	kiteId, err := uuid.NewV4()
	if err != nil {
		panic(err)
	}

	kiteKey, err := p.createKey(m.Username, kiteId.String())
	if err != nil {
		return nil, err
	}

	latestKlientPath, err := p.Bucket.LatestDeb()
	if err != nil {
		errLog("Checking klient S3 path failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [1]")
	}

	latestKlientUrl := p.Bucket.URL(latestKlientPath)

	// Use cloud-init for initial configuration of the VM
	cloudInitConfig := &CloudInitConfig{
		Username:        m.Username,
		UserDomain:      m.Domain.Name,
		Hostname:        m.Username, // no typo here. hostname = username
		KiteKey:         kiteKey,
		LatestKlientURL: latestKlientUrl,
		ApachePort:      DefaultApachePort,
		KitePort:        DefaultKitePort,
		Test:            p.Test,
	}

	// check if the user has some keys
	if keyData, ok := m.Builder["user_ssh_keys"]; ok {
		if keys, ok := keyData.([]string); ok && len(keys) > 0 {
			cloudInitConfig.UserSSHKeys = keys
		}
	}

	cloudInitConfig.setupMigrateScript()

	var userdata bytes.Buffer
	err = cloudInitTemplate.Funcs(funcMap).Execute(&userdata, *cloudInitConfig)
	if err != nil {
		errLog("Template execution failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [2]")
	}

	// validate the userdata first before sending
	if err = yaml.Unmarshal(userdata.Bytes(), struct{}{}); err != nil {
		// write to temporary file so we can see the yaml file that is not
		// formatted in a good way.
		f, err := ioutil.TempFile("", "kloud-cloudinit")
		if err == nil {
			if _, err := f.WriteString(userdata.String()); err != nil {
				errLog("Cloudinit temporary field couldn't be written %v", err)
			}
		}

		errLog("Cloudinit template is not a valid YAML file: %v. YAML file path: %s", err,
			f.Name())
		return nil, errors.New("Cloudinit template is not a valid YAML file.")
	}

	// user data is now ready!
	a.Builder.UserData = userdata.Bytes()

	// add our Koding keypair
	a.Builder.KeyPair = p.KeyName

	// build now our instance!!
	buildArtifact, err := a.Build(instanceName, normalize(45), normalize(60))
	if err != nil {
		return nil, err
	}
	buildArtifact.MachineId = m.Id

	// cleanup build if something goes wrong here
	defer func() {
		if err != nil {
			p.Log.Warning("[%s] Cleaning up instance. Terminating instance: %s",
				m.Id, buildArtifact.InstanceId)

			if _, err := a.Client.TerminateInstances([]string{buildArtifact.InstanceId}); err != nil {
				p.Log.Warning("[%s] Cleaning up instance failed: %v", m.Id, err)
			}
		}
	}()

	a.Push("Updating/Creating domain", normalize(70), machinestate.Building)
	if err := p.UpdateDomain(buildArtifact.IpAddress, m.Domain.Name, m.Username); err != nil {
		return nil, err
	}

	defer func() {
		if err != nil {
			p.Log.Warning("[%s] Cleaning up domain record. Deleting domain record: %s",
				m.Id, m.Domain.Name)
			if err := p.DNS.DeleteDomain(m.Domain.Name, buildArtifact.IpAddress); err != nil {
				p.Log.Warning("[%s] Cleaning up domain failed: %v", m.Id, err)
			}

		}
	}()

	tags := []ec2.Tag{
		{Key: "Name", Value: buildArtifact.InstanceName},
		{Key: "koding-user", Value: m.Username},
		{Key: "koding-env", Value: p.Kite.Config.Environment},
		{Key: "koding-machineId", Value: m.Id},
		{Key: "koding-domain", Value: m.Domain.Name},
	}

	infoLog("Adding user tags %v", tags)
	if err := a.AddTags(buildArtifact.InstanceId, tags); err != nil {
		errLog("Adding tags failed: %v", err)
		return nil, errors.New("machine initialization requirements failed [3]")
	}

	buildArtifact.DomainName = m.Domain.Name

	query := kiteprotocol.Kite{ID: kiteId.String()}
	buildArtifact.KiteQuery = query.String()

	a.Push("Checking connectivity", normalize(75), machinestate.Building)
	infoLog("Connecting to remote Klient instance")
	if p.IsKlientReady(query.String()) {
		p.Log.Info("[%s] klient is ready.", m.Id)
	} else {
		p.Log.Warning("[%s] klient is not ready. I couldn't connect to it.", m.Id)
	}

	return buildArtifact, nil
}

// CreateKey signs a new key and returns the token back
func (p *Provider) createKey(username, kiteId string) (string, error) {
	if username == "" {
		return "", kloud.NewError(kloud.ErrSignUsernameEmpty)
	}

	if p.KontrolURL == "" {
		return "", kloud.NewError(kloud.ErrSignKontrolURLEmpty)
	}

	if p.KontrolPrivateKey == "" {
		return "", kloud.NewError(kloud.ErrSignPrivateKeyEmpty)
	}

	if p.KontrolPublicKey == "" {
		return "", kloud.NewError(kloud.ErrSignPublicKeyEmpty)
	}

	token := jwt.New(jwt.GetSigningMethod("RS256"))

	token.Claims = map[string]interface{}{
		"iss":        "koding",                              // Issuer, should be the same username as kontrol
		"sub":        username,                              // Subject
		"iat":        time.Now().UTC().Unix(),               // Issued At
		"jti":        kiteId,                                // JWT ID
		"kontrolURL": p.KontrolURL,                          // Kontrol URL
		"kontrolKey": strings.TrimSpace(p.KontrolPublicKey), // Public key of kontrol
	}

	return token.SignedString([]byte(p.KontrolPrivateKey))
}

type ByMostIP []ec2.Subnet

func (a ByMostIP) Len() int      { return len(a) }
func (a ByMostIP) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByMostIP) Less(i, j int) bool {
	return a[i].AvailableIpAddressCount > a[j].AvailableIpAddressCount
}

func subnetWithMostIPs(subnets []ec2.Subnet) ec2.Subnet {
	sort.Sort(ByMostIP(subnets))
	return subnets[0]
}
<|endoftext|>


<commit_before>package main

import (
	"koding/kites/kloud/kloud"
	"koding/kites/kloud/kloud/machinestate"
)

type TestStorageFunc func(id string, opt *kloud.GetOption) (*kloud.MachineData, error)

func (t TestStorageFunc) Get(id string, opt *kloud.GetOption) (*kloud.MachineData, error) {
	return t(id, opt)
}

func (t TestStorageFunc) Update(id string, data *kloud.StorageData) error {
	return nil
}

func (t TestStorageFunc) UpdateState(id string, state machinestate.State) error {
	return nil
}

func (t TestStorageFunc) Assignee() string {
	return "TestStorageFunc"
}

func (t TestStorageFunc) ResetAssignee(id string) error {
	return nil
}

type TestStorage struct{}

func (t *TestStorage) Assignee() string { return "TestStorage" }

func (t *TestStorage) Get(id string, opt *kloud.GetOption) (*kloud.MachineData, error) {
	machineData := TestProviderData[id]
	return machineData, nil
}

func (t *TestStorage) Update(id string, s *kloud.StorageData) error {
	machineData := TestProviderData[id]

	if s.Type == "build" {
		machineData.Machine.QueryString = s.Data["queryString"].(string)
		machineData.Machine.IpAddress = s.Data["ipAddress"].(string)
		machineData.Machine.Meta["instanceName"] = s.Data["instanceId"]
		machineData.Machine.Meta["instanceId"] = s.Data["instanceName"]
	}

	if s.Type == "info" {
		machineData.Machine.Meta["instanceName"] = s.Data["instanceId"]
	}

	TestProviderData[id] = machineData
	return nil
}

func (t *TestStorage) UpdateState(id string, state machinestate.State) error {
	machineData := TestProviderData[id]
	machineData.Machine.Status.State = state.String()
	TestProviderData[id] = machineData
	return nil
}

func (t *TestStorage) ResetAssignee(id string) error {
	return nil
}
<commit_msg>kloue_test: fix reorder of instance keys<commit_after>package main

import (
	"koding/kites/kloud/kloud"
	"koding/kites/kloud/kloud/machinestate"
)

type TestStorageFunc func(id string, opt *kloud.GetOption) (*kloud.MachineData, error)

func (t TestStorageFunc) Get(id string, opt *kloud.GetOption) (*kloud.MachineData, error) {
	return t(id, opt)
}

func (t TestStorageFunc) Update(id string, data *kloud.StorageData) error {
	return nil
}

func (t TestStorageFunc) UpdateState(id string, state machinestate.State) error {
	return nil
}

func (t TestStorageFunc) Assignee() string {
	return "TestStorageFunc"
}

func (t TestStorageFunc) ResetAssignee(id string) error {
	return nil
}

type TestStorage struct{}

func (t *TestStorage) Assignee() string { return "TestStorage" }

func (t *TestStorage) Get(id string, opt *kloud.GetOption) (*kloud.MachineData, error) {
	machineData := TestProviderData[id]
	return machineData, nil
}

func (t *TestStorage) Update(id string, s *kloud.StorageData) error {
	machineData := TestProviderData[id]

	if s.Type == "build" {
		machineData.Machine.QueryString = s.Data["queryString"].(string)
		machineData.Machine.IpAddress = s.Data["ipAddress"].(string)
		machineData.Machine.Meta["instanceId"] = s.Data["instanceId"]
		machineData.Machine.Meta["instanceName"] = s.Data["instanceName"]
	}

	if s.Type == "info" {
		machineData.Machine.Meta["instanceName"] = s.Data["instanceName"]
	}

	TestProviderData[id] = machineData
	return nil
}

func (t *TestStorage) UpdateState(id string, state machinestate.State) error {
	machineData := TestProviderData[id]
	machineData.Machine.Status.State = state.String()
	TestProviderData[id] = machineData
	return nil
}

func (t *TestStorage) ResetAssignee(id string) error {
	return nil
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"socialapi/config"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// Generated Slug for body
	Slug string `json:"slug"                        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// type of the message
	TypeConstant string `json:"typeConstant"        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"               sql:"NOT NULL"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId" sql:"NOT NULL"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c ChannelMessage) TableName() string {
	return "api.channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func bodyLenCheck(body string) error {
	if len(body) < config.Get().Limits.MessageBodyMinLen {
		return fmt.Errorf("Message Body Length should be greater than %d, yours is %d ", config.Get().Limits.MessageBodyMinLen, len(body))
	}
	return nil
}

func (c *ChannelMessage) Update() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}

	var err error
	c, err = Slugify(c)
	if err != nil {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	oldId, err := FetchMongoIdByAccountId(c.AccountId)
	if err != nil {
		return nil, err
	}

	container.AccountOldId = oldId

	interactorIds, err := i.List("like")
	if err != nil {
		return nil, err
	}

	oldIds, err := FetchMongoIdsByAccountIds(interactorIds)
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = oldIds

	isInteracted, err := i.IsInteracted(c.AccountId)
	if err != nil {
		return nil, err
	}

	interactionContainer.IsInteracted = isInteracted

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}
<commit_msg>Social: build message with related data<commit_after>package models

import (
	"errors"
	"fmt"
	"socialapi/config"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// Generated Slug for body
	Slug string `json:"slug"                        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// type of the message
	TypeConstant string `json:"typeConstant"        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"               sql:"NOT NULL"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId" sql:"NOT NULL"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c ChannelMessage) TableName() string {
	return "api.channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func bodyLenCheck(body string) error {
	if len(body) < config.Get().Limits.MessageBodyMinLen {
		return fmt.Errorf("Message Body Length should be greater than %d, yours is %d ", config.Get().Limits.MessageBodyMinLen, len(body))
	}
	return nil
}

func (c *ChannelMessage) Update() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}

	var err error
	c, err = Slugify(c)
	if err != nil {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	oldId, err := FetchMongoIdByAccountId(c.AccountId)
	if err != nil {
		return nil, err
	}

	container.AccountOldId = oldId

	interactorIds, err := i.List("like")
	if err != nil {
		return nil, err
	}

	oldIds, err := FetchMongoIdsByAccountIds(interactorIds)
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = oldIds

	isInteracted, err := i.IsInteracted(c.AccountId)
	if err != nil {
		return nil, err
	}

	interactionContainer.IsInteracted = isInteracted

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}

func (c *ChannelMessage) BuildMessage() (*ChannelMessageContainer, error) {
	cmc, err := c.FetchRelatives()
	if err != nil {
		return nil, err
	}

	mr := NewMessageReply()
	mr.MessageId = c.Id
	replies, err := mr.List()
	if err != nil {
		return nil, err
	}

	populatedChannelMessagesReplies := make([]*ChannelMessageContainer, len(replies))
	for rl := 0; rl < len(replies); rl++ {
		cmrc, err := replies[rl].FetchRelatives()
		if err != nil {
			return nil, err
		}
		populatedChannelMessagesReplies[rl] = cmrc
	}

	cmc.Replies = populatedChannelMessagesReplies
	return cmc, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin"
	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin/psp/onlineworldpay"
	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin/types"
)

// Application flags
var flagWPServiceKey string
var flagWPClientKey string

// Application Vars
var wpw wpwithin.WPWithin
var wpwHandler Handler

const (
	redDescr    string = "Turn on the red LED"
	greenDescr  string = "Turn on the green LED"
	yellowDescr string = "Turn on the yellow LED"
	oneSecond   string = "One second"
	oneMinute   string = "One minute"
)

func init() {

	flag.StringVar(&flagWPServiceKey, "wpservicekey", "", "Worldpay service key")
	flag.StringVar(&flagWPClientKey, "wpclientkey", "", "Worldpay client key")
}

func main() {

	flag.Parse()

	if strings.EqualFold(flagWPClientKey, "") {
		fmt.Println("Flag wpclientkey is required")
		os.Exit(1)
	} else if strings.EqualFold(flagWPServiceKey, "") {
		fmt.Println("Flag wpservicekey is required")
		os.Exit(1)
	}

	_wpw, err := wpwithin.Initialise("WPW Pi LED", "Worldpay Within Pi LED Demo")
	wpw = _wpw

	errCheck(err, "WorldpayWithin Initialise")

	doSetupServices()

	// wpwhandler accepts callbacks from worldpay within when service delivery begin/end is required.
	err = wpwHandler.setup()
	errCheck(err, "wpwHandler setup")
	wpw.SetEventHandler(&wpwHandler)

	pspConfig := map[string]string{
		onlineworldpay.CfgMerchantClientKey:  flagWPClientKey,
		onlineworldpay.CfgMerchantServiceKey: flagWPServiceKey,
	}
	err = wpw.InitProducer(pspConfig)

	errCheck(err, "Init producer")

	err = wpw.StartServiceBroadcast(0) // 0 = no timeout

	errCheck(err, "start service broadcast")

	// run the app until it is closed
	runForever()
}

func doSetupServices() {

	////////////////////////////////////////////
	// Green LED
	////////////////////////////////////////////

	svcGreenLed, err := types.NewService()
	errCheck(err, "Create new service - Green LED")
	svcGreenLed.ID = 1
	svcGreenLed.Name = "Big LED"
	svcGreenLed.Description = greenDescr

	priceGreenLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - green led second")

	priceGreenLedSecond.Description = greenDescr
	priceGreenLedSecond.ID = 1
	priceGreenLedSecond.UnitDescription = oneSecond
	priceGreenLedSecond.UnitID = 1
	priceGreenLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       10,
		CurrencyCode: "GBP",
	}

	svcGreenLed.AddPrice(*priceGreenLedSecond)

	priceGreenLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - green led minute")

	priceGreenLedMinute.Description = greenDescr
	priceGreenLedMinute.ID = 2
	priceGreenLedMinute.UnitDescription = oneMinute
	priceGreenLedMinute.UnitID = 2
	priceGreenLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       40, /* WOAH! This is minor units so means just 40p */
		CurrencyCode: "GBP",
	}

	svcGreenLed.AddPrice(*priceGreenLedMinute)

	err = wpw.AddService(svcGreenLed)
	errCheck(err, "Add service - green led")

	////////////////////////////////////////////
	// Red LED
	////////////////////////////////////////////

	svcRedLed, err := types.NewService()
	errCheck(err, "New service - red led")

	svcRedLed.ID = 2
	svcRedLed.Name = "Red LED"
	svcRedLed.Description = redDescr

	priceRedLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - red led second")

	priceRedLedSecond.Description = redDescr
	priceRedLedSecond.ID = 3
	priceRedLedSecond.UnitDescription = oneSecond
	priceRedLedSecond.UnitID = 1
	priceRedLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       5,
		CurrencyCode: "GBP",
	}

	svcRedLed.AddPrice(*priceRedLedSecond)

	priceRedLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - red led minute")

	priceRedLedMinute.Description = redDescr
	priceRedLedMinute.ID = 4
	priceRedLedMinute.UnitDescription = oneMinute
	priceRedLedMinute.UnitID = 2
	priceRedLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       20,
		CurrencyCode: "GBP",
	}

	svcRedLed.AddPrice(*priceRedLedMinute)

	err = wpw.AddService(svcRedLed)
	errCheck(err, "Add service - red led")

	////////////////////////////////////////////
	// Yellow LED
	////////////////////////////////////////////

	svcYellowLed, err := types.NewService()
	errCheck(err, "New service - yellow led")

	svcYellowLed.ID = 3
	svcYellowLed.Name = "Yellow LED"
	svcYellowLed.Description = yellowDescr

	priceYellowLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - yellow led second")

	priceYellowLedSecond.Description = yellowDescr
	priceYellowLedSecond.ID = 1
	priceYellowLedSecond.UnitDescription = oneSecond
	priceYellowLedSecond.UnitID = 1
	priceYellowLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       5,
		CurrencyCode: "GBP",
	}

	svcYellowLed.AddPrice(*priceYellowLedSecond)

	priceYellowLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - yellow led minute")

	priceYellowLedMinute.Description = yellowDescr
	priceYellowLedMinute.ID = 2
	priceYellowLedMinute.UnitDescription = oneMinute
	priceYellowLedMinute.UnitID = 2
	priceYellowLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       20,
		CurrencyCode: "GBP",
	}

	svcYellowLed.AddPrice(*priceYellowLedMinute)

	err = wpw.AddService(svcYellowLed)
	errCheck(err, "Add service - yellow led")
}

func errCheck(err error, hint string) {

	if err != nil {
		fmt.Printf("Did encounter error during: %s", hint)
		fmt.Println(err.Error())
		fmt.Println("Quitting...")
		os.Exit(1)
	}
}

func runForever() {

	done := make(chan bool)
	fnForever := func() {
		for {
			time.Sleep(time.Second * 10)
		}
	}

	go fnForever()

	<-done // Block forever
}
<commit_msg>Change device name/description.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin"
	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin/psp/onlineworldpay"
	"github.com/wptechinnovation/worldpay-within-sdk/sdkcore/wpwithin/types"
)

// Application flags
var flagWPServiceKey string
var flagWPClientKey string

// Application Vars
var wpw wpwithin.WPWithin
var wpwHandler Handler

const (
	redDescr    string = "Turn on the red LED"
	greenDescr  string = "Turn on the green LED"
	yellowDescr string = "Turn on the yellow LED"
	oneSecond   string = "One second"
	oneMinute   string = "One minute"
)

func init() {

	flag.StringVar(&flagWPServiceKey, "wpservicekey", "", "Worldpay service key")
	flag.StringVar(&flagWPClientKey, "wpclientkey", "", "Worldpay client key")
}

func main() {

	flag.Parse()

	if strings.EqualFold(flagWPClientKey, "") {
		fmt.Println("Flag wpclientkey is required")
		os.Exit(1)
	} else if strings.EqualFold(flagWPServiceKey, "") {
		fmt.Println("Flag wpservicekey is required")
		os.Exit(1)
	}

	_wpw, err := wpwithin.Initialise("pi-led-producer", "Worldpay Within Pi LED Demo - Producer")
	wpw = _wpw

	errCheck(err, "WorldpayWithin Initialise")

	doSetupServices()

	// wpwhandler accepts callbacks from worldpay within when service delivery begin/end is required.
	err = wpwHandler.setup()
	errCheck(err, "wpwHandler setup")
	wpw.SetEventHandler(&wpwHandler)

	pspConfig := map[string]string{
		onlineworldpay.CfgMerchantClientKey:  flagWPClientKey,
		onlineworldpay.CfgMerchantServiceKey: flagWPServiceKey,
	}
	err = wpw.InitProducer(pspConfig)

	errCheck(err, "Init producer")

	err = wpw.StartServiceBroadcast(0) // 0 = no timeout

	errCheck(err, "start service broadcast")

	// run the app until it is closed
	runForever()
}

func doSetupServices() {

	////////////////////////////////////////////
	// Green LED
	////////////////////////////////////////////

	svcGreenLed, err := types.NewService()
	errCheck(err, "Create new service - Green LED")
	svcGreenLed.ID = 1
	svcGreenLed.Name = "Big LED"
	svcGreenLed.Description = greenDescr

	priceGreenLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - green led second")

	priceGreenLedSecond.Description = greenDescr
	priceGreenLedSecond.ID = 1
	priceGreenLedSecond.UnitDescription = oneSecond
	priceGreenLedSecond.UnitID = 1
	priceGreenLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       10,
		CurrencyCode: "GBP",
	}

	svcGreenLed.AddPrice(*priceGreenLedSecond)

	priceGreenLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - green led minute")

	priceGreenLedMinute.Description = greenDescr
	priceGreenLedMinute.ID = 2
	priceGreenLedMinute.UnitDescription = oneMinute
	priceGreenLedMinute.UnitID = 2
	priceGreenLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       40, /* WOAH! This is minor units so means just 40p */
		CurrencyCode: "GBP",
	}

	svcGreenLed.AddPrice(*priceGreenLedMinute)

	err = wpw.AddService(svcGreenLed)
	errCheck(err, "Add service - green led")

	////////////////////////////////////////////
	// Red LED
	////////////////////////////////////////////

	svcRedLed, err := types.NewService()
	errCheck(err, "New service - red led")

	svcRedLed.ID = 2
	svcRedLed.Name = "Red LED"
	svcRedLed.Description = redDescr

	priceRedLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - red led second")

	priceRedLedSecond.Description = redDescr
	priceRedLedSecond.ID = 3
	priceRedLedSecond.UnitDescription = oneSecond
	priceRedLedSecond.UnitID = 1
	priceRedLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       5,
		CurrencyCode: "GBP",
	}

	svcRedLed.AddPrice(*priceRedLedSecond)

	priceRedLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - red led minute")

	priceRedLedMinute.Description = redDescr
	priceRedLedMinute.ID = 4
	priceRedLedMinute.UnitDescription = oneMinute
	priceRedLedMinute.UnitID = 2
	priceRedLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       20,
		CurrencyCode: "GBP",
	}

	svcRedLed.AddPrice(*priceRedLedMinute)

	err = wpw.AddService(svcRedLed)
	errCheck(err, "Add service - red led")

	////////////////////////////////////////////
	// Yellow LED
	////////////////////////////////////////////

	svcYellowLed, err := types.NewService()
	errCheck(err, "New service - yellow led")

	svcYellowLed.ID = 3
	svcYellowLed.Name = "Yellow LED"
	svcYellowLed.Description = yellowDescr

	priceYellowLedSecond, err := types.NewPrice()
	errCheck(err, "Create new price - yellow led second")

	priceYellowLedSecond.Description = yellowDescr
	priceYellowLedSecond.ID = 1
	priceYellowLedSecond.UnitDescription = oneSecond
	priceYellowLedSecond.UnitID = 1
	priceYellowLedSecond.PricePerUnit = &types.PricePerUnit{
		Amount:       5,
		CurrencyCode: "GBP",
	}

	svcYellowLed.AddPrice(*priceYellowLedSecond)

	priceYellowLedMinute, err := types.NewPrice()
	errCheck(err, "Create new price - yellow led minute")

	priceYellowLedMinute.Description = yellowDescr
	priceYellowLedMinute.ID = 2
	priceYellowLedMinute.UnitDescription = oneMinute
	priceYellowLedMinute.UnitID = 2
	priceYellowLedMinute.PricePerUnit = &types.PricePerUnit{
		Amount:       20,
		CurrencyCode: "GBP",
	}

	svcYellowLed.AddPrice(*priceYellowLedMinute)

	err = wpw.AddService(svcYellowLed)
	errCheck(err, "Add service - yellow led")
}

func errCheck(err error, hint string) {

	if err != nil {
		fmt.Printf("Did encounter error during: %s", hint)
		fmt.Println(err.Error())
		fmt.Println("Quitting...")
		os.Exit(1)
	}
}

func runForever() {

	done := make(chan bool)
	fnForever := func() {
		for {
			time.Sleep(time.Second * 10)
		}
	}

	go fnForever()

	<-done // Block forever
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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 config

import "testing"

func TestConfigValidate(t *testing.T) {
	cases := []struct {
		TestName       string
		Config         *Config
		ExpectedErrors int
	}{
		{
			TestName:       "Canonical config",
			Config:         New(),
			ExpectedErrors: 0,
		},
		{
			TestName: "Invalid number of nodes (not yet supported",
			Config: &Config{
				NumNodes: 2,
			},
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PreBoot hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PreBoot: []LifecycleHook{
						{
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PreKubeadm hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PreKubeadm: []LifecycleHook{
						{
							Name:    "pull an image",
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PostKubeadm hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PostKubeadm: []LifecycleHook{
						{
							Name:    "pull an image",
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
	}

	for _, tc := range cases {
		err := tc.Config.Validate()
		// the error can be:
		// - nil, in which case we should expect no errors or fail
		if err == nil {
			if tc.ExpectedErrors != 0 {
				t.Errorf("received no errors but expected errors for case %s", tc.TestName)
			}
			continue
		}
		// - not castable to *Errors, in which case we have the wrong error type ...
		configErrors, ok := err.(*Errors)
		if !ok {
			t.Errorf("config.Validate should only return nil or ConfigErrors{...}, got: %v for case: %s", err, tc.TestName)
			continue
		}
		// - ConfigErrors, in which case expect a certain number of errors
		errors := configErrors.Errors()
		if len(errors) != tc.ExpectedErrors {
			t.Errorf("expected %d errors but got len(%v) = %d for case: %s", tc.ExpectedErrors, errors, len(errors), tc.TestName)
		}
	}
}
<commit_msg>Add validation test cases for image name<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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 config

import "testing"

func TestConfigValidate(t *testing.T) {
	cases := []struct {
		TestName       string
		Config         *Config
		ExpectedErrors int
	}{
		{
			TestName:       "Canonical config",
			Config:         New(),
			ExpectedErrors: 0,
		},
		{
			TestName: "Invalid number of nodes (not yet supported",
			Config: func() *Config {
				cfg := New()
				cfg.NumNodes = 2
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PreBoot hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PreBoot: []LifecycleHook{
						{
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PreKubeadm hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PreKubeadm: []LifecycleHook{
						{
							Name:    "pull an image",
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Invalid PostKubeadm hook",
			Config: func() *Config {
				cfg := New()
				cfg.NodeLifecycle = &NodeLifecycle{
					PostKubeadm: []LifecycleHook{
						{
							Name:    "pull an image",
							Command: "",
						},
					},
				}
				return cfg
			}(),
			ExpectedErrors: 1,
		},
		{
			TestName: "Empty image field",
			Config: func() *Config {
				cfg := New()
				cfg.Image = ""
				return cfg
			}(),
			ExpectedErrors: 1,
		},
	}

	for _, tc := range cases {
		err := tc.Config.Validate()
		// the error can be:
		// - nil, in which case we should expect no errors or fail
		if err == nil {
			if tc.ExpectedErrors != 0 {
				t.Errorf("received no errors but expected errors for case %s", tc.TestName)
			}
			continue
		}
		// - not castable to *Errors, in which case we have the wrong error type ...
		configErrors, ok := err.(*Errors)
		if !ok {
			t.Errorf("config.Validate should only return nil or ConfigErrors{...}, got: %v for case: %s", err, tc.TestName)
			continue
		}
		// - ConfigErrors, in which case expect a certain number of errors
		errors := configErrors.Errors()
		if len(errors) != tc.ExpectedErrors {
			t.Errorf("expected %d errors but got len(%v) = %d for case: %s", tc.ExpectedErrors, errors, len(errors), tc.TestName)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"./internal"
	"./codec"
	"./utils"
	"./socks/socks5"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"log"
	"net"
)

const (
	clientPoolSize int = 10
)

func newClient() (x interface{}){
	opts := []grpc.DialOption{}

	if len(*certFile) > 0 {
		//https
		creds, err := credentials.NewClientTLSFromFile(*certFile, *server)
		if err != nil {
			log.Fatalln(err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}

	//enable snappy
	c, err := codec.New("snappy")
	if err != nil {
		log.Fatalln(err)
	}
	var cc grpc.Codec
	cc, err = codec.WithProto(c)
	if err != nil {
		log.Fatalln(err)
	}
	opts = append(opts, grpc.WithCodec(cc))

	var client *internal.Client
	client, err = internal.NewClient(*server, opts...)
	if err != nil {
		log.Fatalln(err)
	}
	return client
}

func deleteClient(x interface{}) {
	client := x.(*internal.Client)

	err := client.Close()
	if err != nil {
		log.Println(err)
	}
}

type PoolDialer struct {
	Pool *utils.Pool
}

func (pd *PoolDialer) Dial(network, address string) (conn net.Conn, err error) {
	dialer := pd.Pool.Get().(*internal.Client)
	defer pd.Pool.Put(dialer)

	return dialer.Dial(network, address)
}

func run_as_local() {
	pool := utils.NewPool(newClient, deleteClient, clientPoolSize)
	pd := &PoolDialer{
		Pool: pool,
	}

	srv := socks5.Server{
		Dialer: pd,
	}
	err := srv.ListenAndServe("tcp", *listen)
	if err != nil {
		log.Fatalln(err)
	}
}<commit_msg>添加local日志<commit_after>package main

import (
	"./internal"
	"./codec"
	"./utils"
	"./socks/socks5"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"log"
	"net"
	"fmt"
)

const (
	clientPoolSize int = 10
)

func newClient() (x interface{}){
	opts := []grpc.DialOption{}

	if len(*certFile) > 0 {
		//https
		creds, err := credentials.NewClientTLSFromFile(*certFile, *server)
		if err != nil {
			log.Fatalln(err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}

	//enable snappy
	c, err := codec.New("snappy")
	if err != nil {
		log.Fatalln(err)
	}
	var cc grpc.Codec
	cc, err = codec.WithProto(c)
	if err != nil {
		log.Fatalln(err)
	}
	opts = append(opts, grpc.WithCodec(cc))

	var client *internal.Client
	client, err = internal.NewClient(*server, opts...)
	if err != nil {
		log.Fatalln(err)
	}
	return client
}

func deleteClient(x interface{}) {
	client := x.(*internal.Client)

	err := client.Close()
	if err != nil {
		log.Println(err)
	}
}

type PoolDialer struct {
	Pool *utils.Pool
}

func (pd *PoolDialer) Dial(network, address string) (conn net.Conn, err error) {
	dialer := pd.Pool.Get().(*internal.Client)
	defer pd.Pool.Put(dialer)

	log.Println("Dial", fmt.Sprintf("%s/%s", network, address))
	return dialer.Dial(network, address)
}

func run_as_local() {
	pool := utils.NewPool(newClient, deleteClient, clientPoolSize)
	pd := &PoolDialer{
		Pool: pool,
	}

	srv := socks5.Server{
		Dialer: pd,
	}
	err := srv.ListenAndServe("tcp", *listen)
	if err != nil {
		log.Fatalln(err)
	}
}<|endoftext|>