<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"os"
	"runtime"
)

const (
	lclCompileCommandline = `"{{.fpc}}" -T{{.platform}} -P{{.arch}} -MObjFPC -Scghi -CX -Cg -O4 -XX{{if eq .platform "darwin"}} -k-framework -kCocoa{{end}} -l -vewnhibq -Fi{{.objFileDir}}/lib/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/components/printers/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/lazcontrols/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/cairocanvas/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/lcl/units/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/DateTimeCtrls/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/lcl/units/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/components/lazutils/lib/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/packager/units/{{.arch}}-{{.platform}} -Fu{{.objFileDir}}/ -FU{{.objFileDir}}/lib/{{.arch}}-{{.platform}}/ -FE{{.binFileDir}}/ -o{{.binFileDir}}/liblcl.{{.ext}} -dLCL -dLCL{{.lclType}} -dUSED_BY_LAZLOGGER_DUMMY "{{.projectFileName}}"`
)

func buildLCL(arch, binFileDir string) error {

	lazarusDir, fpcExe := GetLazarusDir()
	projectFileName := GetLibProjectFile("/liblcl/lcl.lpr")

	// lcl.lpi 这里面要修改版本号之类的
	// ProductVersion="1.2.8.0"

	if !checkFileExists(lazarusDir) {
		return errors.New("未找到lazarus目录。")
	}
	if !checkFileExists(projectFileName) {
		return errors.New("liblcl工程文件未找到。")
	}
	if arch != "i386" && arch != "x86_64" {
		return errors.New("arch错误，只能为i386或者x86_64")
	}

	lazarusDir = fixDirName(lazarusDir)
	objFileDir := fixDirName(GetObjFileDir("liblcl"))
	binFileDir = fixDirName(binFileDir)

	fmt.Println("lazarusDir:", lazarusDir)
	fmt.Println("projectFileName: ", projectFileName)
	fmt.Println("objFileDir: ", objFileDir)
	fmt.Println("binFileDir: ", binFileDir)

	extName := ""
	lclType := ""
	platform := ""
	switch runtime.GOOS {
	case "linux":
		extName = "so"
		lclType = "gtk2"
		platform = "linux"

	case "darwin":
		extName = "dylib"
		lclType = "cocoa"
		//if arch == "i386" {
		//	lclType = "carbon"
		//}
		platform = "darwin"

	default:
		extName = "dll"
		lclType = "win32"
		if arch == "i386" {
			platform = "win32"
		} else {
			platform = "win64"
		}
	}

	var buf bytes.Buffer
	tmp := template.New("lcl")
	tmp.Parse(lclCompileCommandline)
	tmp.Execute(&buf, map[string]interface{}{
		"fpc":             fpcExe,
		"arch":            arch,     // i386 x86_64
		"platform":        platform, // win32 win64 darwin linux
		"lazarusDir":      lazarusDir,
		"lclType":         lclType, // win32 cocoa carbon gtk2 gtk3
		"ext":             extName, // dll so dylib
		"projectFileName": projectFileName,
		"objFileDir":      objFileDir, // 编译时中间文件目录
		"binFileDir":      binFileDir,
	})

	// liblcl二进制输出目录不存在，则创建
	if !checkFileExists(binFileDir) {
		if err := os.MkdirAll(binFileDir, 0775); err != nil {
			return err
		}
	}

	// 中间文件输出
	libOutDir := objFileDir + "/lib/" + arch + "-" + platform
	if !checkFileExists(libOutDir) {
		if err := os.MkdirAll(libOutDir, 0775); err != nil {
			return err
		}
	}

	fmt.Println(buf.String())
	return execCmd(objFileDir, buf.String())
}
<commit_msg>update lcl<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"os"
	"runtime"
)

const (
	lclCompileCommandline = `"{{.fpc}}" -T{{.platform}} -P{{.arch}} -MObjFPC -Scghi -CX -Cg -O4 -XX{{if eq .platform "darwin"}} -k-framework -kCocoa{{end}} -l -vewnhibq -Fi{{.objFileDir}}/lib/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/components/printers/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/lazcontrols/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/cairocanvas/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/lcl/units/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/components/datetimectrls/lib/{{.arch}}-{{.platform}}/{{.lclType}} -Fu{{.lazarusDir}}/lcl/units/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/components/lazutils/lib/{{.arch}}-{{.platform}} -Fu{{.lazarusDir}}/packager/units/{{.arch}}-{{.platform}} -Fu{{.objFileDir}}/ -FU{{.objFileDir}}/lib/{{.arch}}-{{.platform}}/ -FE{{.binFileDir}}/ -o{{.binFileDir}}/liblcl.{{.ext}} -dLCL -dLCL{{.lclType}} -dUSED_BY_LAZLOGGER_DUMMY "{{.projectFileName}}"`
)

func buildLCL(arch, binFileDir string) error {

	lazarusDir, fpcExe := GetLazarusDir()
	projectFileName := GetLibProjectFile("/liblcl/lcl.lpr")

	// lcl.lpi 这里面要修改版本号之类的
	// ProductVersion="1.2.8.0"

	if !checkFileExists(lazarusDir) {
		return errors.New("未找到lazarus目录。")
	}
	if !checkFileExists(projectFileName) {
		return errors.New("liblcl工程文件未找到。")
	}
	if arch != "i386" && arch != "x86_64" {
		return errors.New("arch错误，只能为i386或者x86_64")
	}

	lazarusDir = fixDirName(lazarusDir)
	objFileDir := fixDirName(GetObjFileDir("liblcl"))
	binFileDir = fixDirName(binFileDir)

	fmt.Println("lazarusDir:", lazarusDir)
	fmt.Println("projectFileName: ", projectFileName)
	fmt.Println("objFileDir: ", objFileDir)
	fmt.Println("binFileDir: ", binFileDir)

	extName := ""
	lclType := ""
	platform := ""
	switch runtime.GOOS {
	case "linux":
		extName = "so"
		lclType = "gtk2"
		platform = "linux"

	case "darwin":
		extName = "dylib"
		lclType = "cocoa"
		//if arch == "i386" {
		//	lclType = "carbon"
		//}
		platform = "darwin"

	default:
		extName = "dll"
		lclType = "win32"
		if arch == "i386" {
			platform = "win32"
		} else {
			platform = "win64"
		}
	}

	var buf bytes.Buffer
	tmp := template.New("lcl")
	tmp.Parse(lclCompileCommandline)
	tmp.Execute(&buf, map[string]interface{}{
		"fpc":             fpcExe,
		"arch":            arch,     // i386 x86_64
		"platform":        platform, // win32 win64 darwin linux
		"lazarusDir":      lazarusDir,
		"lclType":         lclType, // win32 cocoa carbon gtk2 gtk3
		"ext":             extName, // dll so dylib
		"projectFileName": projectFileName,
		"objFileDir":      objFileDir, // 编译时中间文件目录
		"binFileDir":      binFileDir,
	})

	// liblcl二进制输出目录不存在，则创建
	if !checkFileExists(binFileDir) {
		if err := os.MkdirAll(binFileDir, 0775); err != nil {
			return err
		}
	}

	// 中间文件输出
	libOutDir := objFileDir + "/lib/" + arch + "-" + platform
	if !checkFileExists(libOutDir) {
		if err := os.MkdirAll(libOutDir, 0775); err != nil {
			return err
		}
	}

	fmt.Println(buf.String())
	return execCmd(objFileDir, buf.String())
}
<|endoftext|>


<commit_before>package players

import (
//	"errors"
    "encoding/json"
    "os"
    "github.com/ckpt/backend-services/utils"
    mailgun "github.com/mailgun/mailgun-go"
//	"github.com/m4rw3r/uuid"
)

import "fmt"

func StartEventProcessor() error {
	events, err := eventqueue.Consume()
	if err != nil {
		return err
	}
	go func() {
		for msg := range events {

			// Fetch event
			var event utils.CKPTEvent
			_ = json.Unmarshal(msg.Body, &event)

			// Notify subscribers
			allPlayers, err := AllPlayers()
			if err != nil {
				msg.Nack(false, true)
				continue
			}
			for _, p := range allPlayers {
				if p.User.SubscribedTo(utils.TypeNames[event.Type]) {
					NotifyUser(p.Nick, p.Profile.Email, event.Subject, event.Message)
				}
			}
			msg.Ack(false)
		}
	}()

	return nil
}

func NotifyUser(name, email, subject, message string) {
	fmt.Printf("Notifying %s with subject:\n", email)
	fmt.Printf("%s\n", subject)

	mailto := fmt.Sprintf("%s <%s>", name, email)
	gun := mailgun.NewMailgun("mail.ckpt.no", os.Getenv("CKPT_MAILGUN_KEY"), "pubkey-b3e133632123a0da24d1e2c5842039b6")
	m := mailgun.NewMessage("CKPT <notifications@mail.ckpt.no>", subject, message, mailto)
	m.AddHeader("Content-Type", "text/plain; charset=\"utf-8\"")
	response, id, err := gun.Send(m)

	if err != nil {
		fmt.Printf("Error:\n%+v\n", err.Error)
	}
	fmt.Printf("Response ID: %s\n", id)
	fmt.Printf("Message from server: %s\n", response)
}<commit_msg>Fix error output<commit_after>package players

import (
//	"errors"
    "encoding/json"
    "os"
    "github.com/ckpt/backend-services/utils"
    mailgun "github.com/mailgun/mailgun-go"
//	"github.com/m4rw3r/uuid"
)

import "fmt"

func StartEventProcessor() error {
	events, err := eventqueue.Consume()
	if err != nil {
		return err
	}
	go func() {
		for msg := range events {

			// Fetch event
			var event utils.CKPTEvent
			_ = json.Unmarshal(msg.Body, &event)

			// Notify subscribers
			allPlayers, err := AllPlayers()
			if err != nil {
				msg.Nack(false, true)
				continue
			}
			for _, p := range allPlayers {
				if p.User.SubscribedTo(utils.TypeNames[event.Type]) {
					NotifyUser(p.Nick, p.Profile.Email, event.Subject, event.Message)
				}
			}
			msg.Ack(false)
		}
	}()

	return nil
}

