<commit_before>package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/vg/veceps"
	"code.google.com/p/plotinum/vg/vecimg"
	"math/rand"
	//	"time"
	"testing"
)

var seed = int64(0) // time.Now().UnixNano()

func TestDrawImage(t *testing.T) {
	w, h := vg.Inches(4), vg.Inches(4)
	img, err := vecimg.New(w, h)
	if err != nil {
		t.Error(err)
	}
	da := NewDrawArea(img, w, h)
	draw(da)
	err = img.SavePNG("test.png")
	if err != nil {
		t.Fatal(err)
	}
}

func TestDrawEps(t *testing.T) {
	w, h := vg.Inches(4), vg.Inches(2)
	da := NewDrawArea(veceps.New(w, h, "test"), w, h)
	draw(da)
	err := da.Canvas.(*veceps.Canvas).Save("test.eps")
	if err != nil {
		t.Fatal(err)
	}
}

// draw draws a simple test plot
func draw(da *DrawArea) {
	rand.Seed(seed)
	n := 10
	uniform := make(Ys, n)
	normal := make(Ys, n)
	expon := make(Ys, n)
	for i := 0; i < n; i++ {
		uniform[i] = rand.Float64()
		normal[i] = rand.NormFloat64()
		expon[i] = rand.ExpFloat64()
	}
	p, err := New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Plot Title"
	p.X.Label.Text = "Values"

	b0 := MakeHorizBox(vg.Points(20), 0, uniform)
	b1 := MakeHorizBox(vg.Points(20), 1, normal)
	b2 := MakeHorizBox(vg.Points(20), 2, expon)
	p.AddData(b0, b1, b2)
	p.Legend.AddEntry("outliers", b0.GlyphStyle)
	p.NominalY("Uniform\nDistribution", "Normal\nDistribution",
		"Exponential\nDistribution")

	_, med0, _, _ := b0.Statistics()
	_, med1, _, _ := b1.Statistics()
	_, med2, _, _ := b2.Statistics()
	meds := XYs{{med0, b0.X}, {med1, b1.X}, {med2, b2.X}}
	l := Line{meds, DefaultLineStyle}
	s := Scatter{meds, GlyphStyle{Shape: CircleGlyph, Radius: vg.Points(2)}}
	p.AddData(l, s)
	p.Legend.AddEntry("median", l, s)
	p.Draw(da)
}
<commit_msg>Tiny change to the demo plot.<commit_after>package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/vg/veceps"
	"code.google.com/p/plotinum/vg/vecimg"
	"math/rand"
	//	"time"
	"testing"
)

var seed = int64(0) // time.Now().UnixNano()

func TestDrawImage(t *testing.T) {
	w, h := vg.Inches(4), vg.Inches(2)
	img, err := vecimg.New(w, h)
	if err != nil {
		t.Error(err)
	}
	da := NewDrawArea(img, w, h)
	draw(da)
	err = img.SavePNG("test.png")
	if err != nil {
		t.Fatal(err)
	}
}

func TestDrawEps(t *testing.T) {
	w, h := vg.Inches(4), vg.Inches(2)
	da := NewDrawArea(veceps.New(w, h, "test"), w, h)
	draw(da)
	err := da.Canvas.(*veceps.Canvas).Save("test.eps")
	if err != nil {
		t.Fatal(err)
	}
}

// draw draws a simple test plot
func draw(da *DrawArea) {
	rand.Seed(seed)
	n := 10
	uniform := make(Ys, n)
	normal := make(Ys, n)
	expon := make(Ys, n)
	for i := 0; i < n; i++ {
		uniform[i] = rand.Float64()
		normal[i] = rand.NormFloat64()
		expon[i] = rand.ExpFloat64()
	}
	p, err := New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Plot Title"
	p.X.Label.Text = "Values"

	b0 := MakeHorizBox(vg.Points(20), 0, uniform)
	b1 := MakeHorizBox(vg.Points(20), 1, normal)
	b2 := MakeHorizBox(vg.Points(20), 2, expon)
	p.AddData(b0, b1, b2)
	p.Legend.AddEntry("outliers", b0.GlyphStyle)
	p.NominalY("Uniform\nDistribution", "Normal\nDistribution",
		"Exponential\nDistribution")

	_, med0, _, _ := b0.Statistics()
	_, med1, _, _ := b1.Statistics()
	_, med2, _, _ := b2.Statistics()
	meds := XYs{{med0, b0.X}, {med1, b1.X}, {med2, b2.X}}
	l := Line{meds, DefaultLineStyle}
	s := Scatter{meds, GlyphStyle{Shape: CircleGlyph, Radius: vg.Points(2)}}
	p.AddData(l, s)
	p.Legend.AddEntry("median", l, s)
	p.Draw(da)
}
<|endoftext|>


<commit_before>package controllers

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"strconv"

	"code.google.com/p/freetype-go/freetype/truetype"
	"github.com/robfig/revel"
	"github.com/slok/gummyimage"
)

type Application struct {
	*revel.Controller
}

type ImageResponse struct {
	sizeX   int
	sizeY   int
	bgColor string
	fgColor string
	text    string
	format  string
}

// Global variable
var (
	font              *truetype.Font
	regularSizeRegex  = regexp.MustCompile(`^(.+)[xX](.+)$`)
	aspectSizeRegex   = regexp.MustCompile(`^(.+):(.+)$`)
	correctColorRegex = regexp.MustCompile(`^[A-Fa-f0-9]{2,6}$`)
	formatRegex       = regexp.MustCompile(`\.(jpg|jpeg|JPG|JPEG|gif|GIF|png|PNG)`)
)

// Custom responses -----------------------------------------------------------
// Custom response for image
func (r ImageResponse) Apply(req *revel.Request, resp *revel.Response) {

	// FIX:
	// If settings loaded out of actions then revel throws nil pointer, so we
	// load here the first time only
	if font == nil {
		fontPath, _ := revel.Config.String("gummyimage.fontpath")
		font, _ = gummyimage.LoadFont(fontPath)
	}

	resp.WriteHeader(http.StatusOK, "image/png")

	g, _ := gummyimage.NewDefaultGummy(r.sizeX, r.sizeY, r.bgColor)
	g.Font = font

	// Custom text?
	if len(r.text) == 0 {
		g.DrawTextSize(r.fgColor)
	} else {
		g.DrawTextCenter(r.text, r.fgColor)
	}

	b := new(bytes.Buffer)
	g.Get(r.format, b)
	resp.Out.Write(b.Bytes())
}

// Actions --------------------------------------------------------------------
func (c Application) Index() revel.Result {
	return c.Render()
}

func (c Application) CreateImage() revel.Result {

	// Get params by dict because we use this action for 3 different url routes
	// with different url params
	var bgColor, fgColor string
	format, _ := revel.Config.String("gummyimage.format.default")
	text := c.Params.Get("text")

	tmpValues := []string{
		c.Params.Get("size"),
		c.Params.Get("bgcolor"),
		c.Params.Get("fgcolor"),
	}

	// Get format
	for k, i := range tmpValues {
		if f := formatRegex.FindStringSubmatch(i); len(f) > 0 {
			format = f[1]
			tmpValues[k] = formatRegex.ReplaceAllString(i, "")
		}
	}

	x, y, err := getSize(tmpValues[0])
	bgColor, err = colorOk(tmpValues[1])
	fgColor = tmpValues[2]

	if err != nil {
		return c.RenderText("Wrong size format")
	}

	// Check limits, don't allow gigantic images :P
	maxY, _ := revel.Config.String("gummyimage.max.height")
	maxX, _ := revel.Config.String("gummyimage.max.width")
	tmx, _ := strconv.Atoi(maxX)
	tmy, _ := strconv.Atoi(maxY)
	if x > tmx || y > tmy {
		return c.RenderText("wow, very big, too image,// Color in HEX format: FAFAFA much pixels")
	}

	return ImageResponse(ImageResponse{x, y, bgColor, fgColor, text, format})
}

// Helpers--------------------------------------------------------------------

// Gets the correct size based on the patern
// Supports:
//  - Predefined sizes (in app.conf)
//  - Aspect sizes: nnnXnn:nn & nn:nnXnnn
//  - Square: nnn
//  - Regular: nnnXnnn & nnnxnnn
func getSize(size string) (x, y int, err error) {

	// Check if is a standard size
	if s, found := revel.Config.String(fmt.Sprintf("size.%v", size)); found {
		size = s
	}

	// Normal size (nnnxnnn, nnnXnnn)
	sizes := regularSizeRegex.FindStringSubmatch(size)
	if len(sizes) > 0 {
		// Check if aspect (nn:nn)

		left := aspectSizeRegex.FindStringSubmatch(sizes[1])
		right := aspectSizeRegex.FindStringSubmatch(sizes[2])

		// If both scale then error
		if len(left) > 0 && len(right) > 0 {
			err = errors.New("Not correct size")
			return

		} else if len(left) > 0 { // nn:nnXnnn
			y, _ = strconv.Atoi(sizes[2])
			tll, _ := strconv.Atoi(left[1])
			tlr, _ := strconv.Atoi(left[2])
			x = y * tll / tlr
		} else if len(right) > 0 { // nnnXnn:nn
			x, _ = strconv.Atoi(sizes[1])
			trl, _ := strconv.Atoi(right[1])
			trr, _ := strconv.Atoi(right[2])
			y = x * trr / trl
		} else { // nnnXnnn
			x, _ = strconv.Atoi(sizes[1])
			y, _ = strconv.Atoi(sizes[2])
		}

	} else { // Square (nnn)
		x, _ = strconv.Atoi(size)
		y = x
	}

	if x == 0 || y == 0 {
		err = errors.New("Not correct size")
	}
	return
}

func colorOk(color string) (bgColor string, err error) {

	// Set defaults
	if color == "" {
		bgColor, _ = revel.Config.String("gummyimage.bgcolor.default")
		return
	} else if !correctColorRegex.MatchString(color) {
		bgColor, _ = revel.Config.String("gummyimage.bgcolor.default")
		err = errors.New("Wrong color format")
		return
	} else {
		switch len(color) {
		case 2:
			bgColor = fmt.Sprintf("%s%s%s", color, color, color)
			return
		case 3:
			c1 := string(color[0])
			c2 := string(color[1])
			c3 := string(color[2])
			bgColor = fmt.Sprintf("%s%s%s%s%s%s", c1, c1, c2, c2, c3, c3)
			return
		}
	}
	bgColor = color
	return
}
<commit_msg>Fixed text color expansion<commit_after>package controllers

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"strconv"

	"code.google.com/p/freetype-go/freetype/truetype"
	"github.com/robfig/revel"
	"github.com/slok/gummyimage"
)

type Application struct {
	*revel.Controller
}

type ImageResponse struct {
	sizeX   int
	sizeY   int
	bgColor string
	fgColor string
	text    string
	format  string
}

// Global variable
var (
	font              *truetype.Font
	regularSizeRegex  = regexp.MustCompile(`^(.+)[xX](.+)$`)
	aspectSizeRegex   = regexp.MustCompile(`^(.+):(.+)$`)
	correctColorRegex = regexp.MustCompile(`^[A-Fa-f0-9]{2,6}$`)
	formatRegex       = regexp.MustCompile(`\.(jpg|jpeg|JPG|JPEG|gif|GIF|png|PNG)`)
)

// Custom responses -----------------------------------------------------------
// Custom response for image
func (r ImageResponse) Apply(req *revel.Request, resp *revel.Response) {

	// FIX:
	// If settings loaded out of actions then revel throws nil pointer, so we
	// load here the first time only
	if font == nil {
		fontPath, _ := revel.Config.String("gummyimage.fontpath")
		font, _ = gummyimage.LoadFont(fontPath)
	}

	resp.WriteHeader(http.StatusOK, "image/png")

	g, _ := gummyimage.NewDefaultGummy(r.sizeX, r.sizeY, r.bgColor)
	g.Font = font

	// Custom text?
	if len(r.text) == 0 {
		g.DrawTextSize(r.fgColor)
	} else {
		g.DrawTextCenter(r.text, r.fgColor)
	}

	b := new(bytes.Buffer)
	g.Get(r.format, b)
	resp.Out.Write(b.Bytes())
}