func NotifyUser(name, email, subject, message string) {
	fmt.Printf("Notifying %s with subject:\n", email)
	fmt.Printf("%s\n", subject)

	mailto := fmt.Sprintf("%s <%s>", name, email)
	gun := mailgun.NewMailgun("mail.ckpt.no", os.Getenv("CKPT_MAILGUN_KEY"), "pubkey-b3e133632123a0da24d1e2c5842039b6")
	m := mailgun.NewMessage("CKPT <notifications@mail.ckpt.no>", subject, message, mailto)
	m.AddHeader("Content-Type", "text/plain; charset=\"utf-8\"")
	response, id, err := gun.Send(m)

	if err != nil {
		fmt.Printf("Error:\n%+v\n", err.Error())
	}
	fmt.Printf("Response ID: %s\n", id)
	fmt.Printf("Message from server: %s\n", response)
}<|endoftext|>


<commit_before>// Copyright (c) 2014-2015, b3log.org
//
// 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 playground

import (
	"bufio"
	"encoding/json"
	"math/rand"
	"net/http"
	"os/exec"
	"strings"
	"time"

	"github.com/b3log/wide/conf"
	"github.com/b3log/wide/output"
	"github.com/b3log/wide/session"
	"github.com/b3log/wide/util"
)

const (
	outputBufMax  = 128 // 128 string(rune)
	outputTimeout = 100 // 100ms
)

type outputBuf struct {
	content     string
	millisecond int64
}

// RunHandler handles request of executing a binary file.
func RunHandler(w http.ResponseWriter, r *http.Request) {
	data := map[string]interface{}{"succ": true}
	defer util.RetJSON(w, r, data)

	var args map[string]interface{}

	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		data["succ"] = false
	}

	sid := args["sid"].(string)
	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		data["succ"] = false
	}

	filePath := args["executable"].(string)

	cmd := exec.Command(filePath)

	if conf.Docker {
		output.SetNamespace(cmd)
	}

	stdout, err := cmd.StdoutPipe()
	if nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	stderr, err := cmd.StderrPipe()
	if nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	outReader := bufio.NewReader(stdout)
	errReader := bufio.NewReader(stderr)

	if err := cmd.Start(); nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	wsChannel := session.PlaygroundWS[sid]

	channelRet := map[string]interface{}{}

	if !data["succ"].(bool) {
		if nil != wsChannel {
			channelRet["cmd"] = "run-done"
			channelRet["output"] = ""

			err := wsChannel.WriteJSON(&channelRet)
			if nil != err {
				logger.Warn(err)
				return
			}

			wsChannel.Refresh()
		}

		return
	}

	channelRet["pid"] = cmd.Process.Pid

	// add the process to user's process set
	output.Processes.Add(wSession, cmd.Process)

	go func(runningId int) {
		defer util.Recover()
		defer cmd.Wait()

		logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.Username, sid, runningId, filePath)

		// push once for front-end to get the 'run' state and pid
		if nil != wsChannel {
			channelRet["cmd"] = "run"
			channelRet["output"] = ""
			err := wsChannel.WriteJSON(&channelRet)
			if nil != err {
				logger.Warn(err)
				return
			}

			wsChannel.Refresh()
		}

		go func() {
			defer util.Recover()

			buf := outputBuf{}

			for {
				wsChannel := session.PlaygroundWS[sid]
				if nil == wsChannel {
					break
				}

				r, _, err := outReader.ReadRune()

				if nil != err {
					// remove the exited process from user process set
					output.Processes.Remove(wSession, cmd.Process)

					logger.Debugf("User [%s, %s] 's running [id=%d, file=%s] has done [stdout %v], ", wSession.Username, sid, runningId, filePath, err)

					channelRet["cmd"] = "run-done"
					channelRet["output"] = buf.content
					err := wsChannel.WriteJSON(&channelRet)
					if nil != err {
						logger.Warn(err)
						break
					}

					wsChannel.Refresh()

					break
				}

				oneRuneStr := string(r)
				oneRuneStr = strings.Replace(oneRuneStr, "<", "<", -1)
				oneRuneStr = strings.Replace(oneRuneStr, ">", ">", -1)

				buf.content += oneRuneStr

				now := time.Now().UnixNano() / int64(time.Millisecond)

				if 0 == buf.millisecond {
					buf.millisecond = now
				}

				if now-outputTimeout >= buf.millisecond || len(buf.content) > outputBufMax || oneRuneStr == "\n" {
					channelRet["cmd"] = "run"
					channelRet["output"] = buf.content

					buf = outputBuf{} // a new buffer

					err = wsChannel.WriteJSON(&channelRet)
					if nil != err {
						logger.Warn(err)
						break
					}

					wsChannel.Refresh()
				}
			}
		}()

		buf := outputBuf{}
		for {
			r, _, err := errReader.ReadRune()

			wsChannel := session.PlaygroundWS[sid]
			if nil != err || nil == wsChannel {
				break
			}

			oneRuneStr := string(r)
			oneRuneStr = strings.Replace(oneRuneStr, "<", "<", -1)
			oneRuneStr = strings.Replace(oneRuneStr, ">", ">", -1)

			buf.content += oneRuneStr

			now := time.Now().UnixNano() / int64(time.Millisecond)

			if 0 == buf.millisecond {
				buf.millisecond = now
			}

			if now-outputTimeout >= buf.millisecond || len(buf.content) > outputBufMax || oneRuneStr == "\n" {
				channelRet["cmd"] = "run"
				channelRet["output"] = "" + buf.content + ""

				buf = outputBuf{} // a new buffer

				err = wsChannel.WriteJSON(&channelRet)
				if nil != err {
					logger.Warn(err)
					break
				}

				wsChannel.Refresh()
			}
		}
	}(rand.Int())
}

// StopHandler handles request of stoping a running process.
func StopHandler(w http.ResponseWriter, r *http.Request) {
	data := map[string]interface{}{"succ": true}
	defer util.RetJSON(w, r, data)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		data["succ"] = false

		return
	}

	sid := args["sid"].(string)
	pid := int(args["pid"].(float64))

	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		data["succ"] = false

		return
	}

	output.Processes.Kill(wSession, pid)
}
<commit_msg>Playground output escape<commit_after>// Copyright (c) 2014-2015, b3log.org
//
// 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 playground

import (
	"bufio"
	"encoding/json"
	"math/rand"
	"net/http"
	"os/exec"
	"time"

	"github.com/b3log/wide/conf"
	"github.com/b3log/wide/output"
	"github.com/b3log/wide/session"
	"github.com/b3log/wide/util"
)

const (
	outputBufMax  = 128 // 128 string(rune)
	outputTimeout = 100 // 100ms
)

type outputBuf struct {
	content     string
	millisecond int64
}

// RunHandler handles request of executing a binary file.
func RunHandler(w http.ResponseWriter, r *http.Request) {
	data := map[string]interface{}{"succ": true}
	defer util.RetJSON(w, r, data)

	var args map[string]interface{}

	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		data["succ"] = false
	}

	sid := args["sid"].(string)
	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		data["succ"] = false
	}

	filePath := args["executable"].(string)

	cmd := exec.Command(filePath)

	if conf.Docker {
		output.SetNamespace(cmd)
	}

	stdout, err := cmd.StdoutPipe()
	if nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	stderr, err := cmd.StderrPipe()
	if nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	outReader := bufio.NewReader(stdout)
	errReader := bufio.NewReader(stderr)

	if err := cmd.Start(); nil != err {
		logger.Error(err)
		data["succ"] = false
	}

	wsChannel := session.PlaygroundWS[sid]

	channelRet := map[string]interface{}{}

	if !data["succ"].(bool) {
		if nil != wsChannel {
			channelRet["cmd"] = "run-done"
			channelRet["output"] = ""

			err := wsChannel.WriteJSON(&channelRet)
			if nil != err {
				logger.Warn(err)
				return
			}

			wsChannel.Refresh()
		}

		return
	}

	channelRet["pid"] = cmd.Process.Pid

	// add the process to user's process set
	output.Processes.Add(wSession, cmd.Process)

	go func(runningId int) {
		defer util.Recover()
		defer cmd.Wait()

		logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.Username, sid, runningId, filePath)

		// push once for front-end to get the 'run' state and pid
		if nil != wsChannel {
			channelRet["cmd"] = "run"
			channelRet["output"] = ""
			err := wsChannel.WriteJSON(&channelRet)
			if nil != err {
				logger.Warn(err)
				return
			}

			wsChannel.Refresh()
		}

		go func() {
			defer util.Recover()

			buf := outputBuf{}

			for {
				wsChannel := session.PlaygroundWS[sid]
				if nil == wsChannel {
					break
				}

				r, _, err := outReader.ReadRune()

				if nil != err {
					// remove the exited process from user process set
					output.Processes.Remove(wSession, cmd.Process)

					logger.Debugf("User [%s, %s] 's running [id=%d, file=%s] has done [stdout %v], ", wSession.Username, sid, runningId, filePath, err)

					channelRet["cmd"] = "run-done"
					channelRet["output"] = buf.content
					err := wsChannel.WriteJSON(&channelRet)
					if nil != err {
						logger.Warn(err)
						break
					}

					wsChannel.Refresh()

					break
				}

				oneRuneStr := string(r)

				buf.content += oneRuneStr

				now := time.Now().UnixNano() / int64(time.Millisecond)

				if 0 == buf.millisecond {
					buf.millisecond = now
				}

				if now-outputTimeout >= buf.millisecond || len(buf.content) > outputBufMax || oneRuneStr == "\n" {
					channelRet["cmd"] = "run"
					channelRet["output"] = buf.content

					buf = outputBuf{} // a new buffer

					err = wsChannel.WriteJSON(&channelRet)
					if nil != err {
						logger.Warn(err)
						break
					}

					wsChannel.Refresh()
				}
			}
		}()

		buf := outputBuf{}
		for {
			r, _, err := errReader.ReadRune()

			wsChannel := session.PlaygroundWS[sid]
			if nil != err || nil == wsChannel {
				break
			}

			oneRuneStr := string(r)

			buf.content += oneRuneStr

			now := time.Now().UnixNano() / int64(time.Millisecond)

			if 0 == buf.millisecond {
				buf.millisecond = now
			}

			if now-outputTimeout >= buf.millisecond || len(buf.content) > outputBufMax || oneRuneStr == "\n" {
				channelRet["cmd"] = "run"
				channelRet["output"] = buf.content

				buf = outputBuf{} // a new buffer

				err = wsChannel.WriteJSON(&channelRet)
				if nil != err {
					logger.Warn(err)
					break
				}

				wsChannel.Refresh()
			}
		}
	}(rand.Int())
}