// Actions --------------------------------------------------------------------
func (c Application) Index() revel.Result {
	return c.Render()
}

func (c Application) CreateImage() revel.Result {

	// Get params by dict because we use this action for 3 different url routes
	// with different url params
	var bgColor, fgColor string
	format, _ := revel.Config.String("gummyimage.format.default")
	text := c.Params.Get("text")

	tmpValues := []string{
		c.Params.Get("size"),
		c.Params.Get("bgcolor"),
		c.Params.Get("fgcolor"),
	}

	// Get format
	for k, i := range tmpValues {
		if f := formatRegex.FindStringSubmatch(i); len(f) > 0 {
			format = f[1]
			tmpValues[k] = formatRegex.ReplaceAllString(i, "")
		}
	}

	x, y, err := getSize(tmpValues[0])
	bgColor, err = colorOk(tmpValues[1])

	if len(tmpValues[2]) > 0 {
		fgColor, err = colorOk(tmpValues[2])
	}

	if err != nil {
		return c.RenderText("Wrong size format")
	}

	// Check limits, don't allow gigantic images :P
	maxY, _ := revel.Config.String("gummyimage.max.height")
	maxX, _ := revel.Config.String("gummyimage.max.width")
	tmx, _ := strconv.Atoi(maxX)
	tmy, _ := strconv.Atoi(maxY)
	if x > tmx || y > tmy {
		return c.RenderText("wow, very big, too image,// Color in HEX format: FAFAFA much pixels")
	}

	return ImageResponse(ImageResponse{x, y, bgColor, fgColor, text, format})
}

// Helpers--------------------------------------------------------------------

// Gets the correct size based on the patern
// Supports:
//  - Predefined sizes (in app.conf)
//  - Aspect sizes: nnnXnn:nn & nn:nnXnnn
//  - Square: nnn
//  - Regular: nnnXnnn & nnnxnnn
func getSize(size string) (x, y int, err error) {

	// Check if is a standard size
	if s, found := revel.Config.String(fmt.Sprintf("size.%v", size)); found {
		size = s
	}

	// Normal size (nnnxnnn, nnnXnnn)
	sizes := regularSizeRegex.FindStringSubmatch(size)
	if len(sizes) > 0 {
		// Check if aspect (nn:nn)

		left := aspectSizeRegex.FindStringSubmatch(sizes[1])
		right := aspectSizeRegex.FindStringSubmatch(sizes[2])

		// If both scale then error
		if len(left) > 0 && len(right) > 0 {
			err = errors.New("Not correct size")
			return

		} else if len(left) > 0 { // nn:nnXnnn
			y, _ = strconv.Atoi(sizes[2])
			tll, _ := strconv.Atoi(left[1])
			tlr, _ := strconv.Atoi(left[2])
			x = y * tll / tlr
		} else if len(right) > 0 { // nnnXnn:nn
			x, _ = strconv.Atoi(sizes[1])
			trl, _ := strconv.Atoi(right[1])
			trr, _ := strconv.Atoi(right[2])
			y = x * trr / trl
		} else { // nnnXnnn
			x, _ = strconv.Atoi(sizes[1])
			y, _ = strconv.Atoi(sizes[2])
		}

	} else { // Square (nnn)
		x, _ = strconv.Atoi(size)
		y = x
	}

	if x == 0 || y == 0 {
		err = errors.New("Not correct size")
	}
	return
}

func colorOk(color string) (newColor string, err error) {

	// Set defaults
	if color == "" {
		newColor, _ = revel.Config.String("gummyimage.bgcolor.default")
		return
	} else if !correctColorRegex.MatchString(color) {
		newColor, _ = revel.Config.String("gummyimage.bgcolor.default")
		err = errors.New("Wrong color format")
		return
	} else {
		switch len(color) {
		case 1:
			newColor = ""
			for i := 0; i < 6; i++ {
				newColor += color
			}
			return
		case 2:
			newColor = fmt.Sprintf("%s%s%s", color, color, color)
			return
		case 3:
			c1 := string(color[0])
			c2 := string(color[1])
			c3 := string(color[2])
			newColor = fmt.Sprintf("%s%s%s%s%s%s", c1, c1, c2, c2, c3, c3)
			return
		}
	}
	newColor = color
	return
}
<|endoftext|>


<commit_before>package blobstore

import (
	"encoding/hex"
	"strings"
	"testing"
)

var simpleTests = []struct {
	content string
	blobHex string
	key     string
	bid     string
}{
	{
		"",
		"01 eb",
		"01 7b54b668 36c1fbdd 13d2441d 9e1434dc 62ca677f b68f5fe6 6a464baa decdbd00",
		"b4f5a7bb 878c0cec 9cb4bd6a e8bb175a 7ea59c1a 048c5ab7 c119990d 0041cb9c fb67c2aa 9e6fada8 11271977 7b4b80ff ada80205 f8ebe698 1c0ade97 ff3df8e5"},
}

func TestEmptyFile(t *testing.T) {

	for _, test := range simpleTests {

		key := strings.Replace(test.key, " ", "", -1)
		bid := strings.Replace(test.bid, " ", "", -1)
		blob, _ := hex.DecodeString(strings.Replace(test.blobHex, " ", "", -1))

		m := NewMemoryBlobStorage()
		bw := FileBlobWriter{Storage: m}
		bw.Write([]byte(test.content))

		rbid, rkey, err := bw.Finalize()
		if err != nil {
			t.Error(err)
		}

		if rbid != bid {
			t.Errorf("Invalid blob id generated, got: %v, expected: %v", rbid, bid)
		}

		if rkey != key {
			t.Error("Invalid key generated, got: %v, expected: %v", rkey, key)
		}
		// TODO: Test the blob content
		blob = blob
	}
}
<commit_msg>Improve the file blob writer test by adding blob content test<commit_after>package blobstore

import (
	"bytes"
	"encoding/hex"
	"io/ioutil"
	"strings"
	"testing"
)

var simpleTests = []struct {
	content string
	blobHex string
	key     string
	bid     string
}{
	{ // Empty file
		"",
		"01 eb",
		"01 7b54b668 36c1fbdd 13d2441d 9e1434dc 62ca677f b68f5fe6 6a464baa decdbd00",
		"b4f5a7bb 878c0cec 9cb4bd6a e8bb175a 7ea59c1a 048c5ab7 c119990d 0041cb9c fb67c2aa 9e6fada8 11271977 7b4b80ff ada80205 f8ebe698 1c0ade97 ff3df8e5"},
}

func TestEmptyFile(t *testing.T) {

	for _, test := range simpleTests {

		key := strings.Replace(test.key, " ", "", -1)
		bid := strings.Replace(test.bid, " ", "", -1)
		blob, _ := hex.DecodeString(strings.Replace(test.blobHex, " ", "", -1))

		m := NewMemoryBlobStorage()
		bw := FileBlobWriter{Storage: m}
		bw.Write([]byte(test.content))

		rbid, rkey, err := bw.Finalize()
		if err != nil {
			t.Error(err)
		}

		if rbid != bid {
			t.Errorf("Invalid blob id generated, got: %v, expected: %v", rbid, bid)
		}

		if rkey != key {
			t.Errorf("Invalid key generated, got: %v, expected: %v", rkey, key)
		}

		reader, err := m.NewBlobReader(rbid)
		if err != nil {
			t.Errorf("Couldn't open the blob with id: %v for reading: %v", rbid, err)
		} else {

			readBytes, err := ioutil.ReadAll(reader)
			if err != nil {
				t.Errorf("Couldn't read the blob with id: %v, error: %v", rbid, err)
			} else if !bytes.Equal(readBytes, blob) {
				t.Errorf("The blob with id: %v has invalid content", rbid)
			}
		}
	}
}
<|endoftext|>


<commit_before>package bongo

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/jinzhu/gorm"
)

// Fetch tries the best option available for retrieving the data first tries
// cache layer, if fails, then tries db
func (b *Bongo) Fetch(i Modellable, id int64) error {
	if id == 0 {
		return IdIsNotSet
	}

	data, ok := i.(Cacher)
	if !ok {
		return errors.New("cacher is not implemented for given struct")
	}

	return b.GetFromBest(i, data, id)
}

// ById Fetches data from db by it's id
func (b *Bongo) ById(i Modellable, id int64) error {
	if err := b.DB.
		Table(i.TableName()).
		Where("id = ?", id).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

// Creates a new record with the given struct and its fields
func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

// Update updates all fields of a struct with assigned data
func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return IdIsNotSet
	}

	// Update and Create is using the Save method, so they are
	// same functions but GORM handles, AfterCreate and AfterUpdate
	// in correct manner
	return b.Create(i)
}

// Delete deletes the data by it's id, it doesnt take any other fields
// into consideration
func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return IdIsNotSet
	}

	if err := b.DB.Delete(i).Error; err != nil {
		return err
	}

	return nil
}

// FetchByIds fetches records by their ids and returns results in the same order
// as the ids; if no records in db we don't return error
func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	orderByQuery := ""
	comma := ""
	for _, id := range ids {
		orderByQuery = orderByQuery + comma + " id = " + strconv.FormatInt(id, 10) + " desc"
		comma = ","
	}

	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	query = query.Order(orderByQuery)

	query = query.Where(ids)

	query = query.Find(data)

	// supress not found errors
	return CheckErr(query)

}

// This function doesnt work, after fixing we can open again
// func (b *Bongo) UpdatePartial(i Modellable, set map[string]interface{}) error {
// 	if i.GetId() == 0 {
// 		return IdIsNotSet
// 	}

// 	// init query
// 	query := b.DB

// 	query = query.Model(i)
// 	// query = query.Table(i.TableName())

// 	query = query.Where("id = ? ", i.GetId())
// 	fmt.Println("query-->", query)
// 	fmt.Printf("set %# v", pretty.Formatter(set))
// 	if err := query.Update(set).Error; err != nil {
// 		fmt.Printf("%# v", pretty.Formatter(err))
// 		return err
// 	}

// 	if err := b.ById(i, i.GetId()); err != nil {
// 		fmt.Printf("%# v", pretty.Formatter(err))
// 		return err
// 	}

// 	fmt.Printf("i %# v", pretty.Formatter(i))
// 	// b.AfterUpdate(i)
// 	return nil
// }