// StopHandler handles request of stoping a running process.
func StopHandler(w http.ResponseWriter, r *http.Request) {
	data := map[string]interface{}{"succ": true}
	defer util.RetJSON(w, r, data)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		data["succ"] = false

		return
	}

	sid := args["sid"].(string)
	pid := int(args["pid"].(float64))

	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		data["succ"] = false

		return
	}

	output.Processes.Kill(wSession, pid)
}
<|endoftext|>


<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 = 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(4)
	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) {
	p, err := New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Title"
	p.Y.Label.Text = "Y Label"
	rand.Seed(seed)
	vs0 := make(Values, 10)
	for i := range vs0 {
		vs0[i] = rand.Float64()*1000
	}
	b0 := NewBox(vg.Points(20), 0, vs0)
	_, med0, _, _ := b0.Statistics()

	vs1 := make(Values, 10)
	for i := range vs1 {
		vs1[i] = rand.NormFloat64()*200 + 500
	}
	b1 := NewBox(vg.Points(20), 1, vs1)
	_, med1, _, _ := b1.Statistics()

	vs2 := make(Values, 10)
	for i := range vs2 {
		vs2[i] = rand.ExpFloat64()*300
	}
	b2 := NewBox(vg.Points(20), 2, vs2)
	_, med2, _, _ := b2.Statistics()

	meds :=  Points{ { b0.X, med0 }, { b1.X, med1 }, { b2.X, med2 } }

	l := Line{ meds, DefaultLineStyle }
	s := Scatter{ meds, GlyphStyle{Shape: CircleGlyph, Radius: vg.Points(2)} }

	p.AddData(b0, b1, b2, l, s)
	p.Legend.AddEntry("outliers", b0.GlyphStyle)
	p.Legend.AddEntry("median", l, s)

	p.NominalX("Uniform\nDistribution", "Normal\nDistribution",
		"Exponential\nDistribution")

	p.Y.Min = 0
	p.Y.Max = 1000
	p.Legend.Top = true
	p.Draw(da)
}
<commit_msg>Shift around a bit of code in the example.<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 = 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(4)
	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)
	vs0 := make(Values, 10)
	for i := range vs0 {
		vs0[i] = rand.Float64()*1000
	}
	b0 := NewBox(vg.Points(20), 0, vs0)
	_, med0, _, _ := b0.Statistics()

	vs1 := make(Values, 10)
	for i := range vs1 {
		vs1[i] = rand.NormFloat64()*200 + 500
	}
	b1 := NewBox(vg.Points(20), 1, vs1)
	_, med1, _, _ := b1.Statistics()

	vs2 := make(Values, 10)
	for i := range vs2 {
		vs2[i] = rand.ExpFloat64()*300
	}
	b2 := NewBox(vg.Points(20), 2, vs2)
	_, med2, _, _ := b2.Statistics()

	meds :=  Points{ { b0.X, med0 }, { b1.X, med1 }, { b2.X, med2 } }

	l := Line{ meds, DefaultLineStyle }
	s := Scatter{ meds, GlyphStyle{Shape: CircleGlyph, Radius: vg.Points(2)} }

	p, err := New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Title"
	p.Y.Label.Text = "Y Label"
	p.AddData(b0, b1, b2, l, s)
	p.Legend.AddEntry("outliers", b0.GlyphStyle)
	p.Legend.AddEntry("median", l, s)
	p.NominalX("Uniform\nDistribution", "Normal\nDistribution",
		"Exponential\nDistribution")
	p.Y.Min = 0
	p.Y.Max = 1000
	p.Legend.Top = true
	p.Draw(da)
}
<|endoftext|>


<commit_before>package jobs

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/cozy/cozy-stack/pkg/accounts"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/couchdb"
	"github.com/cozy/cozy-stack/pkg/jobs"
	"github.com/cozy/cozy-stack/pkg/logger"
	"github.com/cozy/cozy-stack/pkg/scheduler"
	"github.com/cozy/cozy-stack/pkg/stack"
	"github.com/cozy/cozy-stack/web/jsonapi"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/cozy/cozy-stack/web/permissions"
	multierror "github.com/hashicorp/go-multierror"
	"github.com/labstack/echo"

	// exec is needed for bad triggers cleanup
	exec "github.com/cozy/cozy-stack/pkg/workers/exec"

	// import workers
	_ "github.com/cozy/cozy-stack/pkg/workers/log"
	_ "github.com/cozy/cozy-stack/pkg/workers/mails"
	_ "github.com/cozy/cozy-stack/pkg/workers/sharings"
	_ "github.com/cozy/cozy-stack/pkg/workers/thumbnail"
	_ "github.com/cozy/cozy-stack/pkg/workers/unzip"
)

type (
	apiJob struct {
		j *jobs.JobInfos
	}
	apiJobRequest struct {
		Arguments json.RawMessage  `json:"arguments"`
		Options   *jobs.JobOptions `json:"options"`
	}
	apiQueue struct {
		Count      int `json:"count"`
		workerType string
	}
	apiTrigger struct {
		t scheduler.Trigger
	}
	apiTriggerRequest struct {
		Type            string           `json:"type"`
		Arguments       string           `json:"arguments"`
		WorkerType      string           `json:"worker"`
		WorkerArguments json.RawMessage  `json:"worker_arguments"`
		Options         *jobs.JobOptions `json:"options"`
	}
)

func (j *apiJob) ID() string                             { return j.j.ID() }
func (j *apiJob) Rev() string                            { return j.j.Rev() }
func (j *apiJob) DocType() string                        { return consts.Jobs }
func (j *apiJob) Clone() couchdb.Doc                     { return j }
func (j *apiJob) SetID(_ string)                         {}
func (j *apiJob) SetRev(_ string)                        {}
func (j *apiJob) Relationships() jsonapi.RelationshipMap { return nil }
func (j *apiJob) Included() []jsonapi.Object             { return nil }
func (j *apiJob) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/" + j.j.WorkerType + "/" + j.j.ID()}
}
func (j *apiJob) MarshalJSON() ([]byte, error) {
	return json.Marshal(j.j)
}

func (q *apiQueue) ID() string                             { return q.workerType }
func (q *apiQueue) Rev() string                            { return "" }
func (q *apiQueue) DocType() string                        { return consts.Queues }
func (q *apiQueue) Clone() couchdb.Doc                     { return q }
func (q *apiQueue) SetID(_ string)                         {}
func (q *apiQueue) SetRev(_ string)                        {}
func (q *apiQueue) Relationships() jsonapi.RelationshipMap { return nil }
func (q *apiQueue) Included() []jsonapi.Object             { return nil }
func (q *apiQueue) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/queue/" + q.workerType}
}
func (q *apiQueue) Valid(key, value string) bool {
	switch key {
	case "worker":
		return q.workerType == value
	}
	return false
}

func (t *apiTrigger) ID() string                             { return t.t.Infos().TID }
func (t *apiTrigger) Rev() string                            { return "" }
func (t *apiTrigger) DocType() string                        { return consts.Triggers }
func (t *apiTrigger) Clone() couchdb.Doc                     { return t }
func (t *apiTrigger) SetID(_ string)                         {}
func (t *apiTrigger) SetRev(_ string)                        {}
func (t *apiTrigger) Relationships() jsonapi.RelationshipMap { return nil }
func (t *apiTrigger) Included() []jsonapi.Object             { return nil }
func (t *apiTrigger) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/triggers/" + t.ID()}
}
func (t *apiTrigger) MarshalJSON() ([]byte, error) {
	return json.Marshal(t.t.Infos())
}

func getQueue(c echo.Context) error {
	workerType := c.Param("worker-type")
	count, err := stack.GetBroker().QueueLen(workerType)
	if err != nil {
		return wrapJobsError(err)
	}
	o := &apiQueue{
		workerType: workerType,
		Count:      count,
	}

	if err := permissions.Allow(c, permissions.GET, o); err != nil {
		return err
	}

	return jsonapi.Data(c, http.StatusOK, o, nil)
}

func pushJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)

	req := &apiJobRequest{}
	if _, err := jsonapi.Bind(c.Request(), &req); err != nil {
		return wrapJobsError(err)
	}

	jr := &jobs.JobRequest{
		Domain:     instance.Domain,
		WorkerType: c.Param("worker-type"),
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.Arguments,
		},
	}
	if err := permissions.Allow(c, permissions.POST, jr); err != nil {
		return err
	}

	job, err := stack.GetBroker().PushJob(jr)
	if err != nil {
		return wrapJobsError(err)
	}

	return jsonapi.Data(c, http.StatusAccepted, &apiJob{job}, nil)
}

func newTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	req := &apiTriggerRequest{}
	if _, err := jsonapi.Bind(c.Request(), &req); err != nil {
		return wrapJobsError(err)
	}

	t, err := scheduler.NewTrigger(&scheduler.TriggerInfos{
		Type:       req.Type,
		WorkerType: req.WorkerType,
		Domain:     instance.Domain,
		Arguments:  req.Arguments,
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.WorkerArguments,
		},
	})
	if err != nil {
		return wrapJobsError(err)
	}

	if err = permissions.Allow(c, permissions.POST, t); err != nil {
		return err
	}

	if err = sched.Add(t); err != nil {
		return wrapJobsError(err)
	}
	return jsonapi.Data(c, http.StatusCreated, &apiTrigger{t}, nil)
}

func getTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	t, err := sched.Get(instance.Domain, c.Param("trigger-id"))
	if err != nil {
		return wrapJobsError(err)
	}
	if err := permissions.Allow(c, permissions.GET, t); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiTrigger{t}, nil)
}

func deleteTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	t, err := sched.Get(instance.Domain, c.Param("trigger-id"))
	if err != nil {
		return wrapJobsError(err)
	}
	if err := permissions.Allow(c, permissions.DELETE, t); err != nil {
		return err
	}
	if err := sched.Delete(instance.Domain, c.Param("trigger-id")); err != nil {
		return wrapJobsError(err)
	}
	return c.NoContent(http.StatusNoContent)
}

func cleanTriggers(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Triggers); err != nil {
		return err
	}
	if rsched, ok := sched.(*scheduler.RedisScheduler); ok {
		if err := rsched.ImportFromDB(instance.Domain); err != nil {
			return wrapJobsError(err)
		}
	}
	ts, err := sched.GetAll(instance.Domain)
	if err != nil {
		return wrapJobsError(err)
	}
	deleted := 0
	for _, t := range ts {
		infos := t.Infos()
		if infos.WorkerType == "konnector" {
			var msg exec.KonnectorOptions
			if err = infos.Message.Unmarshal(&msg); err != nil {
				if err = sched.Delete(instance.Domain, t.ID()); err != nil {
					logger.WithDomain(instance.Domain).Errorln("failed to delete orphan trigger", err)
				}
				deleted++
				continue
			}

			var a accounts.Account
			err = couchdb.GetDoc(instance, consts.Accounts, msg.Account, &a)
			if couchdb.IsNotFoundError(err) {
				if err = sched.Delete(instance.Domain, t.ID()); err != nil {
					logger.WithDomain(instance.Domain).Errorln("failed to delete orphan trigger", err)
				}
				deleted++
			}
		}
	}

	return c.JSON(200, map[string]int{"deleted": deleted})
}

func getAllTriggers(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	workerFilter := c.QueryParam("Worker")
	sched := stack.GetScheduler()
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Triggers); err != nil {
		return err
	}
	ts, err := sched.GetAll(instance.Domain)
	if err != nil {
		return wrapJobsError(err)
	}
	objs := make([]jsonapi.Object, 0, len(ts))
	for _, t := range ts {
		if workerFilter == "" || t.Infos().WorkerType == workerFilter {
			objs = append(objs, &apiTrigger{t})
		}
	}
	return jsonapi.DataList(c, http.StatusOK, objs, nil)
}

func getJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	job, err := stack.GetBroker().GetJobInfos(instance.Domain, c.Param("job-id"))
	if err != nil {
		return err
	}
	if err := permissions.Allow(c, permissions.GET, job); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiJob{job}, nil)
}

func cleanJobs(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Jobs); err != nil {
		return err
	}
	var ups []*jobs.JobInfos
	now := time.Now()
	err := couchdb.ForeachDocs(instance, consts.Jobs, func(data []byte) error {
		var job *jobs.JobInfos
		if err := json.Unmarshal(data, &job); err != nil {
			return err
		}
		if job.State != jobs.Running {
			return nil
		}
		if job.StartedAt.Add(1 * time.Hour).Before(now) {
			ups = append(ups, job)
		}
		return nil
	})
	if err != nil && !couchdb.IsNoDatabaseError(err) {
		return err
	}
	var errf error
	for _, j := range ups {
		j.State = jobs.Done
		err := couchdb.UpdateDoc(instance, j)
		if err != nil {
			errf = multierror.Append(errf, err)
		}
	}
	if errf != nil {
		return errf
	}
	return c.JSON(200, map[string]int{"deleted": len(ups)})
}

// Routes sets the routing for the jobs service
func Routes(router *echo.Group) {
	router.GET("/queue/:worker-type", getQueue)
	router.POST("/queue/:worker-type", pushJob)

	router.GET("/triggers", getAllTriggers)
	router.POST("/triggers", newTrigger)
	router.POST("/triggers/clean", cleanTriggers)
	router.GET("/triggers/:trigger-id", getTrigger)
	router.DELETE("/triggers/:trigger-id", deleteTrigger)

	router.POST("/clean", cleanJobs)
	router.GET("/:job-id", getJob)
}

func wrapJobsError(err error) error {
	switch err {
	case scheduler.ErrNotFoundTrigger,
		jobs.ErrNotFoundJob,
		jobs.ErrUnknownWorker:
		return jsonapi.NotFound(err)
	case scheduler.ErrUnknownTrigger:
		return jsonapi.InvalidAttribute("Type", err)
	}
	return err
}
<commit_msg>Import exec workers<commit_after>package jobs

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/cozy/cozy-stack/pkg/accounts"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/couchdb"
	"github.com/cozy/cozy-stack/pkg/jobs"
	"github.com/cozy/cozy-stack/pkg/logger"
	"github.com/cozy/cozy-stack/pkg/scheduler"
	"github.com/cozy/cozy-stack/pkg/stack"
	"github.com/cozy/cozy-stack/web/jsonapi"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/cozy/cozy-stack/web/permissions"
	multierror "github.com/hashicorp/go-multierror"
	"github.com/labstack/echo"

	// exec is needed for bad triggers cleanup
	exec "github.com/cozy/cozy-stack/pkg/workers/exec"

	// import workers
	_ "github.com/cozy/cozy-stack/pkg/workers/exec"
	_ "github.com/cozy/cozy-stack/pkg/workers/log"
	_ "github.com/cozy/cozy-stack/pkg/workers/mails"
	_ "github.com/cozy/cozy-stack/pkg/workers/sharings"
	_ "github.com/cozy/cozy-stack/pkg/workers/thumbnail"
	_ "github.com/cozy/cozy-stack/pkg/workers/unzip"
)

type (
	apiJob struct {
		j *jobs.JobInfos
	}
	apiJobRequest struct {
		Arguments json.RawMessage  `json:"arguments"`
		Options   *jobs.JobOptions `json:"options"`
	}
	apiQueue struct {
		Count      int `json:"count"`
		workerType string
	}
	apiTrigger struct {
		t scheduler.Trigger
	}
	apiTriggerRequest struct {
		Type            string           `json:"type"`
		Arguments       string           `json:"arguments"`
		WorkerType      string           `json:"worker"`
		WorkerArguments json.RawMessage  `json:"worker_arguments"`
		Options         *jobs.JobOptions `json:"options"`
	}
)

func (j *apiJob) ID() string                             { return j.j.ID() }
func (j *apiJob) Rev() string                            { return j.j.Rev() }
func (j *apiJob) DocType() string                        { return consts.Jobs }
func (j *apiJob) Clone() couchdb.Doc                     { return j }
func (j *apiJob) SetID(_ string)                         {}
func (j *apiJob) SetRev(_ string)                        {}
func (j *apiJob) Relationships() jsonapi.RelationshipMap { return nil }
func (j *apiJob) Included() []jsonapi.Object             { return nil }
func (j *apiJob) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/" + j.j.WorkerType + "/" + j.j.ID()}
}
func (j *apiJob) MarshalJSON() ([]byte, error) {
	return json.Marshal(j.j)
}

func (q *apiQueue) ID() string                             { return q.workerType }
func (q *apiQueue) Rev() string                            { return "" }
func (q *apiQueue) DocType() string                        { return consts.Queues }
func (q *apiQueue) Clone() couchdb.Doc                     { return q }
func (q *apiQueue) SetID(_ string)                         {}
func (q *apiQueue) SetRev(_ string)                        {}
func (q *apiQueue) Relationships() jsonapi.RelationshipMap { return nil }
func (q *apiQueue) Included() []jsonapi.Object             { return nil }
func (q *apiQueue) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/queue/" + q.workerType}
}
func (q *apiQueue) Valid(key, value string) bool {
	switch key {
	case "worker":
		return q.workerType == value
	}
	return false
}

func (t *apiTrigger) ID() string                             { return t.t.Infos().TID }
func (t *apiTrigger) Rev() string                            { return "" }
func (t *apiTrigger) DocType() string                        { return consts.Triggers }
func (t *apiTrigger) Clone() couchdb.Doc                     { return t }
func (t *apiTrigger) SetID(_ string)                         {}
func (t *apiTrigger) SetRev(_ string)                        {}
func (t *apiTrigger) Relationships() jsonapi.RelationshipMap { return nil }
func (t *apiTrigger) Included() []jsonapi.Object             { return nil }
func (t *apiTrigger) Links() *jsonapi.LinksList {
	return &jsonapi.LinksList{Self: "/jobs/triggers/" + t.ID()}
}
func (t *apiTrigger) MarshalJSON() ([]byte, error) {
	return json.Marshal(t.t.Infos())
}

func getQueue(c echo.Context) error {
	workerType := c.Param("worker-type")
	count, err := stack.GetBroker().QueueLen(workerType)
	if err != nil {
		return wrapJobsError(err)
	}
	o := &apiQueue{
		workerType: workerType,
		Count:      count,
	}

	if err := permissions.Allow(c, permissions.GET, o); err != nil {
		return err
	}

	return jsonapi.Data(c, http.StatusOK, o, nil)
}

func pushJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)

	req := &apiJobRequest{}
	if _, err := jsonapi.Bind(c.Request(), &req); err != nil {
		return wrapJobsError(err)
	}

	jr := &jobs.JobRequest{
		Domain:     instance.Domain,
		WorkerType: c.Param("worker-type"),
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.Arguments,
		},
	}
	if err := permissions.Allow(c, permissions.POST, jr); err != nil {
		return err
	}

	job, err := stack.GetBroker().PushJob(jr)
	if err != nil {
		return wrapJobsError(err)
	}

	return jsonapi.Data(c, http.StatusAccepted, &apiJob{job}, nil)
}

func newTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	req := &apiTriggerRequest{}
	if _, err := jsonapi.Bind(c.Request(), &req); err != nil {
		return wrapJobsError(err)
	}

	t, err := scheduler.NewTrigger(&scheduler.TriggerInfos{
		Type:       req.Type,
		WorkerType: req.WorkerType,
		Domain:     instance.Domain,
		Arguments:  req.Arguments,
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.WorkerArguments,
		},
	})
	if err != nil {
		return wrapJobsError(err)
	}

	if err = permissions.Allow(c, permissions.POST, t); err != nil {
		return err
	}

	if err = sched.Add(t); err != nil {
		return wrapJobsError(err)
	}
	return jsonapi.Data(c, http.StatusCreated, &apiTrigger{t}, nil)
}

func getTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	t, err := sched.Get(instance.Domain, c.Param("trigger-id"))
	if err != nil {
		return wrapJobsError(err)
	}
	if err := permissions.Allow(c, permissions.GET, t); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiTrigger{t}, nil)
}

func deleteTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	t, err := sched.Get(instance.Domain, c.Param("trigger-id"))
	if err != nil {
		return wrapJobsError(err)
	}
	if err := permissions.Allow(c, permissions.DELETE, t); err != nil {
		return err
	}
	if err := sched.Delete(instance.Domain, c.Param("trigger-id")); err != nil {
		return wrapJobsError(err)
	}
	return c.NoContent(http.StatusNoContent)
}