// selector, set
func (b *Bongo) UpdateMulti(i Modellable, rest ...map[string]interface{}) error {
	var set, selector map[string]interface{}

	switch len(rest) {
	case 1:
		set = rest[0]
		selector = nil
	case 2:
		selector = rest[0]
		set = rest[1]
	default:
		return WrongParameter
	}

	query := b.DB.Table(i.TableName())

	//add selector
	query = addWhere(query, selector)

	if err := query.Updates(set).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

func (b *Bongo) CountWithQuery(i Modellable, q *Query) (int, error) {
	query := b.BuildQuery(i, q)
	var count int
	return count, query.Count(&count).Error
}

type Scope func(d *gorm.DB) *gorm.DB

type Query struct {
	Selector   map[string]interface{}
	Sort       map[string]string
	Pluck      string
	Pagination Pagination
	Scopes     []Scope
}

func (q *Query) AddScope(scope Scope) {
	if q.Scopes == nil {
		q.Scopes = make([]Scope, 0)
	}

	q.Scopes = append(q.Scopes, scope)
}

type Pagination struct {
	Limit int
	Skip  int
}

func NewPagination(limit int, skip int) *Pagination {
	return &Pagination{
		Limit: limit,
		Skip:  skip,
	}
}

func NewQS(selector map[string]interface{}) *Query {
	return &Query{
		Selector: selector,
	}
}

// selector, sort, limit, pluck,
func (b *Bongo) Some(i Modellable, data interface{}, q *Query) error {
	err := b.executeQuery(i, data, q)
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, q *Query) error {
	q.Pagination.Limit = 1
	return b.executeQuery(i, data, q)
}

func (b *Bongo) BuildQuery(i Modellable, q *Query) *gorm.DB {
	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	// add sort options
	query = addSort(query, q.Sort)

	query = addSkip(query, q.Pagination.Skip)

	query = addLimit(query, q.Pagination.Limit)

	// add selector
	query = addWhere(query, q.Selector)

	// put scopes
	if q.Scopes != nil && len(q.Scopes) > 0 {
		for _, scope := range q.Scopes {
			query = query.Scopes(scope)
		}
	}

	return query
}

func (b *Bongo) executeQuery(i Modellable, data interface{}, q *Query) error {
	// init query
	query := b.BuildQuery(i, q)

	var err error
	// TODO refactor this part
	if q.Pluck != "" {
		if strings.Contains(q.Pluck, ",") {
			// add pluck data
			query = addPluck(query, q.Pluck)

			err = query.Find(data).Error
		} else {
			err = query.Pluck(q.Pluck, data).Error
		}
	} else {
		err = query.Find(data).Error
	}

	return err
}

func (b *Bongo) PublishEvent(eventName string, i Modellable) error {
	return b.Emit(i.TableName()+"_"+eventName, i)
}

func (b *Bongo) Emit(eventName string, i interface{}) error {
	data, err := json.Marshal(i)
	if err != nil {
		b.log.Error("Error while marshalling for emitting %s", err)
		return err
	}

	err = b.Broker.Publish(eventName, data)
	if err != nil {
		b.log.Error("Error while emitting %s", err)
		return err
	}

	return nil
}

func (b *Bongo) AfterCreate(i Modellable) error {
	b.PublishEvent("created", i)
	return b.AddToCache(i)
}

func (b *Bongo) AfterUpdate(i Modellable) error {
	b.PublishEvent("updated", i)
	return b.AddToCache(i)
}

func (b *Bongo) AfterDelete(i Modellable) error {
	b.PublishEvent("deleted", i)
	return b.AddToCache(i)
}

func (b *Bongo) AddToCache(i Modellable) error {
	data, ok := i.(Cacher)
	if !ok {
		return nil
	}

	err := b.SetToCache(data)
	if err != ErrCacheIsNotEnabled {
		return err
	}

	return nil
}

// addSort injects sort parameters into query
func addSort(query *gorm.DB, options map[string]string) *gorm.DB {

	if options == nil {
		return query
	}

	if len(options) == 0 {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

// addPluck basically adds select statement for
// only required fields
func addPluck(query *gorm.DB, plucked string) *gorm.DB {
	if plucked == "" {
		return query
	}

	return query.Select(plucked)
}

// addWhere adds where query
func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}

	// instead sending one selector, do chaining here
	return query.Where(selector)
}

// addSkip adds skip parameter into sql query
func addSkip(query *gorm.DB, skip int) *gorm.DB {
	if skip > 0 {
		return query.Offset(skip)
	}

	return query
}

// addLimit adds limit into query if set
func addLimit(query *gorm.DB, limit int) *gorm.DB {
	// if limit is minus or 0 ignore
	if limit > 0 {
		return query.Limit(limit)
	}

	return query
}

// CheckErr checks error exitence and returns if found, but this function
// suppress RecordNotFound errors
func CheckErr(res *gorm.DB) error {
	if res == nil {
		return nil
	}

	if res.Error == nil {
		return nil
	}

	if res.Error == gorm.RecordNotFound {
		return nil
	}

	return res.Error
}
<commit_msg>Bongo: Add UnscopedById method<commit_after>package bongo

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/jinzhu/gorm"
)

// Fetch tries the best option available for retrieving the data first tries
// cache layer, if fails, then tries db
func (b *Bongo) Fetch(i Modellable, id int64) error {
	if id == 0 {
		return IdIsNotSet
	}

	data, ok := i.(Cacher)
	if !ok {
		return errors.New("cacher is not implemented for given struct")
	}

	return b.GetFromBest(i, data, id)
}

// ById Fetches data from db by it's id
func (b *Bongo) ById(i Modellable, id int64) error {
	if err := b.DB.
		Table(i.TableName()).
		Where("id = ?", id).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) UnscopedById(i Modellable, id int64) error {
	if err := b.DB.
		Unscoped().
		Table(i.TableName()).
		Where("id = ?", id).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

// Creates a new record with the given struct and its fields
func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

// Update updates all fields of a struct with assigned data
func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return IdIsNotSet
	}

	// Update and Create is using the Save method, so they are
	// same functions but GORM handles, AfterCreate and AfterUpdate
	// in correct manner
	return b.Create(i)
}

// Delete deletes the data by it's id, it doesnt take any other fields
// into consideration
func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return IdIsNotSet
	}

	if err := b.DB.Delete(i).Error; err != nil {
		return err
	}

	return nil
}

// FetchByIds fetches records by their ids and returns results in the same order
// as the ids; if no records in db we don't return error
func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	orderByQuery := ""
	comma := ""
	for _, id := range ids {
		orderByQuery = orderByQuery + comma + " id = " + strconv.FormatInt(id, 10) + " desc"
		comma = ","
	}

	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	query = query.Order(orderByQuery)

	query = query.Where(ids)

	query = query.Find(data)

	// supress not found errors
	return CheckErr(query)

}

// This function doesnt work, after fixing we can open again
// func (b *Bongo) UpdatePartial(i Modellable, set map[string]interface{}) error {
// 	if i.GetId() == 0 {
// 		return IdIsNotSet
// 	}

// 	// init query
// 	query := b.DB

// 	query = query.Model(i)
// 	// query = query.Table(i.TableName())

// 	query = query.Where("id = ? ", i.GetId())
// 	fmt.Println("query-->", query)
// 	fmt.Printf("set %# v", pretty.Formatter(set))
// 	if err := query.Update(set).Error; err != nil {
// 		fmt.Printf("%# v", pretty.Formatter(err))
// 		return err
// 	}

// 	if err := b.ById(i, i.GetId()); err != nil {
// 		fmt.Printf("%# v", pretty.Formatter(err))
// 		return err
// 	}

// 	fmt.Printf("i %# v", pretty.Formatter(i))
// 	// b.AfterUpdate(i)
// 	return nil
// }

// selector, set
func (b *Bongo) UpdateMulti(i Modellable, rest ...map[string]interface{}) error {
	var set, selector map[string]interface{}

	switch len(rest) {
	case 1:
		set = rest[0]
		selector = nil
	case 2:
		selector = rest[0]
		set = rest[1]
	default:
		return WrongParameter
	}

	query := b.DB.Table(i.TableName())

	//add selector
	query = addWhere(query, selector)

	if err := query.Updates(set).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

func (b *Bongo) CountWithQuery(i Modellable, q *Query) (int, error) {
	query := b.BuildQuery(i, q)
	var count int
	return count, query.Count(&count).Error
}

type Scope func(d *gorm.DB) *gorm.DB

type Query struct {
	Selector   map[string]interface{}
	Sort       map[string]string
	Pluck      string
	Pagination Pagination
	Scopes     []Scope
}

func (q *Query) AddScope(scope Scope) {
	if q.Scopes == nil {
		q.Scopes = make([]Scope, 0)
	}

	q.Scopes = append(q.Scopes, scope)
}

type Pagination struct {
	Limit int
	Skip  int
}

func NewPagination(limit int, skip int) *Pagination {
	return &Pagination{
		Limit: limit,
		Skip:  skip,
	}
}

func NewQS(selector map[string]interface{}) *Query {
	return &Query{
		Selector: selector,
	}
}

// selector, sort, limit, pluck,
func (b *Bongo) Some(i Modellable, data interface{}, q *Query) error {
	err := b.executeQuery(i, data, q)
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, q *Query) error {
	q.Pagination.Limit = 1
	return b.executeQuery(i, data, q)
}

func (b *Bongo) BuildQuery(i Modellable, q *Query) *gorm.DB {
	// init query
	query := b.DB.Model(i)

	// add table name
	query = query.Table(i.TableName())

	// add sort options
	query = addSort(query, q.Sort)

	query = addSkip(query, q.Pagination.Skip)

	query = addLimit(query, q.Pagination.Limit)

	// add selector
	query = addWhere(query, q.Selector)

	// put scopes
	if q.Scopes != nil && len(q.Scopes) > 0 {
		for _, scope := range q.Scopes {
			query = query.Scopes(scope)
		}
	}

	return query
}

func (b *Bongo) executeQuery(i Modellable, data interface{}, q *Query) error {
	// init query
	query := b.BuildQuery(i, q)

	var err error
	// TODO refactor this part
	if q.Pluck != "" {
		if strings.Contains(q.Pluck, ",") {
			// add pluck data
			query = addPluck(query, q.Pluck)

			err = query.Find(data).Error
		} else {
			err = query.Pluck(q.Pluck, data).Error
		}
	} else {
		err = query.Find(data).Error
	}

	return err
}

func (b *Bongo) PublishEvent(eventName string, i Modellable) error {
	return b.Emit(i.TableName()+"_"+eventName, i)
}

func (b *Bongo) Emit(eventName string, i interface{}) error {
	data, err := json.Marshal(i)
	if err != nil {
		b.log.Error("Error while marshalling for emitting %s", err)
		return err
	}

	err = b.Broker.Publish(eventName, data)
	if err != nil {
		b.log.Error("Error while emitting %s", err)
		return err
	}

	return nil
}

func (b *Bongo) AfterCreate(i Modellable) error {
	b.PublishEvent("created", i)
	return b.AddToCache(i)
}

func (b *Bongo) AfterUpdate(i Modellable) error {
	b.PublishEvent("updated", i)
	return b.AddToCache(i)
}

func (b *Bongo) AfterDelete(i Modellable) error {
	b.PublishEvent("deleted", i)
	return b.AddToCache(i)
}

func (b *Bongo) AddToCache(i Modellable) error {
	data, ok := i.(Cacher)
	if !ok {
		return nil
	}

	err := b.SetToCache(data)
	if err != ErrCacheIsNotEnabled {
		return err
	}

	return nil
}

// addSort injects sort parameters into query
func addSort(query *gorm.DB, options map[string]string) *gorm.DB {

	if options == nil {
		return query
	}

	if len(options) == 0 {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

// addPluck basically adds select statement for
// only required fields
func addPluck(query *gorm.DB, plucked string) *gorm.DB {
	if plucked == "" {
		return query
	}

	return query.Select(plucked)
}

// addWhere adds where query
func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}

	// instead sending one selector, do chaining here
	return query.Where(selector)
}

// addSkip adds skip parameter into sql query
func addSkip(query *gorm.DB, skip int) *gorm.DB {
	if skip > 0 {
		return query.Offset(skip)
	}

	return query
}

// addLimit adds limit into query if set
func addLimit(query *gorm.DB, limit int) *gorm.DB {
	// if limit is minus or 0 ignore
	if limit > 0 {
		return query.Limit(limit)
	}

	return query
}

// CheckErr checks error exitence and returns if found, but this function
// suppress RecordNotFound errors
func CheckErr(res *gorm.DB) error {
	if res == nil {
		return nil
	}

	if res.Error == nil {
		return nil
	}

	if res.Error == gorm.RecordNotFound {
		return nil
	}

	return res.Error
}
<|endoftext|>


<commit_before>// +build integration

// Space above here matters
// Copyright 2017 Monax Industries Limited
//
// 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 integration

import (
	"encoding/json"
	"fmt"
	"testing"
	"time"

	acm "github.com/hyperledger/burrow/account"
	exe_events "github.com/hyperledger/burrow/execution/events"
	evm_events "github.com/hyperledger/burrow/execution/evm/events"
	"github.com/hyperledger/burrow/rpc"
	tm_client "github.com/hyperledger/burrow/rpc/tm/client"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	tm_types "github.com/tendermint/tendermint/types"
)

//--------------------------------------------------------------------------------
// Test the websocket service

// make a simple connection to the server
func TestWSConnect(t *testing.T) {
	wsc := newWSClient()
	stopWSClient(wsc)
}

// receive a new block message
func TestWSNewBlock(t *testing.T) {
	wsc := newWSClient()
	eid := tm_types.EventNewBlock
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	waitForEvent(t, wsc, eid, func() {},
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			fmt.Println("Check: ", resultEvent.EventDataNewBlock().Block)
			return true, nil
		})
}