func cleanTriggers(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	sched := stack.GetScheduler()
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Triggers); err != nil {
		return err
	}
	if rsched, ok := sched.(*scheduler.RedisScheduler); ok {
		if err := rsched.ImportFromDB(instance.Domain); err != nil {
			return wrapJobsError(err)
		}
	}
	ts, err := sched.GetAll(instance.Domain)
	if err != nil {
		return wrapJobsError(err)
	}
	deleted := 0
	for _, t := range ts {
		infos := t.Infos()
		if infos.WorkerType == "konnector" {
			var msg exec.KonnectorOptions
			if err = infos.Message.Unmarshal(&msg); err != nil {
				if err = sched.Delete(instance.Domain, t.ID()); err != nil {
					logger.WithDomain(instance.Domain).Errorln("failed to delete orphan trigger", err)
				}
				deleted++
				continue
			}

			var a accounts.Account
			err = couchdb.GetDoc(instance, consts.Accounts, msg.Account, &a)
			if couchdb.IsNotFoundError(err) {
				if err = sched.Delete(instance.Domain, t.ID()); err != nil {
					logger.WithDomain(instance.Domain).Errorln("failed to delete orphan trigger", err)
				}
				deleted++
			}
		}
	}

	return c.JSON(200, map[string]int{"deleted": deleted})
}

func getAllTriggers(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	workerFilter := c.QueryParam("Worker")
	sched := stack.GetScheduler()
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Triggers); err != nil {
		return err
	}
	ts, err := sched.GetAll(instance.Domain)
	if err != nil {
		return wrapJobsError(err)
	}
	objs := make([]jsonapi.Object, 0, len(ts))
	for _, t := range ts {
		if workerFilter == "" || t.Infos().WorkerType == workerFilter {
			objs = append(objs, &apiTrigger{t})
		}
	}
	return jsonapi.DataList(c, http.StatusOK, objs, nil)
}

func getJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	job, err := stack.GetBroker().GetJobInfos(instance.Domain, c.Param("job-id"))
	if err != nil {
		return err
	}
	if err := permissions.Allow(c, permissions.GET, job); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiJob{job}, nil)
}

func cleanJobs(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	if err := permissions.AllowWholeType(c, permissions.GET, consts.Jobs); err != nil {
		return err
	}
	var ups []*jobs.JobInfos
	now := time.Now()
	err := couchdb.ForeachDocs(instance, consts.Jobs, func(data []byte) error {
		var job *jobs.JobInfos
		if err := json.Unmarshal(data, &job); err != nil {
			return err
		}
		if job.State != jobs.Running {
			return nil
		}
		if job.StartedAt.Add(1 * time.Hour).Before(now) {
			ups = append(ups, job)
		}
		return nil
	})
	if err != nil && !couchdb.IsNoDatabaseError(err) {
		return err
	}
	var errf error
	for _, j := range ups {
		j.State = jobs.Done
		err := couchdb.UpdateDoc(instance, j)
		if err != nil {
			errf = multierror.Append(errf, err)
		}
	}
	if errf != nil {
		return errf
	}
	return c.JSON(200, map[string]int{"deleted": len(ups)})
}

// Routes sets the routing for the jobs service
func Routes(router *echo.Group) {
	router.GET("/queue/:worker-type", getQueue)
	router.POST("/queue/:worker-type", pushJob)

	router.GET("/triggers", getAllTriggers)
	router.POST("/triggers", newTrigger)
	router.POST("/triggers/clean", cleanTriggers)
	router.GET("/triggers/:trigger-id", getTrigger)
	router.DELETE("/triggers/:trigger-id", deleteTrigger)

	router.POST("/clean", cleanJobs)
	router.GET("/:job-id", getJob)
}

func wrapJobsError(err error) error {
	switch err {
	case scheduler.ErrNotFoundTrigger,
		jobs.ErrNotFoundJob,
		jobs.ErrUnknownWorker:
		return jsonapi.NotFound(err)
	case scheduler.ErrUnknownTrigger:
		return jsonapi.InvalidAttribute("Type", err)
	}
	return err
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package views

import (
	"encoding/json"
	"strings"

	"log"

	"github.com/ernestio/api-gateway/models"

	graph "gopkg.in/r3labs/graph.v2"
)

// ServiceRender : Service representation to be rendered on the frontend
type ServiceRender struct {
	ID              string              `json:"id"`
	DatacenterID    int                 `json:"datacenter_id"`
	Project         string              `json:"project"`
	Provider        string              `json:"provider"`
	Name            string              `json:"name"`
	Version         string              `json:"version"`
	Status          string              `json:"status"`
	UserID          int                 `json:"user_id"`
	UserName        string              `json:"user_name"`
	LastKnownError  string              `json:"last_known_error"`
	Options         string              `json:"options"`
	Definition      string              `json:"definition"`
	Vpcs            []map[string]string `json:"vpcs"`
	Networks        []map[string]string `json:"networks"`
	Instances       []map[string]string `json:"instances"`
	Nats            []map[string]string `json:"nats"`
	SecurityGroups  []map[string]string `json:"security_groups"`
	Elbs            []map[string]string `json:"elbs"`
	RDSClusters     []map[string]string `json:"rds_clusters"`
	RDSInstances    []map[string]string `json:"rds_instances"`
	EBSVolumes      []map[string]string `json:"ebs_volumes"`
	LoadBalancers   []map[string]string `json:"load_balancers"`
	SQLDatabases    []map[string]string `json:"sql_databases"`
	VirtualMachines []map[string]string `json:"virtual_machines"`
	Roles           []string            `json:"roles"`
}

// Render : Map a Service to a ServiceRender
func (o *ServiceRender) Render(s models.Env) (err error) {
	o.Name = s.Name
	parts := strings.Split(o.Name, models.EnvNameSeparator)
	if len(parts) > 1 {
		o.Name = parts[1]
	}
	o.ID = s.ID
	o.DatacenterID = s.DatacenterID
	o.Version = s.Version.String()
	o.Status = s.Status
	o.UserID = s.UserID
	o.UserName = s.UserName
	if def, ok := s.Definition.(string); ok == true {
		o.Definition = def
	}

	g, err := s.Mapping()
	if err != nil {
		log.Println(err.Error())
		return err
	}

	o.Vpcs = RenderVpcs(g)
	o.Networks = RenderNetworks(g)
	o.SecurityGroups = RenderSecurityGroups(g)
	o.Nats = RenderNats(g)
	o.Instances = RenderInstances(g)
	o.Elbs = RenderELBs(g)
	o.RDSClusters = RenderRDSClusters(g)
	o.RDSInstances = RenderRDSInstances(g)
	o.EBSVolumes = RenderEBSVolumes(g)
	o.LoadBalancers = RenderLoadBalancers(g)
	o.SQLDatabases = RenderSQLDatabases(g)
	o.VirtualMachines = RenderVirtualMachines(g)
	o.Roles = s.Roles
	o.Project = s.Project
	o.Provider = s.Provider

	return err
}

// RenderVpcs : renders a services vpcs
func RenderVpcs(g *graph.Graph) []map[string]string {
	var vpcs []map[string]string

	for _, n := range g.GetComponents().ByType("vpc") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["vpc_aws_id"].(string)
		subnet, _ := (*gc)["vpc_subnet"].(string)
		vpcs = append(vpcs, map[string]string{
			"name":       name,
			"vpc_id":     id,
			"vpc_subnet": subnet,
		})
	}

	return vpcs
}

// RenderNetworks : renders a services networks
func RenderNetworks(g *graph.Graph) []map[string]string {
	var networks []map[string]string

	for _, n := range g.GetComponents().ByType("network") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["network_aws_id"].(string)
		az, _ := (*gc)["availability_zone"].(string)
		networks = append(networks, map[string]string{
			"name":              name,
			"network_aws_id":    id,
			"availability_zone": az,
		})
	}

	return networks
}

// RenderSecurityGroups : renders a services security groups
func RenderSecurityGroups(g *graph.Graph) []map[string]string {
	var sgs []map[string]string

	for _, n := range g.GetComponents().ByType("firewall") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["security_group_aws_id"].(string)
		sgs = append(sgs, map[string]string{
			"name":                  name,
			"security_group_aws_id": id,
		})
	}

	return sgs
}

// RenderNats : renders a services nat gateways
func RenderNats(g *graph.Graph) []map[string]string {
	var nats []map[string]string

	for _, n := range g.GetComponents().ByType("nat") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["nat_gateway_aws_id"].(string)
		pubIP, _ := (*gc)["nat_gateway_allocation_ip"].(string)
		nats = append(nats, map[string]string{
			"name":               name,
			"nat_gateway_aws_id": id,
			"public_ip":          pubIP,
		})
	}

	return nats
}

// RenderELBs : renders a services elbs
func RenderELBs(g *graph.Graph) []map[string]string {
	var elbs []map[string]string

	for _, n := range g.GetComponents().ByType("elb") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		dns, _ := (*gc)["dns_name"].(string)
		elbs = append(elbs, map[string]string{
			"name":     name,
			"dns_name": dns,
		})
	}

	return elbs
}

// RenderInstances : renders a services instances
func RenderInstances(g *graph.Graph) []map[string]string {
	var instances []map[string]string

	for _, n := range g.GetComponents().ByType("instance") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["instance_aws_id"].(string)
		pip, _ := (*gc)["public_ip"].(string)
		ip, _ := (*gc)["ip"].(string)
		instances = append(instances, map[string]string{
			"name":            name,
			"instance_aws_id": id,
			"public_ip":       pip,
			"ip":              ip,
		})
	}

	return instances
}

// RenderRDSClusters : renders a services rds clusters
func RenderRDSClusters(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("rds_cluster") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		endpoint, _ := (*gc)["endpoint"].(string)
		rdss = append(rdss, map[string]string{
			"name":     name,
			"endpoint": endpoint,
		})
	}

	return rdss
}

// RenderRDSInstances : renders a services rds instances
func RenderRDSInstances(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("rds_instance") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		endpoint, _ := (*gc)["endpoint"].(string)
		rdss = append(rdss, map[string]string{
			"name":     name,
			"endpoint": endpoint,
		})
	}

	return rdss
}

// RenderEBSVolumes : renders a services ebs volumes
func RenderEBSVolumes(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("ebs_volume") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["volume_aws_id"].(string)
		rdss = append(rdss, map[string]string{
			"name":          name,
			"volume_aws_id": id,
		})
	}

	return rdss
}

// RenderLoadBalancers : renders load balancers
func RenderLoadBalancers(g *graph.Graph) []map[string]string {
	var lbs []map[string]string
	ips := listIPAddresses(g)

	for _, n := range g.GetComponents().ByType("lb") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["id"].(string)
		configs, _ := (*gc)["frontend_ip_configurations"].([]interface{})
		cfg, _ := configs[0].(map[string]interface{})
		ipID, _ := cfg["public_ip_address_id"].(string)
		ip, _ := ips[ipID]

		lbs = append(lbs, map[string]string{
			"name":      name,
			"id":        id,
			"public_ip": ip,
		})
	}

	return lbs
}

func listIPAddresses(g *graph.Graph) map[string]string {
	existingIPs := make(map[string]string, 0)

	for _, ip := range g.GetComponents().ByType("public_ip") {
		gc := ip.(*graph.GenericComponent)
		id, _ := (*gc)["id"].(string)
		ipAddress, _ := (*gc)["ip_address"].(string)
		existingIPs[id] = ipAddress
	}

	return existingIPs
}

// RenderVirtualMachines : renders virtual machines
func RenderVirtualMachines(g *graph.Graph) []map[string]string {
	var resources []map[string]string
	mappedIPs := make(map[string]interface{}, 0)
	existingIPs := listIPAddresses(g)

	for _, ni := range g.GetComponents().ByType("network_interface") {
		var public []string
		var private []string

		gc := ni.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		ips := make(map[string][]string)

		configs, _ := (*gc)["ip_configuration"].([]interface{})
		for _, cfg := range configs {
			c, _ := cfg.(map[string]interface{})
			pubID, _ := c["public_ip_address_id"].(string)
			pri, _ := c["private_ip_address"].(string)
			if pub, ok := existingIPs[pubID]; ok {
				public = append(public, pub)
			}
			private = append(private, pri)
		}

		ips["public"] = public
		ips["private"] = private
		mappedIPs[name] = make(map[string][]string, 0)
		mappedIPs[name] = ips
	}

	for _, n := range g.GetComponents().ByType("virtual_machine") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["id"].(string)
		networks, _ := (*gc)["network_interfaces"].([]interface{})
		publicIPs := make([]string, 0)
		privateIPs := make([]string, 0)
		for _, ni := range networks {
			netName := ni.(string)
			if val, ok := mappedIPs[netName]; ok {
				ips, _ := val.(map[string][]string)
				publicIPs = append(publicIPs, ips["public"]...)
				privateIPs = append(privateIPs, ips["private"]...)
			}
		}

		resources = append(resources, map[string]string{
			"name":       name,
			"id":         id,
			"public_ip":  strings.Join(publicIPs, ", "),
			"private_ip": strings.Join(privateIPs, ", "),
		})
	}

	return resources
}

// RenderSQLDatabases : renders sql databases
func RenderSQLDatabases(g *graph.Graph) []map[string]string {
	return renderResources(g, "sql_database", func(gc *graph.GenericComponent) map[string]string {
		name, _ := (*gc)["name"].(string)
		server, _ := (*gc)["server_name"].(string)
		id, _ := (*gc)["id"].(string)

		return map[string]string{
			"name":        name,
			"server_name": server + ".database.windows.net",
			"id":          id,
		}
	})
}

type convert func(*graph.GenericComponent) map[string]string

func renderResources(g *graph.Graph, resourceType string, f convert) (resources []map[string]string) {
	for _, n := range g.GetComponents().ByType(resourceType) {
		gc := n.(*graph.GenericComponent)
		resources = append(resources, f(gc))
	}

	return
}

// RenderCollection : Maps a collection of Service on a collection of ServiceRender
func (o *ServiceRender) RenderCollection(services []models.Env) (list []ServiceRender, err error) {
	for _, s := range services {
		var output ServiceRender
		if err := output.Render(s); err == nil {
			list = append(list, output)
		}
	}

	return list, nil
}

// ToJSON : Converts a ServiceRender to json string
func (o *ServiceRender) ToJSON() ([]byte, error) {
	return json.Marshal(o)
}

// RenderDefinition : renders service defiition steps
func RenderDefinition(service map[string]interface{}) (result []byte, err error) {
	var lines []string
	var actions = map[string]string{"create": "Create", "update": "Update", "delete": "Delete"}

	for _, change := range service["changes"].([]interface{}) {
		component := change.(map[string]interface{})
		c := component["_component"].(string)
		c = strings.Replace(c, "_", " ", -1)
		n := component["name"].(string)
		a := component["_action"].(string)
		line := actions[a] + " a " + c + " named " + n
		lines = append(lines, line)
	}

	result, err = json.Marshal(lines)
	if err != nil {
		return result, err
	}

	return result, nil
}
<commit_msg>Avoid panic on empty frontend ip configurations<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package views

import (
	"encoding/json"
	"strings"

	"log"

	"github.com/ernestio/api-gateway/models"

	graph "gopkg.in/r3labs/graph.v2"
)

// ServiceRender : Service representation to be rendered on the frontend
type ServiceRender struct {
	ID              string              `json:"id"`
	DatacenterID    int                 `json:"datacenter_id"`
	Project         string              `json:"project"`
	Provider        string              `json:"provider"`
	Name            string              `json:"name"`
	Version         string              `json:"version"`
	Status          string              `json:"status"`
	UserID          int                 `json:"user_id"`
	UserName        string              `json:"user_name"`
	LastKnownError  string              `json:"last_known_error"`
	Options         string              `json:"options"`
	Definition      string              `json:"definition"`
	Vpcs            []map[string]string `json:"vpcs"`
	Networks        []map[string]string `json:"networks"`
	Instances       []map[string]string `json:"instances"`
	Nats            []map[string]string `json:"nats"`
	SecurityGroups  []map[string]string `json:"security_groups"`
	Elbs            []map[string]string `json:"elbs"`
	RDSClusters     []map[string]string `json:"rds_clusters"`
	RDSInstances    []map[string]string `json:"rds_instances"`
	EBSVolumes      []map[string]string `json:"ebs_volumes"`
	LoadBalancers   []map[string]string `json:"load_balancers"`
	SQLDatabases    []map[string]string `json:"sql_databases"`
	VirtualMachines []map[string]string `json:"virtual_machines"`
	Roles           []string            `json:"roles"`
}

// Render : Map a Service to a ServiceRender
func (o *ServiceRender) Render(s models.Env) (err error) {
	o.Name = s.Name
	parts := strings.Split(o.Name, models.EnvNameSeparator)
	if len(parts) > 1 {
		o.Name = parts[1]
	}
	o.ID = s.ID
	o.DatacenterID = s.DatacenterID
	o.Version = s.Version.String()
	o.Status = s.Status
	o.UserID = s.UserID
	o.UserName = s.UserName
	if def, ok := s.Definition.(string); ok == true {
		o.Definition = def
	}

	g, err := s.Mapping()
	if err != nil {
		log.Println(err.Error())
		return err
	}

	o.Vpcs = RenderVpcs(g)
	o.Networks = RenderNetworks(g)
	o.SecurityGroups = RenderSecurityGroups(g)
	o.Nats = RenderNats(g)
	o.Instances = RenderInstances(g)
	o.Elbs = RenderELBs(g)
	o.RDSClusters = RenderRDSClusters(g)
	o.RDSInstances = RenderRDSInstances(g)
	o.EBSVolumes = RenderEBSVolumes(g)
	o.LoadBalancers = RenderLoadBalancers(g)
	o.SQLDatabases = RenderSQLDatabases(g)
	o.VirtualMachines = RenderVirtualMachines(g)
	o.Roles = s.Roles
	o.Project = s.Project
	o.Provider = s.Provider

	return err
}

// RenderVpcs : renders a services vpcs
func RenderVpcs(g *graph.Graph) []map[string]string {
	var vpcs []map[string]string

	for _, n := range g.GetComponents().ByType("vpc") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["vpc_aws_id"].(string)
		subnet, _ := (*gc)["vpc_subnet"].(string)
		vpcs = append(vpcs, map[string]string{
			"name":       name,
			"vpc_id":     id,
			"vpc_subnet": subnet,
		})
	}

	return vpcs
}

// RenderNetworks : renders a services networks
func RenderNetworks(g *graph.Graph) []map[string]string {
	var networks []map[string]string

	for _, n := range g.GetComponents().ByType("network") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["network_aws_id"].(string)
		az, _ := (*gc)["availability_zone"].(string)
		networks = append(networks, map[string]string{
			"name":              name,
			"network_aws_id":    id,
			"availability_zone": az,
		})
	}

	return networks
}

// RenderSecurityGroups : renders a services security groups
func RenderSecurityGroups(g *graph.Graph) []map[string]string {
	var sgs []map[string]string

	for _, n := range g.GetComponents().ByType("firewall") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["security_group_aws_id"].(string)
		sgs = append(sgs, map[string]string{
			"name":                  name,
			"security_group_aws_id": id,
		})
	}

	return sgs
}

// RenderNats : renders a services nat gateways
func RenderNats(g *graph.Graph) []map[string]string {
	var nats []map[string]string

	for _, n := range g.GetComponents().ByType("nat") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["nat_gateway_aws_id"].(string)
		pubIP, _ := (*gc)["nat_gateway_allocation_ip"].(string)
		nats = append(nats, map[string]string{
			"name":               name,
			"nat_gateway_aws_id": id,
			"public_ip":          pubIP,
		})
	}

	return nats
}

// RenderELBs : renders a services elbs
func RenderELBs(g *graph.Graph) []map[string]string {
	var elbs []map[string]string

	for _, n := range g.GetComponents().ByType("elb") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		dns, _ := (*gc)["dns_name"].(string)
		elbs = append(elbs, map[string]string{
			"name":     name,
			"dns_name": dns,
		})
	}

	return elbs
}

// RenderInstances : renders a services instances
func RenderInstances(g *graph.Graph) []map[string]string {
	var instances []map[string]string

	for _, n := range g.GetComponents().ByType("instance") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["instance_aws_id"].(string)
		pip, _ := (*gc)["public_ip"].(string)
		ip, _ := (*gc)["ip"].(string)
		instances = append(instances, map[string]string{
			"name":            name,
			"instance_aws_id": id,
			"public_ip":       pip,
			"ip":              ip,
		})
	}

	return instances
}

// RenderRDSClusters : renders a services rds clusters
func RenderRDSClusters(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("rds_cluster") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		endpoint, _ := (*gc)["endpoint"].(string)
		rdss = append(rdss, map[string]string{
			"name":     name,
			"endpoint": endpoint,
		})
	}

	return rdss
}

// RenderRDSInstances : renders a services rds instances
func RenderRDSInstances(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("rds_instance") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		endpoint, _ := (*gc)["endpoint"].(string)
		rdss = append(rdss, map[string]string{
			"name":     name,
			"endpoint": endpoint,
		})
	}

	return rdss
}