// receive a few new block messages in a row, with increasing height
func TestWSBlockchainGrowth(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	eid := tm_types.EventNewBlock
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	// listen for NewBlock, ensure height increases by 1
	var initBlockN int64
	for i := int64(0); i < 2; i++ {
		waitForEvent(t, wsc, eid, func() {},
			func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
				eventDataNewBlock := resultEvent.EventDataNewBlock()
				if eventDataNewBlock == nil {
					t.Fatalf("Was expecting EventDataNewBlock but got %v", resultEvent)
				}
				block := eventDataNewBlock.Block
				if i == 0 {
					initBlockN = block.Height
				} else {
					if block.Header.Height != initBlockN+i {
						return true, fmt.Errorf("Expected block %d, got block %d", i,
							block.Header.Height)
					}
				}
				return true, nil
			})
	}
}

// send a transaction and validate the events from listening for both sender and receiver
func TestWSSend(t *testing.T) {
	wsc := newWSClient()
	toAddr := privateAccounts[1].Address()
	amt := uint64(100)
	eidInput := exe_events.EventStringAccountInput(privateAccounts[0].Address())
	eidOutput := exe_events.EventStringAccountOutput(toAddr)
	subIdInput := subscribeAndGetSubscriptionId(t, wsc, eidInput)
	subIdOutput := subscribeAndGetSubscriptionId(t, wsc, eidOutput)
	defer func() {
		unsubscribe(t, wsc, subIdInput)
		unsubscribe(t, wsc, subIdOutput)
		stopWSClient(wsc)
	}()
	waitForEvent(t, wsc, eidInput, func() {
		tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt)
		broadcastTx(t, jsonRpcClient, tx)
	}, unmarshalValidateSend(amt, toAddr))

	waitForEvent(t, wsc, eidOutput, func() {},
		unmarshalValidateSend(amt, toAddr))
}

// ensure events are only fired once for a given transaction
func TestWSDoubleFire(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	eid := exe_events.EventStringAccountInput(privateAccounts[0].Address())
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	amt := uint64(100)
	toAddr := privateAccounts[1].Address()
	// broadcast the transaction, wait to hear about it
	waitForEvent(t, wsc, eid, func() {
		tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt)
		broadcastTx(t, jsonRpcClient, tx)
	}, func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
		return true, nil
	})
	// but make sure we don't hear about it twice
	err := waitForEvent(t, wsc, eid,
		func() {},
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			return false, nil
		})
	assert.True(t, err.Timeout(), "We should have timed out waiting for second"+
		" %v event", eid)
}

// create a contract, wait for the event, and send it a msg, validate the return
func TestWSCallWait(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	// Mini soak test
	for i := 0; i < 20; i++ {
		amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
		code, returnCode, returnVal := simpleContract()
		var contractAddr acm.Address
		eid1 := exe_events.EventStringAccountInput(privateAccounts[0].Address())
		subId1 := subscribeAndGetSubscriptionId(t, wsc, eid1)
		// wait for the contract to be created
		waitForEvent(t, wsc, eid1, func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
			receipt := broadcastTx(t, jsonRpcClient, tx)
			contractAddr = receipt.ContractAddress
		}, unmarshalValidateTx(amt, returnCode))
		unsubscribe(t, wsc, subId1)

		// susbscribe to the new contract
		amt = uint64(10001)
		eid2 := exe_events.EventStringAccountOutput(contractAddr)
		subId2 := subscribeAndGetSubscriptionId(t, wsc, eid2)
		// get the return value from a call
		data := []byte{0x1}
		waitForEvent(t, wsc, eid2, func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, &contractAddr, data, amt, gasLim, fee)
			receipt := broadcastTx(t, jsonRpcClient, tx)
			contractAddr = receipt.ContractAddress
		}, unmarshalValidateTx(amt, returnVal))
		unsubscribe(t, wsc, subId2)
	}
}

// create a contract and send it a msg without waiting. wait for contract event
// and validate return
func TestWSCallNoWait(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
	code, _, returnVal := simpleContract()

	tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt, err := broadcastTxAndWait(t, jsonRpcClient, wsc, tx)
	require.NoError(t, err)
	contractAddr := receipt.ContractAddress

	// susbscribe to the new contract
	amt = uint64(10001)
	eid := exe_events.EventStringAccountOutput(contractAddr)
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer unsubscribe(t, wsc, subId)
	// get the return value from a call
	data := []byte{0x1}
	waitForEvent(t, wsc, eid, func() {
		tx := makeDefaultCallTx(t, jsonRpcClient, &contractAddr, data, amt, gasLim, fee)
		broadcastTx(t, jsonRpcClient, tx)
	}, unmarshalValidateTx(amt, returnVal))
}

// create two contracts, one of which calls the other
func TestWSCallCall(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
	code, _, returnVal := simpleContract()
	TxHash := new([]byte)

	// deploy the two contracts
	tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt, err := broadcastTxAndWait(t, jsonRpcClient, wsc, tx)
	require.NoError(t, err)
	contractAddr1 := receipt.ContractAddress

	// subscribe to the new contracts
	eid := evm_events.EventStringAccountCall(contractAddr1)
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer unsubscribe(t, wsc, subId)
	// call contract2, which should call contract1, and wait for ev1
	code, _, _ = simpleCallContract(contractAddr1)
	tx = makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt = broadcastTx(t, jsonRpcClient, tx)
	contractAddr2 := receipt.ContractAddress

	// let the contract get created first
	waitForEvent(t, wsc, eid,
		// Runner
		func() {
		},
		// Event Checker
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			return true, nil
		})
	// call it
	waitForEvent(t, wsc, eid,
		// Runner
		func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, &contractAddr2, nil, amt, gasLim, fee)
			broadcastTx(t, jsonRpcClient, tx)
			*TxHash = tx.Hash(genesisDoc.ChainID())
		},
		// Event checker
		unmarshalValidateCall(privateAccounts[0].Address(), returnVal, TxHash))
}

func TestSubscribe(t *testing.T) {
	wsc := newWSClient()
	var subId string
	subscribe(t, wsc, tm_types.EventNewBlock)

Subscribe:
	for {
		select {
		case <-time.After(timeoutSeconds * time.Second):
			t.Fatal("Timed out waiting for subscription result")

		case response := <-wsc.ResponsesCh:
			require.Nil(t, response.Error)
			res := new(rpc.ResultSubscribe)
			require.NoError(t, json.Unmarshal(response.Result, res))
			assert.Equal(t, tm_types.EventNewBlock, res.EventID)
			subId = res.SubscriptionID
			break Subscribe
		}
	}

	blocksSeen := 0
	for {
		select {
		// wait long enough to check we don't see another new block event even though
		// a block will have come
		case <-time.After(expectBlockInSeconds * time.Second):
			if blocksSeen == 0 {
				t.Fatal("Timed out without seeing a NewBlock event")
			}
			return

		case response := <-wsc.ResponsesCh:
			require.Nil(t, response.Error)

			if response.ID == tm_client.EventResponseID(tm_types.EventNewBlock) {
				res := new(rpc.ResultEvent)
				json.Unmarshal(response.Result, res)
				enb := res.EventDataNewBlock()
				if enb != nil {
					assert.Equal(t, genesisDoc.ChainID(), enb.Block.ChainID)
					if blocksSeen > 1 {
						t.Fatal("Continued to see NewBlock event after unsubscribing")
					} else {
						if blocksSeen == 0 {
							unsubscribe(t, wsc, subId)
						}
						blocksSeen++
					}
				}
			}
		}
	}
}
<commit_msg>Fix flaky NoWait test by anticipating sequence number rather waiting for block (which may or may not contain tx)<commit_after>// +build integration

// Space above here matters
// Copyright 2017 Monax Industries Limited
//
// 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 integration

import (
	"encoding/json"
	"fmt"
	"testing"
	"time"

	acm "github.com/hyperledger/burrow/account"
	exe_events "github.com/hyperledger/burrow/execution/events"
	evm_events "github.com/hyperledger/burrow/execution/evm/events"
	"github.com/hyperledger/burrow/rpc"
	tm_client "github.com/hyperledger/burrow/rpc/tm/client"
	"github.com/hyperledger/burrow/txs"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	tm_types "github.com/tendermint/tendermint/types"
)

//--------------------------------------------------------------------------------
// Test the websocket service

// make a simple connection to the server
func TestWSConnect(t *testing.T) {
	wsc := newWSClient()
	stopWSClient(wsc)
}

// receive a new block message
func TestWSNewBlock(t *testing.T) {
	wsc := newWSClient()
	eid := tm_types.EventNewBlock
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	waitForEvent(t, wsc, eid, func() {},
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			fmt.Println("Check: ", resultEvent.EventDataNewBlock().Block)
			return true, nil
		})
}

// receive a few new block messages in a row, with increasing height
func TestWSBlockchainGrowth(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	eid := tm_types.EventNewBlock
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	// listen for NewBlock, ensure height increases by 1
	var initBlockN int64
	for i := int64(0); i < 2; i++ {
		waitForEvent(t, wsc, eid, func() {},
			func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
				eventDataNewBlock := resultEvent.EventDataNewBlock()
				if eventDataNewBlock == nil {
					t.Fatalf("Was expecting EventDataNewBlock but got %v", resultEvent)
				}
				block := eventDataNewBlock.Block
				if i == 0 {
					initBlockN = block.Height
				} else {
					if block.Header.Height != initBlockN+i {
						return true, fmt.Errorf("Expected block %d, got block %d", i,
							block.Header.Height)
					}
				}
				return true, nil
			})
	}
}

// send a transaction and validate the events from listening for both sender and receiver
func TestWSSend(t *testing.T) {
	wsc := newWSClient()
	toAddr := privateAccounts[1].Address()
	amt := uint64(100)
	eidInput := exe_events.EventStringAccountInput(privateAccounts[0].Address())
	eidOutput := exe_events.EventStringAccountOutput(toAddr)
	subIdInput := subscribeAndGetSubscriptionId(t, wsc, eidInput)
	subIdOutput := subscribeAndGetSubscriptionId(t, wsc, eidOutput)
	defer func() {
		unsubscribe(t, wsc, subIdInput)
		unsubscribe(t, wsc, subIdOutput)
		stopWSClient(wsc)
	}()
	waitForEvent(t, wsc, eidInput, func() {
		tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt)
		broadcastTx(t, jsonRpcClient, tx)
	}, unmarshalValidateSend(amt, toAddr))

	waitForEvent(t, wsc, eidOutput, func() {},
		unmarshalValidateSend(amt, toAddr))
}

// ensure events are only fired once for a given transaction
func TestWSDoubleFire(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	eid := exe_events.EventStringAccountInput(privateAccounts[0].Address())
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer func() {
		unsubscribe(t, wsc, subId)
		stopWSClient(wsc)
	}()
	amt := uint64(100)
	toAddr := privateAccounts[1].Address()
	// broadcast the transaction, wait to hear about it
	waitForEvent(t, wsc, eid, func() {
		tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt)
		broadcastTx(t, jsonRpcClient, tx)
	}, func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
		return true, nil
	})
	// but make sure we don't hear about it twice
	err := waitForEvent(t, wsc, eid,
		func() {},
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			return false, nil
		})
	assert.True(t, err.Timeout(), "We should have timed out waiting for second"+
		" %v event", eid)
}