// RenderEBSVolumes : renders a services ebs volumes
func RenderEBSVolumes(g *graph.Graph) []map[string]string {
	var rdss []map[string]string

	for _, n := range g.GetComponents().ByType("ebs_volume") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["volume_aws_id"].(string)
		rdss = append(rdss, map[string]string{
			"name":          name,
			"volume_aws_id": id,
		})
	}

	return rdss
}

// RenderLoadBalancers : renders load balancers
func RenderLoadBalancers(g *graph.Graph) []map[string]string {
	var lbs []map[string]string
	ips := listIPAddresses(g)

	for _, n := range g.GetComponents().ByType("lb") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["id"].(string)
		configs, _ := (*gc)["frontend_ip_configurations"].([]interface{})
		ip := ""
		if len(configs) > 0 {
			cfg, _ := configs[0].(map[string]interface{})
			ipID, _ := cfg["public_ip_address_id"].(string)
			ip, _ = ips[ipID]
		}

		lbs = append(lbs, map[string]string{
			"name":      name,
			"id":        id,
			"public_ip": ip,
		})
	}

	return lbs
}

func listIPAddresses(g *graph.Graph) map[string]string {
	existingIPs := make(map[string]string, 0)

	for _, ip := range g.GetComponents().ByType("public_ip") {
		gc := ip.(*graph.GenericComponent)
		id, _ := (*gc)["id"].(string)
		ipAddress, _ := (*gc)["ip_address"].(string)
		existingIPs[id] = ipAddress
	}

	return existingIPs
}

// RenderVirtualMachines : renders virtual machines
func RenderVirtualMachines(g *graph.Graph) []map[string]string {
	var resources []map[string]string
	mappedIPs := make(map[string]interface{}, 0)
	existingIPs := listIPAddresses(g)

	for _, ni := range g.GetComponents().ByType("network_interface") {
		var public []string
		var private []string

		gc := ni.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		ips := make(map[string][]string)

		configs, _ := (*gc)["ip_configuration"].([]interface{})
		for _, cfg := range configs {
			c, _ := cfg.(map[string]interface{})
			pubID, _ := c["public_ip_address_id"].(string)
			pri, _ := c["private_ip_address"].(string)
			if pub, ok := existingIPs[pubID]; ok {
				public = append(public, pub)
			}
			private = append(private, pri)
		}

		ips["public"] = public
		ips["private"] = private
		mappedIPs[name] = make(map[string][]string, 0)
		mappedIPs[name] = ips
	}

	for _, n := range g.GetComponents().ByType("virtual_machine") {
		gc := n.(*graph.GenericComponent)
		name, _ := (*gc)["name"].(string)
		id, _ := (*gc)["id"].(string)
		networks, _ := (*gc)["network_interfaces"].([]interface{})
		publicIPs := make([]string, 0)
		privateIPs := make([]string, 0)
		for _, ni := range networks {
			netName := ni.(string)
			if val, ok := mappedIPs[netName]; ok {
				ips, _ := val.(map[string][]string)
				publicIPs = append(publicIPs, ips["public"]...)
				privateIPs = append(privateIPs, ips["private"]...)
			}
		}

		resources = append(resources, map[string]string{
			"name":       name,
			"id":         id,
			"public_ip":  strings.Join(publicIPs, ", "),
			"private_ip": strings.Join(privateIPs, ", "),
		})
	}

	return resources
}

// RenderSQLDatabases : renders sql databases
func RenderSQLDatabases(g *graph.Graph) []map[string]string {
	return renderResources(g, "sql_database", func(gc *graph.GenericComponent) map[string]string {
		name, _ := (*gc)["name"].(string)
		server, _ := (*gc)["server_name"].(string)
		id, _ := (*gc)["id"].(string)

		return map[string]string{
			"name":        name,
			"server_name": server + ".database.windows.net",
			"id":          id,
		}
	})
}

type convert func(*graph.GenericComponent) map[string]string

func renderResources(g *graph.Graph, resourceType string, f convert) (resources []map[string]string) {
	for _, n := range g.GetComponents().ByType(resourceType) {
		gc := n.(*graph.GenericComponent)
		resources = append(resources, f(gc))
	}

	return
}

// RenderCollection : Maps a collection of Service on a collection of ServiceRender
func (o *ServiceRender) RenderCollection(services []models.Env) (list []ServiceRender, err error) {
	for _, s := range services {
		var output ServiceRender
		if err := output.Render(s); err == nil {
			list = append(list, output)
		}
	}

	return list, nil
}

// ToJSON : Converts a ServiceRender to json string
func (o *ServiceRender) ToJSON() ([]byte, error) {
	return json.Marshal(o)
}

// RenderDefinition : renders service defiition steps
func RenderDefinition(service map[string]interface{}) (result []byte, err error) {
	var lines []string
	var actions = map[string]string{"create": "Create", "update": "Update", "delete": "Delete"}

	for _, change := range service["changes"].([]interface{}) {
		component := change.(map[string]interface{})
		c := component["_component"].(string)
		c = strings.Replace(c, "_", " ", -1)
		n := component["name"].(string)
		a := component["_action"].(string)
		line := actions[a] + " a " + c + " named " + n
		lines = append(lines, line)
	}

	result, err = json.Marshal(lines)
	if err != nil {
		return result, err
	}

	return result, nil
}
<|endoftext|>


<commit_before>package web

const (
	indexTemplate string = `
<!DOCTYPE html>

	<meta charset="utf-8">
	<title> Wallboard Control </title>

	Oops, something went wrong with the Wallboard page!

`

	welcomeTemplate string = `
<!DOCTYPE html>

	<meta charset="utf-8">
	<title> Welcome </title>

wbc

		{{ if ne .Client "" }}
Client: {{ .Client }}
{{end}}

IP Addr: {{ .RemoteAddr }}

Add a URL or two and this page will disappear. :)

`
)
<commit_msg>Fix nil pointer reference<commit_after>package web

const (
	indexTemplate string = `
<!DOCTYPE html>

	<meta charset="utf-8">
	<title> Wallboard Control </title>

	Oops, something went wrong with the Wallboard page!

`

	welcomeTemplate string = `
<!DOCTYPE html>

	<meta charset="utf-8">
	<title> Welcome </title>

wbc

		{{ if ne .Client "" }}
Client: {{ .Client }}
{{end}}

IP Addr: {{ .RemoteAddr }}

Add a URL or two and this page will disappear. :)

`
)
<|endoftext|>


<commit_before>package webui

import "html/template"

// PageTemplate is an HTML template for a complete page.
var PageTemplate = template.Must(template.New("page").Parse(`
<!DOCTYPE html>

<title>{{.Title}}</title>

{{.Title}}

{{.Content}}

`))

// PageData is a valid data argument for PageTemplate.
type PageData struct {
	Title   string
	Content template.HTML
}
<commit_msg>Modify webui template styles<commit_after>package webui

import "html/template"

// PageTemplate is an HTML template for a complete page.
var PageTemplate = template.Must(template.New("page").Parse(`
<!DOCTYPE html>

<title>{{.Title}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

{{.Title}}

{{.Content}}

`))

// PageData is a valid data argument for PageTemplate.
type PageData struct {
	Title   string
	Content template.HTML
}
<|endoftext|>


<commit_before>package neurgo

import (
	"fmt"
	"github.com/ajstarks/svgo"
	"io"
	"log"
)

func (cortex Cortex) RenderSVG(writer io.Writer) {

	width := 500
	height := 500
	canvas := svg.New(writer)

	canvas.Start(width, height)

	canvas.Rect(0, 0, width, height, canvas.RGB(255, 255, 255))

	x := 100
	xDelta := 100
	yDelta := 100
	radius := 25
	neuronFill := "fill:black"
	actuatorFill := "fill:red"
	sensorFill := "fill:blue"

	layerToNodeIdMap := cortex.NodeIdLayerMap()
	layerIndexes := layerToNodeIdMap.Keys()
	for _, layerIndex := range layerIndexes {

		y := 100
		nodeIds := layerToNodeIdMap[layerIndex]
		layerIndexStr := fmt.Sprintf("%v", layerIndex)

		canvas.Text(x, y, layerIndexStr, "font-size:12;fill:black")
		y += yDelta

		for _, nodeId := range nodeIds {
			log.Printf("nodeId: %v", nodeId)
			log.Printf("x: %v, y: %v", x, y)

			switch nodeId.NodeType {
			case NEURON:
				canvas.Circle(x, y, radius, neuronFill)
			case ACTUATOR:
				canvas.Circle(x, y, radius, actuatorFill)
			case SENSOR:
				canvas.Circle(x, y, radius, sensorFill)
			}

			y += yDelta
		}

		x += xDelta
	}

	canvas.End()

}
<commit_msg>draw lines between nodes<commit_after>package neurgo

import (
	"fmt"
	"github.com/ajstarks/svgo"
	"io"
	"log"
)

type NodeCircleSVG struct {
	x      int
	y      int
	radius int
}

type NodeUUIDToCircleSVG map[string]NodeCircleSVG

func (cortex *Cortex) RenderSVG(writer io.Writer) {

	width := 500
	height := 500
	x := 100
	xDelta := 100
	yDelta := 100
	radius := 25
	neuronFill := "fill:black"
	actuatorFill := "fill:red"
	sensorFill := "fill:blue"

	canvas := svg.New(writer)
	canvas.Start(width, height)
	canvas.Rect(0, 0, width, height, canvas.RGB(255, 255, 255))

	nodeUUIDToCircleSVG := make(NodeUUIDToCircleSVG)
	layerToNodeIdMap := cortex.NodeIdLayerMap()
	layerIndexes := layerToNodeIdMap.Keys()

	for _, layerIndex := range layerIndexes {

		y := 100
		nodeIds := layerToNodeIdMap[layerIndex]
		layerIndexStr := fmt.Sprintf("%v", layerIndex)

		canvas.Text(x, y, layerIndexStr, "font-size:12;fill:black")
		y += yDelta

		for _, nodeId := range nodeIds {

			switch nodeId.NodeType {
			case NEURON:
				canvas.Circle(x, y, radius, neuronFill)
			case ACTUATOR:
				canvas.Circle(x, y, radius, actuatorFill)
			case SENSOR:
				canvas.Circle(x, y, radius, sensorFill)
			}

			circleSVG := NodeCircleSVG{x: x, y: y, radius: radius}
			nodeUUIDToCircleSVG[nodeId.UUID] = circleSVG

			y += yDelta
		}

		x += xDelta
	}

	addConnectionsToSVG(cortex, canvas, nodeUUIDToCircleSVG)

	canvas.End()

}