// create a contract, wait for the event, and send it a msg, validate the return
func TestWSCallWait(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	// Mini soak test
	for i := 0; i < 20; i++ {
		amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
		code, returnCode, returnVal := simpleContract()
		var contractAddr acm.Address
		eid1 := exe_events.EventStringAccountInput(privateAccounts[0].Address())
		subId1 := subscribeAndGetSubscriptionId(t, wsc, eid1)
		// wait for the contract to be created
		assert.False(t, waitForEvent(t, wsc, eid1, func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
			receipt := broadcastTx(t, jsonRpcClient, tx)
			contractAddr = receipt.ContractAddress
		}, unmarshalValidateTx(amt, returnCode)).Timeout(), "waitForEvent timed out")

		unsubscribe(t, wsc, subId1)

		// susbscribe to the new contract
		amt = uint64(10001)
		eid2 := exe_events.EventStringAccountOutput(contractAddr)
		subId2 := subscribeAndGetSubscriptionId(t, wsc, eid2)
		// get the return value from a call
		data := []byte{0x1}
		assert.False(t, waitForEvent(t, wsc, eid2, func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, &contractAddr, data, amt, gasLim, fee)
			receipt := broadcastTx(t, jsonRpcClient, tx)
			contractAddr = receipt.ContractAddress
		}, unmarshalValidateTx(amt, returnVal)).Timeout(), "waitForEvent timed out")
		unsubscribe(t, wsc, subId2)
	}
}

// create a contract and send it a msg without waiting. wait for contract event
// and validate return
func TestWSCallNoWait(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
	code, _, returnVal := simpleContract()

	sequence := getSequence(t, jsonRpcClient, privateAccounts[0].Address())
	tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt := broadcastTx(t, jsonRpcClient, tx)
	contractAddr := receipt.ContractAddress

	// susbscribe to the new contract
	amt = uint64(10001)
	eid := exe_events.EventStringAccountOutput(contractAddr)
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer unsubscribe(t, wsc, subId)

	data := []byte{0x1}
	assert.False(t, waitForEvent(t, wsc, eid, func() {
		tx = txs.NewCallTxWithSequence(privateAccounts[0].PublicKey(), &contractAddr, data, amt, gasLim, fee,
			sequence+3)
		require.NoError(t, tx.Sign(genesisDoc.ChainID(), privateAccounts[0]))
		broadcastTx(t, jsonRpcClient, tx)
	}, unmarshalValidateTx(amt, returnVal)).Timeout(), "waitForEvent timed out")
}

// create two contracts, one of which calls the other
func TestWSCallCall(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	wsc := newWSClient()
	defer stopWSClient(wsc)
	amt, gasLim, fee := uint64(10000), uint64(1000), uint64(1000)
	code, _, returnVal := simpleContract()
	TxHash := new([]byte)

	// deploy the two contracts
	tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt, err := broadcastTxAndWait(t, jsonRpcClient, wsc, tx)
	require.NoError(t, err)
	contractAddr1 := receipt.ContractAddress

	// subscribe to the new contracts
	eid := evm_events.EventStringAccountCall(contractAddr1)
	subId := subscribeAndGetSubscriptionId(t, wsc, eid)
	defer unsubscribe(t, wsc, subId)
	// call contract2, which should call contract1, and wait for ev1
	code, _, _ = simpleCallContract(contractAddr1)
	tx = makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee)
	receipt = broadcastTx(t, jsonRpcClient, tx)
	contractAddr2 := receipt.ContractAddress

	// let the contract get created first
	waitForEvent(t, wsc, eid,
		// Runner
		func() {
		},
		// Event Checker
		func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) {
			return true, nil
		})
	// call it
	waitForEvent(t, wsc, eid,
		// Runner
		func() {
			tx := makeDefaultCallTx(t, jsonRpcClient, &contractAddr2, nil, amt, gasLim, fee)
			broadcastTx(t, jsonRpcClient, tx)
			*TxHash = tx.Hash(genesisDoc.ChainID())
		},
		// Event checker
		unmarshalValidateCall(privateAccounts[0].Address(), returnVal, TxHash))
}