func addConnectionsToSVG(cortex *Cortex, canvas *svg.SVG, nodeUUIDToCircleSVG NodeUUIDToCircleSVG) {

	// loop over all nodes

	// loop over all outbound connections

	// find node id of source and target

	// loopup circle svg for that node

	// draw a line from source center to target center

	layerToNodeIdMap := cortex.NodeIdLayerMap()
	layerIndexes := layerToNodeIdMap.Keys()

	for _, layerIndex := range layerIndexes {

		nodeIds := layerToNodeIdMap[layerIndex]

		for _, nodeId := range nodeIds {
			log.Printf("nodeId: %v", nodeId)

			node := cortex.FindConnector(nodeId)
			if node == nil {
				continue
			}
			for _, outbound := range node.outbound() {
				tgtNodeId := outbound.NodeId
				srcCircle := nodeUUIDToCircleSVG[nodeId.UUID]
				tgtCircle := nodeUUIDToCircleSVG[tgtNodeId.UUID]
				connectNodesSVG(canvas, srcCircle, tgtCircle)

			}

		}

	}

}

func connectNodesSVG(canvas *svg.SVG, src NodeCircleSVG, tgt NodeCircleSVG) {
	linestyle := []string{`stroke="blue"`, `stroke-linecap="round"`, `stroke-width="5"`}
	canvas.Line(src.x, src.y, tgt.x, tgt.y, linestyle[0], linestyle[1], linestyle[2])
}
<|endoftext|>


<commit_before>package fire

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/256dpi/fire/coal"

	"github.com/256dpi/jsonapi"
)

// A Tester provides facilities to the test a fire API.
type Tester struct {
	// The store to use for cleaning the database.
	Store *coal.Store

	// The registered models.
	Models []coal.Model

	// The handler to be tested.
	Handler http.Handler

	// A path prefix e.g. 'api'.
	Prefix string

	// The token that should be used to authorize the request.
	Token string

	// These headers are added to the request if available.
	Headers map[string]string
}

// Register will register the specified model with the tester.
func (t *Tester) Register(model coal.Model) {
	t.Models = append(t.Models, model)
}

// Clean will remove the collections of models that have been registered.
func (t *Tester) Clean() {
	store := t.Store.Copy()
	defer store.Close()

	for _, model := range t.Models {
		// remove all is faster than dropping the collection
		store.C(model).RemoveAll(nil)
	}
}

// Save will save the specified model.
func (t *Tester) Save(model coal.Model) coal.Model {
	store := t.Store.Copy()
	defer store.Close()

	// initialize model
	model = coal.Init(model)

	// insert to collection
	err := store.C(model).Insert(model)
	if err != nil {
		panic(err)
	}

	return model
}

// SaveAll will save the specified models.
func (t *Tester) SaveAll(models ...coal.Model) {
	store := t.Store.Copy()
	defer store.Close()

	// loop through all models
	for _, model := range models {
		// initialize model
		model = coal.Init(model)

		// insert to collection
		err := store.C(model).Insert(model)
		if err != nil {
			panic(err)
		}
	}
}

// FindLast will return the last saved model.
func (t *Tester) FindLast(model coal.Model) coal.Model {
	store := t.Store.Copy()
	defer store.Close()

	err := store.C(model).Find(nil).Sort("-_id").One(model)
	if err != nil {
		panic(err)
	}

	return coal.Init(model)
}

// Path returns a root prefixed path for the supplied path.
func (t *Tester) Path(path string) string {
	// add root slash
	path = "/" + strings.Trim(path, "/")

	// add prefix if available
	if t.Prefix != "" {
		path = "/" + t.Prefix + path
	}

	return path
}

// Request will run the specified request against the registered handler. This
// function can be used to create custom testing facilities.
func (t *Tester) Request(method, path string, payload string, callback func(*httptest.ResponseRecorder, *http.Request)) {
	// create request
	request, err := http.NewRequest(method, t.Path(path), strings.NewReader(payload))
	if err != nil {
		panic(err)
	}

	// prepare recorder
	recorder := httptest.NewRecorder()

	// preset jsonapi accept header
	request.Header.Set("Accept", jsonapi.MediaType)

	// add content type if required
	if method == "POST" || method == "PATCH" || method == "DELETE" {
		request.Header.Set("Content-Type", jsonapi.MediaType)
	}

	// TODO: Remove token as it can be set through the headers?

	// add authorization header
	if t.Token != "" {
		request.Header.Set("Authorization", "Bearer "+t.Token)
	}

	// set custom headers
	for k, v := range t.Headers {
		request.Header.Set(k, v)
	}

	// server request
	t.Handler.ServeHTTP(recorder, request)

	// run callback
	callback(recorder, request)
}

// DebugRequest returns a string of information to debug requests.
func (t *Tester) DebugRequest(r *http.Request, rr *httptest.ResponseRecorder) string {
	return fmt.Sprintf(`
	URL:    %s
	Header: %s
	Status: %d
	Header: %v
	Body:   %v`, r.URL.String(), r.Header, rr.Code, rr.HeaderMap, rr.Body.String())
}
<commit_msg>removed token field<commit_after>package fire

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/256dpi/fire/coal"

	"github.com/256dpi/jsonapi"
)

// A Tester provides facilities to the test a fire API.
type Tester struct {
	// The store to use for cleaning the database.
	Store *coal.Store

	// The registered models.
	Models []coal.Model

	// The handler to be tested.
	Handler http.Handler

	// A path prefix e.g. 'api'.
	Prefix string

	// The headers to be set on all requests.
	Headers map[string]string
}

// Register will register the specified model with the tester.
func (t *Tester) Register(model coal.Model) {
	t.Models = append(t.Models, model)
}

// Clean will remove the collections of models that have been registered.
func (t *Tester) Clean() {
	store := t.Store.Copy()
	defer store.Close()

	for _, model := range t.Models {
		// remove all is faster than dropping the collection
		store.C(model).RemoveAll(nil)
	}
}

// Save will save the specified model.
func (t *Tester) Save(model coal.Model) coal.Model {
	store := t.Store.Copy()
	defer store.Close()

	// initialize model
	model = coal.Init(model)

	// insert to collection
	err := store.C(model).Insert(model)
	if err != nil {
		panic(err)
	}

	return model
}

// SaveAll will save the specified models.
func (t *Tester) SaveAll(models ...coal.Model) {
	store := t.Store.Copy()
	defer store.Close()

	// loop through all models
	for _, model := range models {
		// initialize model
		model = coal.Init(model)

		// insert to collection
		err := store.C(model).Insert(model)
		if err != nil {
			panic(err)
		}
	}
}

// FindLast will return the last saved model.
func (t *Tester) FindLast(model coal.Model) coal.Model {
	store := t.Store.Copy()
	defer store.Close()

	err := store.C(model).Find(nil).Sort("-_id").One(model)
	if err != nil {
		panic(err)
	}

	return coal.Init(model)
}

// Path returns a root prefixed path for the supplied path.
func (t *Tester) Path(path string) string {
	// add root slash
	path = "/" + strings.Trim(path, "/")

	// add prefix if available
	if t.Prefix != "" {
		path = "/" + t.Prefix + path
	}

	return path
}

// Request will run the specified request against the registered handler. This
// function can be used to create custom testing facilities.
func (t *Tester) Request(method, path string, payload string, callback func(*httptest.ResponseRecorder, *http.Request)) {
	// create request
	request, err := http.NewRequest(method, t.Path(path), strings.NewReader(payload))
	if err != nil {
		panic(err)
	}

	// prepare recorder
	recorder := httptest.NewRecorder()

	// preset jsonapi accept header
	request.Header.Set("Accept", jsonapi.MediaType)

	// add content type if required
	if method == "POST" || method == "PATCH" || method == "DELETE" {
		request.Header.Set("Content-Type", jsonapi.MediaType)
	}

	// set custom headers
	for k, v := range t.Headers {
		request.Header.Set(k, v)
	}

	// server request
	t.Handler.ServeHTTP(recorder, request)

	// run callback
	callback(recorder, request)
}

// DebugRequest returns a string of information to debug requests.
func (t *Tester) DebugRequest(r *http.Request, rr *httptest.ResponseRecorder) string {
	return fmt.Sprintf(`
	URL:    %s
	Header: %s
	Status: %d
	Header: %v
	Body:   %v`, r.URL.String(), r.Header, rr.Code, rr.HeaderMap, rr.Body.String())
}
<|endoftext|>


<commit_before>package testme

import (
	"reflect"
	"testing"
)

type Expect struct {
	t    *testing.T
	name string
}

func (t *Expect) Expect(actual interface{}) *Expectation {
	return &Expectation{t.t, t.name, actual}
}

type Expectation struct {
	t      *testing.T
	name   string
	actual interface{}
}

func (e *Expectation) ToBe(expected interface{}) {
	if expected != e.actual {
		e.t.Logf("%s: expected %s to be %s", e.name, expected, e.actual)
		e.t.Fail()
	}
}

func Run(t *testing.T, suite interface{}) {
	suiteType := reflect.TypeOf(suite)
	for i := 0; i < suiteType.NumMethod(); i++ {
		method := suiteType.Method(i)
		expect := &Expect{t, method.Name}
		method.Func.Call([]reflect.Value{
			reflect.ValueOf(suite),
			reflect.ValueOf(expect),
		})
	}
}
<commit_msg>fixed fail message<commit_after>package testme

import (
	"reflect"
	"testing"
)

type Expect struct {
	t    *testing.T
	name string
}

func (t *Expect) Expect(actual interface{}) *Expectation {
	return &Expectation{t.t, t.name, actual}
}

type Expectation struct {
	t      *testing.T
	name   string
	actual interface{}
}

func (e *Expectation) ToBe(expected interface{}) {
	if expected != e.actual {
		e.t.Logf("%s: expected %s to be %s", e.name, e.actual, expected)
		e.t.Fail()
	}
}

func Run(t *testing.T, suite interface{}) {
	suiteType := reflect.TypeOf(suite)
	for i := 0; i < suiteType.NumMethod(); i++ {
		method := suiteType.Method(i)
		expect := &Expect{t, method.Name}
		method.Func.Call([]reflect.Value{
			reflect.ValueOf(suite),
			reflect.ValueOf(expect),
		})
	}
}
<|endoftext|>