func TestSubscribe(t *testing.T) {
	wsc := newWSClient()
	var subId string
	subscribe(t, wsc, tm_types.EventNewBlock)

Subscribe:
	for {
		select {
		case <-time.After(timeoutSeconds * time.Second):
			t.Fatal("Timed out waiting for subscription result")

		case response := <-wsc.ResponsesCh:
			require.Nil(t, response.Error)
			res := new(rpc.ResultSubscribe)
			require.NoError(t, json.Unmarshal(response.Result, res))
			assert.Equal(t, tm_types.EventNewBlock, res.EventID)
			subId = res.SubscriptionID
			break Subscribe
		}
	}

	blocksSeen := 0
	for {
		select {
		// wait long enough to check we don't see another new block event even though
		// a block will have come
		case <-time.After(expectBlockInSeconds * time.Second):
			if blocksSeen == 0 {
				t.Fatal("Timed out without seeing a NewBlock event")
			}
			return

		case response := <-wsc.ResponsesCh:
			require.Nil(t, response.Error)

			if response.ID == tm_client.EventResponseID(tm_types.EventNewBlock) {
				res := new(rpc.ResultEvent)
				json.Unmarshal(response.Result, res)
				enb := res.EventDataNewBlock()
				if enb != nil {
					assert.Equal(t, genesisDoc.ChainID(), enb.Block.ChainID)
					if blocksSeen > 1 {
						t.Fatal("Continued to see NewBlock event after unsubscribing")
					} else {
						if blocksSeen == 0 {
							unsubscribe(t, wsc, subId)
						}
						blocksSeen++
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package identity

import (
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/client"
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/crud"
	"github.com/hashicorp/terraform/helper/schema"
)

func AvailabilityDomainDatasource() *schema.Resource {
	return &schema.Resource{
		Read: readAvailabilityDomains,
		Schema: map[string]*schema.Schema{
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"name": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func readAvailabilityDomains(d *schema.ResourceData, m interface{}) (e error) {
	client := m.(client.BareMetalClient)
	sync := &AvailabilityDomainDatasourceCrud{}
	sync.D = d
	sync.Client = client
	return crud.ReadResource(sync)
}
<commit_msg>Fix availability domain datasource. I was just being dumb, but I still want to figure out why the test was working. Closes #296<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package identity

import (
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/client"
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/crud"
	"github.com/hashicorp/terraform/helper/schema"
)

func AvailabilityDomainDatasource() *schema.Resource {
	return &schema.Resource{
		Read: readAvailabilityDomains,
		Schema: map[string]*schema.Schema{
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"availability_domains": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Resource{
					Schema: map[string]*schema.Schema{
						"compartment_id": {
							Type:     schema.TypeString,
							Computed: true,
						},

						"name": {
							Type:     schema.TypeString,
							Computed: true,
						},
					},
				},
			},
		},
	}
}

func readAvailabilityDomains(d *schema.ResourceData, m interface{}) (e error) {
	client := m.(client.BareMetalClient)
	sync := &AvailabilityDomainDatasourceCrud{}
	sync.D = d
	sync.Client = client
	return crud.ReadResource(sync)
}
<|endoftext|>


<commit_before>package main

func main() {

}
<commit_msg>remove error example<commit_after><|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.170"
<commit_msg>functions: 0.3.171 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.171"
<|endoftext|>


<commit_before>package redis

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/garyburd/redigo/redis"
)

type RedisSession struct {
	pool   *redis.Pool
	prefix string
}

type RedisConf struct {
	Server string
	DB     int
}

func NewRedisSession(conf *RedisConf) (*RedisSession, error) {
	s := &RedisSession{}

	pool := &redis.Pool{
		MaxIdle:     3,
		MaxActive:   1000,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", conf.Server)
			if err != nil {
				return nil, err
			}

			// default is 0 for redis
			if conf.DB != 0 {
				if _, err := c.Do("SELECT", conf.DB); err != nil {
					c.Close()
					return nil, err
				}
			}

			return c, err
		},
	}
	s.pool = pool
	// when we use connection pooling
	// dialing and returning an error will be
	// with the request
	return s, nil
}

// Pool Returns the connection pool for redis
func (r *RedisSession) Pool() *redis.Pool {
	return r.pool
}

// Close closes the connection pool for redis
func (r *RedisSession) Close() error {
	return r.pool.Close()
}

// SetPrefix is used to add a prefix to all keys to be used. It is useful for
// creating namespaces for each different application
func (r *RedisSession) SetPrefix(name string) {
	r.prefix = name + ":"
}

func (r *RedisSession) AddPrefix(name string) string {
	return r.prefix + name
}

// Do is a wrapper around redigo's redis.Do method that executes any redis
// command. Do does not support prefix support. Example usage: redis.Do("INCR",
// "counter").
func (r *RedisSession) Do(cmd string, args ...interface{}) (interface{}, error) {
	conn := r.pool.Get()
	// conn.Close() returns an error but we are already returning regarding error
	// while returning the Do(..) response
	defer conn.Close()
	return conn.Do(cmd, args...)
}

// Send is a wrapper around redigo's redis.Send method that writes the
// command to the client's output buffer.
func (r *RedisSession) Send(cmd string, args ...interface{}) error {
	conn := r.pool.Get()
	// conn.Close() returns an error but we are already returning regarding error
	// while returning the Do(..) response
	defer conn.Close()
	return conn.Send(cmd, args...)
}

// Set is used to hold the string value. If key already holds a value, it is
// overwritten, regardless of its type. A return of nil means successfull.
// Example usage: redis.Set("arslan:name", "fatih")
func (r *RedisSession) Set(key, value string) error {
	reply, err := r.Do("SET", r.AddPrefix(key), value)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)

	}
	return nil
}

// Get is used to get the value of key. If the key does not exist an empty
// string is returned. Usage: redis.Get("arslan")
func (r *RedisSession) Get(key string) (string, error) {
	reply, err := redis.String(r.Do("GET", r.AddPrefix(key)))
	if err != nil {
		return "", err
	}
	return reply, nil
}

// GetInt is used the value of key as an integer. If the key does not exist or
// the stored value is a non-integer, zero is returned. Example usage:
// redis.GetInt("counter")
func (r *RedisSession) GetInt(key string) (int, error) {
	reply, err := redis.Int(r.Do("GET", r.AddPrefix(key)))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// Del is used to remove the specified keys. Key is ignored if it does not
// exist. It returns the number of keys that were removed. Example usage:
// redis.Del("counter", "arslan:name")
func (r *RedisSession) Del(args ...interface{}) (int, error) {
	prefixed := make([]interface{}, 0)
	for _, arg := range args {
		prefixed = append(prefixed, r.AddPrefix(arg.(string)))
	}

	reply, err := redis.Int(r.Do("DEL", prefixed...))
	if err != nil {
		return 0, err
	}
	return reply, nil
}

// Incr increments the number stored at key by one. If the key does not exist,
// it is set to 0 before performing the operation. An error is returned if the
// key contains a value of the wrong type or contains a string that can not be
// represented as integer
func (r *RedisSession) Incr(key string) (int, error) {
	reply, err := redis.Int(r.Do("INCR", r.AddPrefix(key)))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// Expire sets a timeout on a key. After the timeout has expired, the key will
// automatically be deleted. Calling Expire on a key that has already expire
// set will update the expire value.
func (r *RedisSession) Expire(key string, timeout time.Duration) error {
	seconds := strconv.Itoa(int(timeout.Seconds()))
	reply, err := redis.Int(r.Do("EXPIRE", r.AddPrefix(key), seconds))
	if err != nil {
		return err
	}

	if reply != 1 {
		return errors.New("key does not exist or the timeout could not be set")
	}

	return nil
}

// Set key to hold the string value and set key to timeout after a given
// number of seconds. This command is equivalent to executing the following commands:
// SET mykey value
// EXPIRE mykey seconds
// SETEX is atomic, and can be reproduced by using the previous two
// commands inside an MULTI / EXEC block. It is provided as a faster alternative
// to the given sequence of operations, because this operation is very common
// when Redis is used as a cache.
// An error is returned when seconds is invalid.
func (r *RedisSession) Setex(key string, timeout time.Duration, item interface{}) error {
	reply, err := redis.String(
		r.Do(
			"SETEX",
			r.AddPrefix(key),
			strconv.Itoa(int(timeout.Seconds())),
			item,
		),
	)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// PubSubConn wraps a Conn with convenience methods for subscribers.
func (r *RedisSession) CreatePubSubConn() *redis.PubSubConn {
	return &redis.PubSubConn{Conn: r.pool.Get()}
}

// Exists returns true if key exists or false if not.
func (r *RedisSession) Exists(key string) bool {
	// does not have any err message to be checked, it return either 1 or 0
	reply, _ := redis.Int(r.Do("EXISTS", r.AddPrefix(key)))

	if reply == 1 {
		return true
	}

	return false // means reply is 0, key does not exist
}

// Ping pings the redis server to check if it is alive or not
// If the server is not alive will return a proper error
func (r *RedisSession) Ping() error {
	reply, err := redis.String(r.Do("PING"))
	if err != nil {
		return err
	}

	if reply != "PONG" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// Scard gets the member count of a Set with given key
func (r *RedisSession) Scard(key string) (int, error) {
	reply, err := redis.Int(r.Do("SCARD", key))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// SortedSetIncrBy increments the value of a member
// in a sorted set
//
// This function tries to return last floating value of the item,
// if it fails to parse reply to float64, returns parsing error along with
// Reply it self
func (r *RedisSession) SortedSetIncrBy(key string, incrBy, item interface{}) (float64, error) {
	prefixed := make([]interface{}, 0)
	// add key
	prefixed = append(prefixed, r.AddPrefix(key))

	// add incrBy
	prefixed = append(prefixed, incrBy)

	// add item
	prefixed = append(prefixed, item)

	return redis.Float64(r.Do("ZINCRBY", prefixed...))
}

// ZREVRANGE key start stop [WITHSCORES]
// Returns the specified range of elements in the sorted set stored at key.
// The elements are considered to be ordered from the highest
// to the lowest score. Descending lexicographical order is used
// for elements with equal score.
//
// Apart from the reversed ordering, ZREVRANGE is similar to ZRANGE.
func (r *RedisSession) SortedSetReverseRange(key string, rest ...interface{}) ([]interface{}, error) {
	// create a slice with rest length +1
	// because we are gonna prepend key to it
	prefixedReq := make([]interface{}, len(rest)+1)

	// prepend prefixed key
	prefixedReq[0] = r.AddPrefix(key)

	for key, el := range rest {
		prefixedReq[key+1] = el
	}

	return redis.Values(r.Do("ZREVRANGE", prefixedReq...))
}

// HashMultipleSet sets multiple hashset elements stored at key with given field values.
// Returns error state of this operation
func (r *RedisSession) HashMultipleSet(key string, item map[string]interface{}) error {
	reply, err := r.Do("HMSET", redis.Args{}.Add(r.AddPrefix(key)).AddFlat(item)...)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// GetHashMultipleSet returns values of the hashset at stored key with
// requested field order
// Usage: GetHashMultipleSet("canthefason", "name", "age", "birthDate")
func (r *RedisSession) GetHashMultipleSet(key string, rest ...interface{}) ([]interface{}, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)
	return redis.Values(r.Do("HMGET", prefixedReq...))
}

// AddSetMembers adds given elements to the set stored at key. Given elements
// that are already included in set are ignored.
// Returns successfully added key count and error state
func (r *RedisSession) AddSetMembers(key string, rest ...interface{}) (int, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)

	reply, err := redis.Int(r.Do("SADD", prefixedReq...))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// RemoveSetMembers removes given elements from the set stored at key
// Returns successfully removed key count and error state
func (r *RedisSession) RemoveSetMembers(key string, rest ...interface{}) (int, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)

	reply, err := redis.Int(r.Do("SREM", prefixedReq...))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// GetSetMembers returns all members included in the set at key
// Returns members array and error state
func (r *RedisSession) GetSetMembers(key string) ([]interface{}, error) {
	return redis.Values(r.Do("SMEMBERS", r.AddPrefix(key)))
}

// PopSetMember removes and returns a random element from the set stored at key
func (r *RedisSession) PopSetMember(key string) (string, error) {
	return redis.String(r.Do("SPOP", r.AddPrefix(key)))
}

// SortBy sorts elements stored at key with given weight and order(ASC|DESC)
//
// i.e. Suppose we have elements stored at key as object_1, object_2 and object_3
// and their weight is relatively stored at object_1:weight, object_2:weight, object_3:weight
// When we give sortBy parameter as *:weight, it gets all weight values and sorts the objects
// at given key with specified order.
func (r *RedisSession) SortBy(key, sortBy, order string) ([]interface{}, error) {
	return redis.Values(r.Do("SORT", r.AddPrefix(key), "by", r.AddPrefix(sortBy), order))
}

// Keys returns all keys with given pattern
// WARNING: Redis Doc says: "Don't use KEYS in your regular application code."
func (r *RedisSession) Keys(key string) ([]interface{}, error) {
	return redis.Values(r.Do("KEYS", r.AddPrefix(key)))
}

// Bool converts the given value to boolean
func (r *RedisSession) Bool(reply interface{}) (bool, error) {
	return redis.Bool(reply, nil)
}

// Int converts the given value to integer
func (r *RedisSession) Int(reply interface{}) (int, error) {
	return redis.Int(reply, nil)
}

// String converts the given value to string
func (r *RedisSession) String(reply interface{}) (string, error) {
	return redis.String(reply, nil)
}

// Int64 converts the given value to 64 bit integer
func (r *RedisSession) Int64(reply interface{}) (int64, error) {
	return redis.Int64(reply, nil)
}

// Values is a helper that converts an array command reply to a
// []interface{}. If err is not equal to nil, then Values returns nil, err.
// Otherwise, Values converts the reply as follows:
// Reply type      Result
// array           reply, nil
// nil             nil, ErrNil
// other           nil, error
func (r *RedisSession) Values(reply interface{}) ([]interface{}, error) {
	return redis.Values(reply, nil)
}

// prepareArgsWithKey helper method prepends key to given variadic parameter
func (r *RedisSession) prepareArgsWithKey(key string, rest ...interface{}) []interface{} {
	prefixedReq := make([]interface{}, len(rest)+1)

	// prepend prefixed key
	prefixedReq[0] = r.AddPrefix(key)

	for key, el := range rest {
		prefixedReq[key+1] = el
	}

	return prefixedReq
}
<commit_msg>Redis: add ErrNil<commit_after>package redis

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/garyburd/redigo/redis"
)

type RedisSession struct {
	pool   *redis.Pool
	prefix string
}

type RedisConf struct {
	Server string
	DB     int
}

var ErrNil = redis.ErrNil

func NewRedisSession(conf *RedisConf) (*RedisSession, error) {
	s := &RedisSession{}

	pool := &redis.Pool{
		MaxIdle:     3,
		MaxActive:   1000,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", conf.Server)
			if err != nil {
				return nil, err
			}

			// default is 0 for redis
			if conf.DB != 0 {
				if _, err := c.Do("SELECT", conf.DB); err != nil {
					c.Close()
					return nil, err
				}
			}

			return c, err
		},
	}
	s.pool = pool
	// when we use connection pooling
	// dialing and returning an error will be
	// with the request
	return s, nil
}

// Pool Returns the connection pool for redis
func (r *RedisSession) Pool() *redis.Pool {
	return r.pool
}

// Close closes the connection pool for redis
func (r *RedisSession) Close() error {
	return r.pool.Close()
}

// SetPrefix is used to add a prefix to all keys to be used. It is useful for
// creating namespaces for each different application
func (r *RedisSession) SetPrefix(name string) {
	r.prefix = name + ":"
}

func (r *RedisSession) AddPrefix(name string) string {
	return r.prefix + name
}

// Do is a wrapper around redigo's redis.Do method that executes any redis
// command. Do does not support prefix support. Example usage: redis.Do("INCR",
// "counter").
func (r *RedisSession) Do(cmd string, args ...interface{}) (interface{}, error) {
	conn := r.pool.Get()
	// conn.Close() returns an error but we are already returning regarding error
	// while returning the Do(..) response
	defer conn.Close()
	return conn.Do(cmd, args...)
}

// Send is a wrapper around redigo's redis.Send method that writes the
// command to the client's output buffer.
func (r *RedisSession) Send(cmd string, args ...interface{}) error {
	conn := r.pool.Get()
	// conn.Close() returns an error but we are already returning regarding error
	// while returning the Do(..) response
	defer conn.Close()
	return conn.Send(cmd, args...)
}

// Set is used to hold the string value. If key already holds a value, it is
// overwritten, regardless of its type. A return of nil means successfull.
// Example usage: redis.Set("arslan:name", "fatih")
func (r *RedisSession) Set(key, value string) error {
	reply, err := r.Do("SET", r.AddPrefix(key), value)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)

	}
	return nil
}

// Get is used to get the value of key. If the key does not exist an empty
// string is returned. Usage: redis.Get("arslan")
func (r *RedisSession) Get(key string) (string, error) {
	reply, err := redis.String(r.Do("GET", r.AddPrefix(key)))
	if err != nil {
		return "", err
	}
	return reply, nil
}

// GetInt is used the value of key as an integer. If the key does not exist or
// the stored value is a non-integer, zero is returned. Example usage:
// redis.GetInt("counter")
func (r *RedisSession) GetInt(key string) (int, error) {
	reply, err := redis.Int(r.Do("GET", r.AddPrefix(key)))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// Del is used to remove the specified keys. Key is ignored if it does not
// exist. It returns the number of keys that were removed. Example usage:
// redis.Del("counter", "arslan:name")
func (r *RedisSession) Del(args ...interface{}) (int, error) {
	prefixed := make([]interface{}, 0)
	for _, arg := range args {
		prefixed = append(prefixed, r.AddPrefix(arg.(string)))
	}

	reply, err := redis.Int(r.Do("DEL", prefixed...))
	if err != nil {
		return 0, err
	}
	return reply, nil
}

// Incr increments the number stored at key by one. If the key does not exist,
// it is set to 0 before performing the operation. An error is returned if the
// key contains a value of the wrong type or contains a string that can not be
// represented as integer
func (r *RedisSession) Incr(key string) (int, error) {
	reply, err := redis.Int(r.Do("INCR", r.AddPrefix(key)))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// Expire sets a timeout on a key. After the timeout has expired, the key will
// automatically be deleted. Calling Expire on a key that has already expire
// set will update the expire value.
func (r *RedisSession) Expire(key string, timeout time.Duration) error {
	seconds := strconv.Itoa(int(timeout.Seconds()))
	reply, err := redis.Int(r.Do("EXPIRE", r.AddPrefix(key), seconds))
	if err != nil {
		return err
	}

	if reply != 1 {
		return errors.New("key does not exist or the timeout could not be set")
	}

	return nil
}

// Set key to hold the string value and set key to timeout after a given
// number of seconds. This command is equivalent to executing the following commands:
// SET mykey value
// EXPIRE mykey seconds
// SETEX is atomic, and can be reproduced by using the previous two
// commands inside an MULTI / EXEC block. It is provided as a faster alternative
// to the given sequence of operations, because this operation is very common
// when Redis is used as a cache.
// An error is returned when seconds is invalid.
func (r *RedisSession) Setex(key string, timeout time.Duration, item interface{}) error {
	reply, err := redis.String(
		r.Do(
			"SETEX",
			r.AddPrefix(key),
			strconv.Itoa(int(timeout.Seconds())),
			item,
		),
	)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// PubSubConn wraps a Conn with convenience methods for subscribers.
func (r *RedisSession) CreatePubSubConn() *redis.PubSubConn {
	return &redis.PubSubConn{Conn: r.pool.Get()}
}

// Exists returns true if key exists or false if not.
func (r *RedisSession) Exists(key string) bool {
	// does not have any err message to be checked, it return either 1 or 0
	reply, _ := redis.Int(r.Do("EXISTS", r.AddPrefix(key)))

	if reply == 1 {
		return true
	}

	return false // means reply is 0, key does not exist
}

// Ping pings the redis server to check if it is alive or not
// If the server is not alive will return a proper error
func (r *RedisSession) Ping() error {
	reply, err := redis.String(r.Do("PING"))
	if err != nil {
		return err
	}

	if reply != "PONG" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// Scard gets the member count of a Set with given key
func (r *RedisSession) Scard(key string) (int, error) {
	reply, err := redis.Int(r.Do("SCARD", key))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// SortedSetIncrBy increments the value of a member
// in a sorted set
//
// This function tries to return last floating value of the item,
// if it fails to parse reply to float64, returns parsing error along with
// Reply it self
func (r *RedisSession) SortedSetIncrBy(key string, incrBy, item interface{}) (float64, error) {
	prefixed := make([]interface{}, 0)
	// add key
	prefixed = append(prefixed, r.AddPrefix(key))

	// add incrBy
	prefixed = append(prefixed, incrBy)

	// add item
	prefixed = append(prefixed, item)

	return redis.Float64(r.Do("ZINCRBY", prefixed...))
}

// ZREVRANGE key start stop [WITHSCORES]
// Returns the specified range of elements in the sorted set stored at key.
// The elements are considered to be ordered from the highest
// to the lowest score. Descending lexicographical order is used
// for elements with equal score.
//
// Apart from the reversed ordering, ZREVRANGE is similar to ZRANGE.
func (r *RedisSession) SortedSetReverseRange(key string, rest ...interface{}) ([]interface{}, error) {
	// create a slice with rest length +1
	// because we are gonna prepend key to it
	prefixedReq := make([]interface{}, len(rest)+1)

	// prepend prefixed key
	prefixedReq[0] = r.AddPrefix(key)

	for key, el := range rest {
		prefixedReq[key+1] = el
	}

	return redis.Values(r.Do("ZREVRANGE", prefixedReq...))
}

// HashMultipleSet sets multiple hashset elements stored at key with given field values.
// Returns error state of this operation
func (r *RedisSession) HashMultipleSet(key string, item map[string]interface{}) error {
	reply, err := r.Do("HMSET", redis.Args{}.Add(r.AddPrefix(key)).AddFlat(item)...)
	if err != nil {
		return err
	}

	if reply != "OK" {
		return fmt.Errorf("reply string is wrong!: %s", reply)
	}

	return nil
}

// GetHashMultipleSet returns values of the hashset at stored key with
// requested field order
// Usage: GetHashMultipleSet("canthefason", "name", "age", "birthDate")
func (r *RedisSession) GetHashMultipleSet(key string, rest ...interface{}) ([]interface{}, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)
	return redis.Values(r.Do("HMGET", prefixedReq...))
}

// AddSetMembers adds given elements to the set stored at key. Given elements
// that are already included in set are ignored.
// Returns successfully added key count and error state
func (r *RedisSession) AddSetMembers(key string, rest ...interface{}) (int, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)

	reply, err := redis.Int(r.Do("SADD", prefixedReq...))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// RemoveSetMembers removes given elements from the set stored at key
// Returns successfully removed key count and error state
func (r *RedisSession) RemoveSetMembers(key string, rest ...interface{}) (int, error) {
	prefixedReq := r.prepareArgsWithKey(key, rest...)

	reply, err := redis.Int(r.Do("SREM", prefixedReq...))
	if err != nil {
		return 0, err
	}

	return reply, nil
}

// GetSetMembers returns all members included in the set at key
// Returns members array and error state
func (r *RedisSession) GetSetMembers(key string) ([]interface{}, error) {
	return redis.Values(r.Do("SMEMBERS", r.AddPrefix(key)))
}

// PopSetMember removes and returns a random element from the set stored at key
func (r *RedisSession) PopSetMember(key string) (string, error) {
	return redis.String(r.Do("SPOP", r.AddPrefix(key)))
}

// SortBy sorts elements stored at key with given weight and order(ASC|DESC)
//
// i.e. Suppose we have elements stored at key as object_1, object_2 and object_3
// and their weight is relatively stored at object_1:weight, object_2:weight, object_3:weight
// When we give sortBy parameter as *:weight, it gets all weight values and sorts the objects
// at given key with specified order.
func (r *RedisSession) SortBy(key, sortBy, order string) ([]interface{}, error) {
	return redis.Values(r.Do("SORT", r.AddPrefix(key), "by", r.AddPrefix(sortBy), order))
}

// Keys returns all keys with given pattern
// WARNING: Redis Doc says: "Don't use KEYS in your regular application code."
func (r *RedisSession) Keys(key string) ([]interface{}, error) {
	return redis.Values(r.Do("KEYS", r.AddPrefix(key)))
}

// Bool converts the given value to boolean
func (r *RedisSession) Bool(reply interface{}) (bool, error) {
	return redis.Bool(reply, nil)
}

// Int converts the given value to integer
func (r *RedisSession) Int(reply interface{}) (int, error) {
	return redis.Int(reply, nil)
}

// String converts the given value to string
func (r *RedisSession) String(reply interface{}) (string, error) {
	return redis.String(reply, nil)
}

// Int64 converts the given value to 64 bit integer
func (r *RedisSession) Int64(reply interface{}) (int64, error) {
	return redis.Int64(reply, nil)
}

// Values is a helper that converts an array command reply to a
// []interface{}. If err is not equal to nil, then Values returns nil, err.
// Otherwise, Values converts the reply as follows:
// Reply type      Result
// array           reply, nil
// nil             nil, ErrNil
// other           nil, error
func (r *RedisSession) Values(reply interface{}) ([]interface{}, error) {
	return redis.Values(reply, nil)
}

// prepareArgsWithKey helper method prepends key to given variadic parameter
func (r *RedisSession) prepareArgsWithKey(key string, rest ...interface{}) []interface{} {
	prefixedReq := make([]interface{}, len(rest)+1)

	// prepend prefixed key
	prefixedReq[0] = r.AddPrefix(key)

	for key, el := range rest {
		prefixedReq[key+1] = el
	}

	return prefixedReq
}
<|endoftext|>


<commit_before>package adapter

const (
	DiscoveryFilterTransportAuto  = "auto"
	DiscoveryFilterTransportBrEdr = "bredr"
	DiscoveryFilterTransportLE    = "le"
)

type DiscoveryFilter struct {

	// Filter by service UUIDs, empty means match
	// _any_ UUID.
	// When a remote device is found that advertises
	// any UUID from UUIDs, it will be reported if:
	// - Pathloss and RSSI are both empty.
	// - only Pathloss param is set, device advertise
	// TX pwer, and computed pathloss is less than
	// Pathloss param.
	// - only RSSI param is set, and received RSSI is
	// higher than RSSI param.
	UUIDs []string

	// RSSI threshold value.
	// PropertiesChanged signals will be emitted
	// for already existing Device objects, with
	// updated RSSI value. If one or more discovery
	// filters have been set, the RSSI delta-threshold,
	// that is imposed by StartDiscovery by default,
	// will not be applied.
	RSSI int16

	// Pathloss threshold value.
	// PropertiesChanged signals will be emitted
	// for already existing Device objects, with
	// updated Pathloss value.
	Pathloss uint16

	// string Transport (Default "auto")
	// Transport parameter determines the type of
	// scan.
	// Possible values:
	// "auto"	- interleaved scan
	// "bredr"	- BR/EDR inquiry
	// "le"	- LE scan only
	// If "le" or "bredr" Transport is requested,
	// and the controller doesn't support it,
	// org.bluez.Error.Failed error will be returned.
	// If "auto" transport is requested, scan will use
	// LE, BREDR, or both, depending on what's
	// currently enabled on the controller.
	Transport string

	// bool DuplicateData (Default: true)
	// Disables duplicate detection of advertisement
	// data.
	DuplicateData bool
}

func (a *DiscoveryFilter) uuidExists(uuid string) bool {
	for _, uiid1 := range a.UUIDs {
		if uiid1 == uuid {
			return true
		}
	}
	return false
}

func (a *DiscoveryFilter) AddUUIDs(uuids ...string) {
	for _, uuid := range uuids {
		if !a.uuidExists(uuid) {
			a.UUIDs = append(a.UUIDs, uuid)
		}
	}
}

func NewDiscoveryFilter() DiscoveryFilter {
	return DiscoveryFilter{
		// default true
		DuplicateData: true,
	}
}
<commit_msg>added discovery filter<commit_after>package adapter

import "github.com/muka/go-bluetooth/util"

const (
	DiscoveryFilterTransportAuto  = "auto"
	DiscoveryFilterTransportBrEdr = "bredr"
	DiscoveryFilterTransportLE    = "le"
)

type DiscoveryFilter struct {

	// Filter by service UUIDs, empty means match
	// _any_ UUID.
	// When a remote device is found that advertises
	// any UUID from UUIDs, it will be reported if:
	// - Pathloss and RSSI are both empty.
	// - only Pathloss param is set, device advertise
	// TX pwer, and computed pathloss is less than
	// Pathloss param.
	// - only RSSI param is set, and received RSSI is
	// higher than RSSI param.
	UUIDs []string

	// RSSI threshold value.
	// PropertiesChanged signals will be emitted
	// for already existing Device objects, with
	// updated RSSI value. If one or more discovery
	// filters have been set, the RSSI delta-threshold,
	// that is imposed by StartDiscovery by default,
	// will not be applied.
	RSSI int16

	// Pathloss threshold value.
	// PropertiesChanged signals will be emitted
	// for already existing Device objects, with
	// updated Pathloss value.
	Pathloss uint16

	// string Transport (Default "auto")
	// Transport parameter determines the type of
	// scan.
	// Possible values:
	// "auto"	- interleaved scan
	// "bredr"	- BR/EDR inquiry
	// "le"	- LE scan only
	// If "le" or "bredr" Transport is requested,
	// and the controller doesn't support it,
	// org.bluez.Error.Failed error will be returned.
	// If "auto" transport is requested, scan will use
	// LE, BREDR, or both, depending on what's
	// currently enabled on the controller.
	Transport string

	// bool DuplicateData (Default: true)
	// Disables duplicate detection of advertisement
	// data.
	DuplicateData bool
}

func (a *DiscoveryFilter) uuidExists(uuid string) bool {
	for _, uiid1 := range a.UUIDs {
		if uiid1 == uuid {
			return true
		}
	}
	return false
}

func (a *DiscoveryFilter) AddUUIDs(uuids ...string) {
	for _, uuid := range uuids {
		if !a.uuidExists(uuid) {
			a.UUIDs = append(a.UUIDs, uuid)
		}
	}
}

// ToMap convert to a format compatible with adapter SetDiscoveryFilter
func (a *DiscoveryFilter) ToMap() map[string]interface{} {
	m := make(map[string]interface{})
	util.StructToMap(a, m)
	return m
}

func NewDiscoveryFilter() DiscoveryFilter {
	return DiscoveryFilter{
		// default true
		DuplicateData: true,
	}
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.687"
<commit_msg>fnserver: 0.3.688 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.688"
<|endoftext|>


<commit_before>package kloud

import (
	"encoding/json"
	"errors"
	"fmt"
	"koding/db/mongodb"
	"koding/db/mongodb/modelhelper"
	"koding/kites/kloud/contexthelper/session"
	"koding/kites/kloud/terraformer"
	tf "koding/kites/terraformer"

	"labix.org/v2/mgo/bson"

	"golang.org/x/net/context"

	"github.com/koding/kite"
	"github.com/mitchellh/mapstructure"
)

type TerraformPlanRequest struct {
	// Terraform template file
	TerraformContext string `json:"terraformContext"`

	// PublicKeys contains publicKeys to be used with terraform
	PublicKeys []string `json:"publicKeys"`
}

type terraformCredentials struct {
	Creds []*terraformCredential
}

type terraformCredential struct {
	Provider  string
	PublicKey string
	Data      map[string]string `mapstructure:"data"`
}

// region returns the region from the credential data
func (t *terraformCredential) region() (string, error) {
	// for now we support only aws
	if t.Provider != "aws" {
		return "", fmt.Errorf("provider '%s' is not supported", t.Provider)
	}

	region := t.Data["region"]
	if region == "" {
		return "", fmt.Errorf("region for publicKey '%s' is not set", t.PublicKey)
	}

	return region, nil
}

// appendAWSVariable appends the credentials aws data to the given template and
// returns it back.
func (t *terraformCredential) appendAWSVariable(template string) (string, error) {
	var data struct {
		Output   map[string]map[string]interface{} `json:"output,omitempty"`
		Resource map[string]map[string]interface{} `json:"resource,omitempty"`
		Provider struct {
			Aws struct {
				Region    string `json:"region"`
				AccessKey string `json:"access_key"`
				SecretKey string `json:"secret_key"`
			} `json:"aws"`
		} `json:"provider"`
		Variable map[string]map[string]interface{} `json:"variable,omitempty"`
	}

	if err := json.Unmarshal([]byte(template), &data); err != nil {
		return "", err
	}

	credRegion := t.Data["region"]
	if credRegion == "" {
		return "", fmt.Errorf("region for publicKey '%s' is not set", t.PublicKey)
	}

	// if region is not added, add it via credRegion
	region := data.Provider.Aws.Region
	if region == "" {
		data.Provider.Aws.Region = credRegion
	} else if !isVariable(region) && region != credRegion {
		// compare with the provider block's region. Don't allow if they are
		// different.
		return "", fmt.Errorf("region in the provider block doesn't match the region in credential data. Provider block: '%s'. Credential data: '%s'", region, credRegion)
	}

	if data.Variable == nil {
		data.Variable = make(map[string]map[string]interface{})
	}

	data.Variable["access_key"] = map[string]interface{}{
		"default": t.Data["access_key"],
	}

	data.Variable["secret_key"] = map[string]interface{}{
		"default": t.Data["secret_key"],
	}

	data.Variable["region"] = map[string]interface{}{
		"default": credRegion,
	}

	out, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}

	return string(out), nil
}

func (k *Kloud) Plan(r *kite.Request) (interface{}, error) {
	if r.Args == nil {
		return nil, NewError(ErrNoArguments)
	}

	var args *TerraformPlanRequest
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	if args.TerraformContext == "" {
		return nil, NewError(ErrTerraformContextIsMissing)
	}

	if len(args.PublicKeys) == 0 {
		return nil, errors.New("publicKeys are not passed")
	}

	ctx := k.ContextCreator(context.Background())
	sess, ok := session.FromContext(ctx)
	if !ok {
		return nil, errors.New("session context is not passed")
	}

	creds, err := fetchCredentials(r.Username, sess.DB, args.PublicKeys)
	if err != nil {
		return nil, err
	}

	// TODO(arslan): make one single persistent connection if needed, for now
	// this is ok.
	tfKite, err := terraformer.Connect(sess.Kite)
	if err != nil {
		return nil, err
	}
	defer tfKite.Close()

	var region string
	for _, cred := range creds.Creds {
		region, err = cred.region()
		if err != nil {
			return nil, err
		}

		args.TerraformContext, err = cred.appendAWSVariable(args.TerraformContext)
		if err != nil {
			return nil, err
		}
	}

	panic("imlement contnedi1")

	plan, err := tfKite.Plan(&tf.TerraformRequest{
		Content:   args.TerraformContext,
		ContentID: r.Username + "-" + "!234",
		Variables: nil,
	})
	if err != nil {
		return nil, err
	}

	machines, err := machinesFromPlan(plan)
	if err != nil {
		return nil, err
	}
	machines.AppendRegion(region)

	return machines, nil
}

func fetchCredentials(username string, db *mongodb.MongoDB, keys []string) (*terraformCredentials, error) {
	// 1- fetch jaccount from username
	account, err := modelhelper.GetAccount(username)
	if err != nil {
		return nil, err
	}

	// 2- fetch credential from publickey via args
	credentials, err := modelhelper.GetCredentialsFromPublicKeys(keys...)
	if err != nil {
		return nil, err
	}

	// 3- count relationship with credential id and jaccount id as user or
	// owner. Any non valid credentials will be discarded
	validKeys := make(map[string]string, 0)

	for _, cred := range credentials {
		selector := modelhelper.Selector{
			"targetId": cred.Id,
			"sourceId": account.Id,
			"as": bson.M{
				"$in": []string{"owner", "user"},
			},
		}

		count, err := modelhelper.RelationshipCount(selector)
		if err != nil {
			// we return for any not validated public key.
			return nil, fmt.Errorf("credential with publicKey '%s' is not validated", cred.PublicKey)
		}

		// does this ever happen ?
		if count == 0 {
			return nil, fmt.Errorf("credential with publicKey '%s' is not validated", cred.PublicKey)
		}

		validKeys[cred.PublicKey] = cred.Provider
	}

	// 4- fetch credentialdata with publickey
	validPublicKeys := make([]string, 0)
	for pKey := range validKeys {
		validPublicKeys = append(validPublicKeys, pKey)
	}

	credentialData, err := modelhelper.GetCredentialDatasFromPublicKeys(validPublicKeys...)
	if err != nil {
		return nil, err
	}

	// 5- return list of keys. We only support aws for now
	creds := &terraformCredentials{
		Creds: make([]*terraformCredential, 0),
	}

	for _, data := range credentialData {
		provider, ok := validKeys[data.PublicKey]
		if !ok {
			return nil, fmt.Errorf("provider is not found for key: %s", data.PublicKey)
		}
		// for now we only support aws
		if provider != "aws" {
			continue
		}

		cred := &terraformCredential{
			Provider:  provider,
			PublicKey: data.PublicKey,
		}

		if err := mapstructure.Decode(data.Meta, &cred.Data); err != nil {
			return nil, err
		}
		creds.Creds = append(creds.Creds, cred)

	}
	return creds, nil
}
<commit_msg>plan: retrieve from stackTemplate instead of manual<commit_after>package kloud

import (
	"encoding/json"
	"errors"
	"fmt"
	"koding/db/mongodb"
	"koding/db/mongodb/modelhelper"
	"koding/kites/kloud/contexthelper/session"
	"koding/kites/kloud/terraformer"
	tf "koding/kites/terraformer"

	"labix.org/v2/mgo/bson"

	"golang.org/x/net/context"

	"github.com/koding/kite"
	"github.com/mitchellh/mapstructure"
)

type TerraformPlanRequest struct {
	StackTemplateId string `json:"stackTemplateId"`
}

type terraformCredentials struct {
	Creds []*terraformCredential
}

type terraformCredential struct {
	Provider  string
	PublicKey string
	Data      map[string]string `mapstructure:"data"`
}

// region returns the region from the credential data
func (t *terraformCredential) region() (string, error) {
	// for now we support only aws
	if t.Provider != "aws" {
		return "", fmt.Errorf("provider '%s' is not supported", t.Provider)
	}

	region := t.Data["region"]
	if region == "" {
		return "", fmt.Errorf("region for publicKey '%s' is not set", t.PublicKey)
	}

	return region, nil
}

// appendAWSVariable appends the credentials aws data to the given template and
// returns it back.
func (t *terraformCredential) appendAWSVariable(template string) (string, error) {
	var data struct {
		Output   map[string]map[string]interface{} `json:"output,omitempty"`
		Resource map[string]map[string]interface{} `json:"resource,omitempty"`
		Provider struct {
			Aws struct {
				Region    string `json:"region"`
				AccessKey string `json:"access_key"`
				SecretKey string `json:"secret_key"`
			} `json:"aws"`
		} `json:"provider"`
		Variable map[string]map[string]interface{} `json:"variable,omitempty"`
	}

	if err := json.Unmarshal([]byte(template), &data); err != nil {
		return "", err
	}

	credRegion := t.Data["region"]
	if credRegion == "" {
		return "", fmt.Errorf("region for publicKey '%s' is not set", t.PublicKey)
	}

	// if region is not added, add it via credRegion
	region := data.Provider.Aws.Region
	if region == "" {
		data.Provider.Aws.Region = credRegion
	} else if !isVariable(region) && region != credRegion {
		// compare with the provider block's region. Don't allow if they are
		// different.
		return "", fmt.Errorf("region in the provider block doesn't match the region in credential data. Provider block: '%s'. Credential data: '%s'", region, credRegion)
	}

	if data.Variable == nil {
		data.Variable = make(map[string]map[string]interface{})
	}

	data.Variable["access_key"] = map[string]interface{}{
		"default": t.Data["access_key"],
	}

	data.Variable["secret_key"] = map[string]interface{}{
		"default": t.Data["secret_key"],
	}

	data.Variable["region"] = map[string]interface{}{
		"default": credRegion,
	}

	out, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}

	return string(out), nil
}

func (k *Kloud) Plan(r *kite.Request) (interface{}, error) {
	if r.Args == nil {
		return nil, NewError(ErrNoArguments)
	}

	var args *TerraformPlanRequest
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	if args.StackTemplateId == "" {
		return nil, errors.New("stackIdTemplate is not passed")
	}

	ctx := k.ContextCreator(context.Background())
	sess, ok := session.FromContext(ctx)
	if !ok {
		return nil, errors.New("session context is not passed")
	}

	stackTemplate, err := modelhelper.GetStackTemplate(args.StackTemplateId)
	if err != nil {
		return nil, err
	}

	creds, err := fetchCredentials(r.Username, sess.DB, stackTemplate.Credentials)
	if err != nil {
		return nil, err
	}

	// TODO(arslan): make one single persistent connection if needed, for now
	// this is ok.
	tfKite, err := terraformer.Connect(sess.Kite)
	if err != nil {
		return nil, err
	}
	defer tfKite.Close()

	var region string
	for _, cred := range creds.Creds {
		region, err = cred.region()
		if err != nil {
			return nil, err
		}

		stackTemplate.Template.Content, err = cred.appendAWSVariable(stackTemplate.Template.Content)
		if err != nil {
			return nil, err
		}
	}

	plan, err := tfKite.Plan(&tf.TerraformRequest{
		Content:   stackTemplate.Template.Content,
		ContentID: r.Username + "-" + args.StackTemplateId,
		Variables: nil,
	})
	if err != nil {
		return nil, err
	}

	machines, err := machinesFromPlan(plan)
	if err != nil {
		return nil, err
	}
	machines.AppendRegion(region)

	return machines, nil
}

func fetchCredentials(username string, db *mongodb.MongoDB, keys []string) (*terraformCredentials, error) {
	// 1- fetch jaccount from username
	account, err := modelhelper.GetAccount(username)
	if err != nil {
		return nil, err
	}

	// 2- fetch credential from publickey via args
	credentials, err := modelhelper.GetCredentialsFromPublicKeys(keys...)
	if err != nil {
		return nil, err
	}

	// 3- count relationship with credential id and jaccount id as user or
	// owner. Any non valid credentials will be discarded
	validKeys := make(map[string]string, 0)

	for _, cred := range credentials {
		selector := modelhelper.Selector{
			"targetId": cred.Id,
			"sourceId": account.Id,
			"as": bson.M{
				"$in": []string{"owner", "user"},
			},
		}

		count, err := modelhelper.RelationshipCount(selector)
		if err != nil {
			// we return for any not validated public key.
			return nil, fmt.Errorf("credential with publicKey '%s' is not validated", cred.PublicKey)
		}

		// does this ever happen ?
		if count == 0 {
			return nil, fmt.Errorf("credential with publicKey '%s' is not validated", cred.PublicKey)
		}

		validKeys[cred.PublicKey] = cred.Provider
	}

	// 4- fetch credentialdata with publickey
	validPublicKeys := make([]string, 0)
	for pKey := range validKeys {
		validPublicKeys = append(validPublicKeys, pKey)
	}

	credentialData, err := modelhelper.GetCredentialDatasFromPublicKeys(validPublicKeys...)
	if err != nil {
		return nil, err
	}

	// 5- return list of keys. We only support aws for now
	creds := &terraformCredentials{
		Creds: make([]*terraformCredential, 0),
	}

	for _, data := range credentialData {
		provider, ok := validKeys[data.PublicKey]
		if !ok {
			return nil, fmt.Errorf("provider is not found for key: %s", data.PublicKey)
		}
		// for now we only support aws
		if provider != "aws" {
			continue
		}

		cred := &terraformCredential{
			Provider:  provider,
			PublicKey: data.PublicKey,
		}

		if err := mapstructure.Decode(data.Meta, &cred.Data); err != nil {
			return nil, err
		}
		creds.Creds = append(creds.Creds, cred)

	}
	return creds, nil
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.596"
<commit_msg>fnserver: 0.3.597 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.597"
<|endoftext|>