<commit_before>package apiv1

import (
	"errors"
		"os"
			"strconv"
			)

			type GetStoragePoolsResp_entries struct {
				Entries `json:"entries"`
					Content []struct {
									StoragePoolName string `json:"i$ElementName"`
													InstanceName string `json:"i$InstanceID"`
														}
														}

														//Get a list of all Storage Pools associated with SymmID
														func (smis *SMIS) GetStoragePools(sid string) (resp *GetStoragePoolsResp, err error){
															err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::SymmStorageSystem,Name::" + sid + "/relationships/CIM_StoragePool", nil, &resp)
																jaon.UnmRAHl
																	return resp,err
																	}

																	//Get a list of Storage Volumes to/associated with a Device Masking Group
																	func (smis *SMIS) GetDeviceMaskingGroups(sid string) (resp *GetDeviceMaskingGroupsResp, err error){
																		err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::Symm_StorageSystem,Name::" + sid + "/relationships/CIM_DeviceMaskingGroup", nil, &resp)
																			return resp,err
																			}

																			//Get a list of Storage Volumes on/associated with SymmID
																			func (smis *SMIS) GetStorageVolumes(sid string) (resp *GetStorageVolumesResp, err error){
																				err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::Symm_StorageSystem,Name::" + sid + "/relationships/CIM_StorageVolume", nil, &resp)
																					return resp,err
																					}

																					type PostVolumesReq struct {
																					{
																						Content PostVolumesContent `json: "content"`
																						}

																						type PostVolumesContent struct {
																							ElementType string `json: "ElementType"`
																								Size string `json: "Size"`
																									ElementName string `json: "ElementName"`
																										EMCNumberOfDevices string `json: "EMCNumberOfDevices"`
																											Type string `json: "@type"`
																											}
																											//Add goal struct later

																											type PostVolumesResp struct {

																											}

																											//Create a Storage Volume
																											func (smis *SMIS) PostVolumes(req *PostVolumesReq, sid string) (resp *PostVolumesResp, err error){
																												err = smis.query("POST","/ecom/edaa/root/emc/instances/Symm_StorageConfigurationService/CreationClassName::Symm_StorageConfigurationService,Name::EMCStorageConfigurationService,SystemCreationClassName::Symm_StorageSystem,SystemName::" + sid + "/action/CreateOrModifyElementFromStoragePool", req, &resp)
																													return resp,err
																													}

<commit_msg>fixed white space added new structs<commit_after>package apiv1

import (
	"errors"
	"os"
	"strconv"
	)

type GetStoragePoolsResp_entries struct {
	Entries `json:"entries"`
	Content []struct {
		StoragePoolName string `json:"i$ElementName"`
		InstanceName string `json:"i$InstanceID"`
		}
	}
//Get a list of all Storage Pools associated with SymmID
func (smis *SMIS) GetStoragePools(sid string) (resp *GetStoragePoolsResp, err error){
	err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::SymmStorageSystem,Name::" + sid + "/relationships/CIM_StoragePool", nil, &resp)
	return resp,err
}

//Get a list of Storage Volumes to/associated with a Device Masking Group
func (smis *SMIS) GetDeviceMaskingGroups(sid string) (resp *GetDeviceMaskingGroupsResp, err error){
	err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::Symm_StorageSystem,Name::" + sid + "/relationships/CIM_DeviceMaskingGroup", nil, &resp)
	return resp,err
}

//Get a list of Storage Volumes on/associated with SymmID
func (smis *SMIS) GetStorageVolumes(sid string) (resp *GetStorageVolumesResp, err error){
	err = smis.query("GET","/ecom/edaa/root/emc/instances/Symm_StorageSystem/CreationClassName::Symm_StorageSystem,Name::" + sid + "/relationships/CIM_StorageVolume", nil, &resp)
	return resp,err
}

type PostVolumesReq struct {

}

type PostVolumesContent struct {

	ElementType string `json: "ElementType"`
	Size string `json: "Size"`
	ElementName string `json: "ElementName"`
	EMCNumberOfDevices string `json: "EMCNumberOfDevices"`
	Type string `json: "@type"`
}
//Add goal struct later

type PostVolumesResp struct {

}

//Create a Storage Volume
func (smis *SMIS) PostVolumes(req *PostVolumesReq, sid string) (resp *PostVolumesResp, err error){
	err = smis.query("POST","/ecom/edaa/root/emc/instances/Symm_StorageConfigurationService/CreationClassName::Symm_StorageConfigurationService,Name::EMCStorageConfigurationService,SystemCreationClassName::Symm_StorageSystem,SystemName::" + sid + "/action/CreateOrModifyElementFromStoragePool", req, &resp)
	return resp,err
}

<|endoftext|>


<commit_before>package evaluator

import "monkey/ast"
import "monkey/object"

func Eval(node ast.Node) object.Object {
	switch node := node.(type) {
	// Statements
	case *ast.Program:
		return evalStatements(node.Statements)
	case *ast.ExpressionStatement:
		return Eval(node.Expression)
	// Expressions
	case *ast.IntegerLiteral:
		return &object.Integer{Value: node.Value}
	case *ast.Boolean:
		return &object.Boolean{Value: node.Value}
	}

	return nil
}

func evalStatements(stmts []ast.Statement) object.Object {
	var result object.Object

	for _, statement := range stmts {
		result = Eval(statement)
	}

	return result
}
<commit_msg>refactored boolean object<commit_after>package evaluator

import "monkey/ast"
import "monkey/object"

var (
	TRUE  = &object.Boolean{Value: true}
	FALSE = &object.Boolean{Value: false}
)

func Eval(node ast.Node) object.Object {
	switch node := node.(type) {
	// Statements
	case *ast.Program:
		return evalStatements(node.Statements)
	case *ast.ExpressionStatement:
		return Eval(node.Expression)
	// Expressions
	case *ast.IntegerLiteral:
		return &object.Integer{Value: node.Value}
	case *ast.Boolean:
		return nativeBoolToBooleanObject(node.Value)
	}

	return nil
}

func evalStatements(stmts []ast.Statement) object.Object {
	var result object.Object

	for _, statement := range stmts {
		result = Eval(statement)
	}

	return result
}

func nativeBoolToBooleanObject(input bool) *object.Boolean {
	if input {
		return TRUE
	}
	return FALSE
}
<|endoftext|>


<commit_before>// The package gomotion defines a concurrent Go library that can connect to a Leap motion device over a WebSocket conection.
// By default, the LeapMotion exposes a JSON WebSocket that pumps out messages near 30 to 50 fps.
package gomotion

import (
	"code.google.com/p/go.net/websocket"
)

// The LeapMotionDevice definition. Connecting to a device will return an instance of this struct.
type LeapMotionDevice struct {
	Pipe       chan *Frame
	Connection *websocket.Conn
}

// This function acts as a constructor and connector for the gomotion package.
func GetDevice(url string) (*LeapMotionDevice, error) {
	pipe := make(chan *Frame)
	connection, err := websocket.Dial(url, "", "http://localhost")
	if err != nil {
		return nil, err
	}
	return &LeapMotionDevice{pipe, connection}, nil
}

// This function starts the listening on the WebSocket. By default it enables Gestures on the LeapMotionDevice.
func (device *LeapMotionDevice) Listen() (error) {
	var config struct {
		enableGestures bool `json:"enableGestures"`
	}
	config.enableGestures = true
	err := websocket.JSON.Send(device.Connection, &config)
	if err != nil {
		return err
	}
	go device.listenRead()
	return nil
}

func (device *LeapMotionDevice) listenRead() (error){
	for {
		var frame Frame
		err := websocket.JSON.Receive(device.Connection, &frame)
		if err == nil {
			device.Pipe <- &frame
		} else {
			return err
		}
	}
	return nil
}

// This function closes the internal WebSocket connection on a LeapMotionDevice
func (device *LeapMotionDevice) Close() {
	device.Connection.Close()
}
<commit_msg>Before an error in decoding caused the program to block forever since the read goroutine returned and stopped. Now errors are reported.<commit_after>// The package gomotion defines a concurrent Go library that can connect to a Leap motion device over a WebSocket conection.
// By default, the LeapMotion exposes a JSON WebSocket that pumps out messages near 30 to 50 fps.
package gomotion

import (
	"code.google.com/p/go.net/websocket"
	"net"
	"fmt"
)

// A simple type to carry decode errors along rather than just dieing.
type FrameErr struct {
	Frame *Frame
	Error error
}

// The LeapMotionDevice definition. Connecting to a device will return an instance of this struct.
type LeapMotionDevice struct {
	Pipe       chan FrameErr
	Connection *websocket.Conn
}

// This function acts as a constructor and connector for the gomotion package.
func GetDevice(url string) (*LeapMotionDevice, error) {
	pipe := make(chan FrameErr)
	connection, err := websocket.Dial(url, "", "http://localhost")
	if err != nil {
		return nil, err
	}
	return &LeapMotionDevice{pipe, connection}, nil
}

// This function starts the listening on the WebSocket. By default it enables Gestures on the LeapMotionDevice.
func (device *LeapMotionDevice) Listen() error {
	config := struct {
		enableGestures bool `json:"enableGestures"`
	} { true }
	if err := websocket.JSON.Send(device.Connection, &config); err != nil {
		return err
	}
	go device.listenRead()
	return nil
}

func (device *LeapMotionDevice) listenRead() {
	for {
		var frame FrameErr
		if err := websocket.JSON.Receive(device.Connection, &frame.Frame); err != nil {
			// Slightly way to avoid another variable in LeapMotionDevice. Works for me.
			if _, ok := err.(*net.OpError); ok {
				fmt.Println("Closed!")
				close(device.Pipe)
				return
			}
			frame.Error = err
		}
		device.Pipe <- frame
	}
	close(device.Pipe)
}

// This function closes the internal WebSocket connection on a LeapMotionDevice
func (device *LeapMotionDevice) Close() {
	device.Connection.Close()
}
<|endoftext|>


<commit_before>package image

import (
	"bytes"
	"encoding/base64"
	"github.com/labstack/echo"
	"golang.org/x/image/draw"
	goimg "image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"net/http"
	"xorkevin.dev/governor"
	"xorkevin.dev/governor/service/fileloader"
)

const (
	defaultThumbnailWidth  = 24
	defaultThumbnailHeight = 24
	defaultQuality         = 85
	defaultThumbQuality    = 50
)

type (
	// Image is an open image file
	Image interface {
		Duplicate() Image
		Resize(width, height int)
		ResizeFit(width, height int)
		ResizeLimit(width, height int)
		Crop(bounds goimg.Rectangle)
		ResizeFill(width, height int)
		ToJpeg(quality int) (*bytes.Buffer, error)
		ToBase64(quality int) (string, error)
	}

	imageData struct {
		img goimg.Image
	}

	// Options represent the image options of the loaded image
	Options struct {
		Width        int
		Height       int
		ThumbWidth   int
		ThumbHeight  int
		Quality      int
		ThumbQuality int
		Fill         bool
	}
)

// LoadJpeg reads an image from a form and encodes it as a jpeg
func LoadJpeg(c echo.Context, formField string, opt Options) (*bytes.Buffer, string, error) {
	if opt.Width < 1 || opt.Height < 1 {
		opt.Width = defaultThumbnailWidth
		opt.Height = defaultThumbnailHeight
	}
	if opt.ThumbWidth < 1 || opt.ThumbHeight < 1 {
		opt.ThumbWidth = defaultThumbnailWidth
		opt.ThumbHeight = defaultThumbnailHeight
	}
	if opt.Quality < 1 || opt.Quality > 100 {
		opt.Quality = defaultQuality
	}
	if opt.ThumbQuality < 1 || opt.ThumbQuality > 100 {
		opt.ThumbQuality = defaultThumbQuality
	}

	img, err := LoadImage(c, formField)
	if err != nil {
		return nil, "", err
	}
	if opt.Fill {
		img.ResizeFill(opt.Width, opt.Height)
	} else {
		img.ResizeLimit(opt.Width, opt.Height)
	}
	thumb := img.Duplicate()
	thumb.ResizeLimit(opt.ThumbWidth, opt.ThumbHeight)

	b, err := img.ToJpeg(opt.Quality)
	if err != nil {
		return nil, "", governor.NewError("Failed to encode image as JPEG", http.StatusInternalServerError, err)
	}
	b2, err := thumb.ToBase64(opt.ThumbQuality)
	if err != nil {
		return nil, "", governor.NewError("Failed to encode thumbnail as JPEG", http.StatusInternalServerError, err)
	}
	return b, b2, nil
}

const (
	// MediaTypeJpeg is the mime type for jpeg images
	MediaTypeJpeg = "image/jpeg"
	// MediaTypePng is the mime type for png images
	MediaTypePng = "image/png"
	// MediaTypeGif is the mime type for gif images
	MediaTypeGif = "image/gif"
)

func LoadImage(c echo.Context, formField string) (Image, error) {
	file, mediaType, _, err := fileloader.LoadOpenFile(c, formField, []string{MediaTypePng, MediaTypeJpeg, MediaTypeGif})
	if err != nil {
		return nil, governor.NewErrorUser("Invalid image file", http.StatusBadRequest, err)
	}
	defer func() {
		err := file.Close()
		if err != nil {
		}
	}()
	var img goimg.Image
	switch mediaType {
	case MediaTypeJpeg:
		if i, err := jpeg.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid JPEG image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	case MediaTypePng:
		if i, err := png.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid PNG image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	case MediaTypeGif:
		if i, err := gif.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid GIF image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	}
	return &imageData{
		img: img,
	}, nil
}

func (i imageData) Duplicate() Image {
	bounds := i.img.Bounds()
	target := goimg.NewNRGBA(bounds)
	draw.Draw(target, target.Bounds(), i.img, bounds.Min, draw.Src)
	return &imageData{
		img: target,
	}
}

func (i *imageData) Resize(width, height int) {
	target := goimg.NewNRGBA(goimg.Rect(0, 0, width, height))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.ApproxBiLinear.Scale(target, target.Bounds(), i.img, i.img.Bounds(), draw.Src, nil)
	i.img = target
}

func dimensionsFit(fromWidth, fromHeight, toWidth, toHeight int) (int, int) {
	// fromRatio < toRatio
	if fromWidth*toHeight < toWidth*fromHeight {
		// height is fit
		return fromWidth * toHeight / fromHeight, toHeight
	} else {
		// width is fit
		return toWidth, fromHeight * toWidth / fromWidth
	}
}

func (i *imageData) ResizeFit(width, height int) {
	s := i.img.Bounds().Size()
	targetWidth, targetHeight := dimensionsFit(s.X, s.Y, width, height)
	i.Resize(targetWidth, targetHeight)
}

func (i *imageData) ResizeLimit(width, height int) {
	s := i.img.Bounds().Size()
	if s.X < width && s.Y < height {
		return
	}
	i.ResizeFit(width, height)
}

func (i *imageData) Crop(bounds goimg.Rectangle) {
	size := bounds.Size()
	target := goimg.NewNRGBA(goimg.Rect(0, 0, size.X, size.Y))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.Draw(target, target.Bounds(), i.img, bounds.Min, draw.Src)
	i.img = target
}

func maxInt(a, b int) int {
	if a < b {
		return b
	}
	return a
}

func dimensionsFill(fromWidth, fromHeight, toWidth, toHeight int) (int, int, int, int) {
	// fromRatio < toRatio
	if fromWidth*toHeight < toWidth*fromHeight {
		// width is fit
		height := toHeight * fromWidth / toWidth
		return fromWidth, height, 0, maxInt((fromHeight-height)/2, 0)
	} else {
		// height is fit
		width := toWidth * fromHeight / toHeight
		return width, fromHeight, maxInt((fromWidth-width)/2, 0), 0
	}
}

func (i *imageData) ResizeFill(width, height int) {
	s := i.img.Bounds().Size()
	targetWidth, targetHeight, offsetX, offsetY := dimensionsFill(s.X, s.Y, width, height)
	target := goimg.NewNRGBA(goimg.Rect(0, 0, width, height))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.ApproxBiLinear.Scale(target, target.Bounds(), i.img, goimg.Rect(offsetX, offsetY, offsetX+targetWidth, offsetY+targetHeight), draw.Src, nil)
	i.img = target
}

func (i *imageData) ToJpeg(quality int) (*bytes.Buffer, error) {
	b := &bytes.Buffer{}
	j := jpeg.Options{
		Quality: quality,
	}
	if err := jpeg.Encode(b, i.img, &j); err != nil {
		return nil, governor.NewError("Failed to encode JPEG image", http.StatusInternalServerError, err)
	}
	return b, nil
}

type PngCompressionOpt int

const (
	PngDefault PngCompressionOpt = 0
	PngNone    PngCompressionOpt = 1
	PngFast    PngCompressionOpt = 2
	PngBest    PngCompressionOpt = 3
)

func compressionOptTranslate(level PngCompressionOpt) png.CompressionLevel {
	switch level {
	case PngDefault:
		return png.DefaultCompression
	case PngNone:
		return png.NoCompression
	case PngFast:
		return png.BestSpeed
	case PngBest:
		return png.BestCompression
	default:
		return png.DefaultCompression
	}
}

func (i *imageData) ToPng(level PngCompressionOpt) (*bytes.Buffer, error) {
	b := &bytes.Buffer{}
	encoder := png.Encoder{
		CompressionLevel: compressionOptTranslate(level),
	}
	if err := encoder.Encode(b, i.img); err != nil {
		return nil, governor.NewError("Failed to encode PNG image", http.StatusInternalServerError, err)
	}
	return b, nil
}

const (
	dataURIPrefixJpeg = "data:image/jpeg;base64,"
)

func (i *imageData) ToBase64(quality int) (string, error) {
	b, err := i.ToJpeg(quality)
	if err != nil {
		return "", err
	}
	return dataURIPrefixJpeg + base64.RawStdEncoding.EncodeToString(b.Bytes()), nil
}
<commit_msg>Impl FromImage in image service to intake go std Image<commit_after>package image

import (
	"bytes"
	"encoding/base64"
	"github.com/labstack/echo"
	"golang.org/x/image/draw"
	goimg "image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"net/http"
	"xorkevin.dev/governor"
	"xorkevin.dev/governor/service/fileloader"
)

const (
	defaultThumbnailWidth  = 24
	defaultThumbnailHeight = 24
	defaultQuality         = 85
	defaultThumbQuality    = 50
)

type (
	// Image is an open image file
	Image interface {
		Duplicate() Image
		Resize(width, height int)
		ResizeFit(width, height int)
		ResizeLimit(width, height int)
		Crop(bounds goimg.Rectangle)
		ResizeFill(width, height int)
		ToJpeg(quality int) (*bytes.Buffer, error)
		ToBase64(quality int) (string, error)
	}

	imageData struct {
		img goimg.Image
	}

	// Options represent the image options of the loaded image
	Options struct {
		Width        int
		Height       int
		ThumbWidth   int
		ThumbHeight  int
		Quality      int
		ThumbQuality int
		Fill         bool
	}
)

func FromImage(img goimg.Image) Image {
	return &imageData{
		img: img,
	}
}

// LoadJpeg reads an image from a form and encodes it as a jpeg
func LoadJpeg(c echo.Context, formField string, opt Options) (*bytes.Buffer, string, error) {
	if opt.Width < 1 || opt.Height < 1 {
		opt.Width = defaultThumbnailWidth
		opt.Height = defaultThumbnailHeight
	}
	if opt.ThumbWidth < 1 || opt.ThumbHeight < 1 {
		opt.ThumbWidth = defaultThumbnailWidth
		opt.ThumbHeight = defaultThumbnailHeight
	}
	if opt.Quality < 1 || opt.Quality > 100 {
		opt.Quality = defaultQuality
	}
	if opt.ThumbQuality < 1 || opt.ThumbQuality > 100 {
		opt.ThumbQuality = defaultThumbQuality
	}

	img, err := LoadImage(c, formField)
	if err != nil {
		return nil, "", err
	}
	if opt.Fill {
		img.ResizeFill(opt.Width, opt.Height)
	} else {
		img.ResizeLimit(opt.Width, opt.Height)
	}
	thumb := img.Duplicate()
	thumb.ResizeLimit(opt.ThumbWidth, opt.ThumbHeight)

	b, err := img.ToJpeg(opt.Quality)
	if err != nil {
		return nil, "", governor.NewError("Failed to encode image as JPEG", http.StatusInternalServerError, err)
	}
	b2, err := thumb.ToBase64(opt.ThumbQuality)
	if err != nil {
		return nil, "", governor.NewError("Failed to encode thumbnail as JPEG", http.StatusInternalServerError, err)
	}
	return b, b2, nil
}

const (
	// MediaTypeJpeg is the mime type for jpeg images
	MediaTypeJpeg = "image/jpeg"
	// MediaTypePng is the mime type for png images
	MediaTypePng = "image/png"
	// MediaTypeGif is the mime type for gif images
	MediaTypeGif = "image/gif"
)

func LoadImage(c echo.Context, formField string) (Image, error) {
	file, mediaType, _, err := fileloader.LoadOpenFile(c, formField, []string{MediaTypePng, MediaTypeJpeg, MediaTypeGif})
	if err != nil {
		return nil, governor.NewErrorUser("Invalid image file", http.StatusBadRequest, err)
	}
	defer func() {
		err := file.Close()
		if err != nil {
		}
	}()
	var img goimg.Image
	switch mediaType {
	case MediaTypeJpeg:
		if i, err := jpeg.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid JPEG image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	case MediaTypePng:
		if i, err := png.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid PNG image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	case MediaTypeGif:
		if i, err := gif.Decode(file); err != nil {
			return nil, governor.NewErrorUser("Invalid GIF image", http.StatusBadRequest, err)
		} else {
			img = i
		}
	}
	return &imageData{
		img: img,
	}, nil
}

func (i imageData) Duplicate() Image {
	bounds := i.img.Bounds()
	target := goimg.NewNRGBA(bounds)
	draw.Draw(target, target.Bounds(), i.img, bounds.Min, draw.Src)
	return &imageData{
		img: target,
	}
}

func (i *imageData) Resize(width, height int) {
	target := goimg.NewNRGBA(goimg.Rect(0, 0, width, height))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.ApproxBiLinear.Scale(target, target.Bounds(), i.img, i.img.Bounds(), draw.Src, nil)
	i.img = target
}

func dimensionsFit(fromWidth, fromHeight, toWidth, toHeight int) (int, int) {
	// fromRatio < toRatio
	if fromWidth*toHeight < toWidth*fromHeight {
		// height is fit
		return fromWidth * toHeight / fromHeight, toHeight
	} else {
		// width is fit
		return toWidth, fromHeight * toWidth / fromWidth
	}
}

func (i *imageData) ResizeFit(width, height int) {
	s := i.img.Bounds().Size()
	targetWidth, targetHeight := dimensionsFit(s.X, s.Y, width, height)
	i.Resize(targetWidth, targetHeight)
}

func (i *imageData) ResizeLimit(width, height int) {
	s := i.img.Bounds().Size()
	if s.X < width && s.Y < height {
		return
	}
	i.ResizeFit(width, height)
}

func (i *imageData) Crop(bounds goimg.Rectangle) {
	size := bounds.Size()
	target := goimg.NewNRGBA(goimg.Rect(0, 0, size.X, size.Y))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.Draw(target, target.Bounds(), i.img, bounds.Min, draw.Src)
	i.img = target
}

func maxInt(a, b int) int {
	if a < b {
		return b
	}
	return a
}

func dimensionsFill(fromWidth, fromHeight, toWidth, toHeight int) (int, int, int, int) {
	// fromRatio < toRatio
	if fromWidth*toHeight < toWidth*fromHeight {
		// width is fit
		height := toHeight * fromWidth / toWidth
		return fromWidth, height, 0, maxInt((fromHeight-height)/2, 0)
	} else {
		// height is fit
		width := toWidth * fromHeight / toHeight
		return width, fromHeight, maxInt((fromWidth-width)/2, 0), 0
	}
}

func (i *imageData) ResizeFill(width, height int) {
	s := i.img.Bounds().Size()
	targetWidth, targetHeight, offsetX, offsetY := dimensionsFill(s.X, s.Y, width, height)
	target := goimg.NewNRGBA(goimg.Rect(0, 0, width, height))
	draw.Draw(target, target.Bounds(), goimg.Transparent, goimg.ZP, draw.Src)
	draw.ApproxBiLinear.Scale(target, target.Bounds(), i.img, goimg.Rect(offsetX, offsetY, offsetX+targetWidth, offsetY+targetHeight), draw.Src, nil)
	i.img = target
}

func (i *imageData) ToJpeg(quality int) (*bytes.Buffer, error) {
	b := &bytes.Buffer{}
	j := jpeg.Options{
		Quality: quality,
	}
	if err := jpeg.Encode(b, i.img, &j); err != nil {
		return nil, governor.NewError("Failed to encode JPEG image", http.StatusInternalServerError, err)
	}
	return b, nil
}

type PngCompressionOpt int

const (
	PngDefault PngCompressionOpt = 0
	PngNone    PngCompressionOpt = 1
	PngFast    PngCompressionOpt = 2
	PngBest    PngCompressionOpt = 3
)

func compressionOptTranslate(level PngCompressionOpt) png.CompressionLevel {
	switch level {
	case PngDefault:
		return png.DefaultCompression
	case PngNone:
		return png.NoCompression
	case PngFast:
		return png.BestSpeed
	case PngBest:
		return png.BestCompression
	default:
		return png.DefaultCompression
	}
}

func (i *imageData) ToPng(level PngCompressionOpt) (*bytes.Buffer, error) {
	b := &bytes.Buffer{}
	encoder := png.Encoder{
		CompressionLevel: compressionOptTranslate(level),
	}
	if err := encoder.Encode(b, i.img); err != nil {
		return nil, governor.NewError("Failed to encode PNG image", http.StatusInternalServerError, err)
	}
	return b, nil
}

const (
	dataURIPrefixJpeg = "data:image/jpeg;base64,"
)

func (i *imageData) ToBase64(quality int) (string, error) {
	b, err := i.ToJpeg(quality)
	if err != nil {
		return "", err
	}
	return dataURIPrefixJpeg + base64.RawStdEncoding.EncodeToString(b.Bytes()), nil
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"encoding/json"
	"fmt"
	"github.com/google/safehtml"
	"github.com/google/safehtml/template"
	"io"
	"net/http"
)

// DefaultDispatcher is responsible for writing safe responses.
type DefaultDispatcher struct{}

// ContentType returns the Content-Type of a safe response if it's of a
// safe-type and an error otherwise.
func (DefaultDispatcher) ContentType(resp Response) (string, error) {
	switch resp.(type) {
	case safehtml.HTML, *template.Template:
		return "text/html; charset=utf-8", nil
	case JSONResponse:
		return "application/json; charset=utf-8", nil
	default:
		return "", fmt.Errorf("%T is not a safe response type, a Content-Type cannot be provided", resp)
	}
}

// Write writes the response to the Response Writer if it's safe HTML. It
// returns a non-nil error if the response is not safe HTML or if writing the
// response fails.
func (DefaultDispatcher) Write(rw http.ResponseWriter, resp Response) error {
	x, ok := resp.(safehtml.HTML)
	if !ok {
		return fmt.Errorf("%T is not a safe response type and it cannot be written", resp)
	}
	_, err := io.WriteString(rw, x.String())
	return err

}

// WriteJSON serialises and writes a JSON to the underlying http.ResponseWriter.
// If the provided response is not valid JSON or writing the response fails, the
// method will return an error.
func (DefaultDispatcher) WriteJSON(rw http.ResponseWriter, resp JSONResponse) error {
	io.WriteString(rw, ")]}',\n") // Break parsing of JavaScript in order to prevent XSSI.
	return json.NewEncoder(rw).Encode(resp.Data)
}

// ExecuteTemplate applies the parsed template to the provided data object, if
// the template is a safe HTML template, writing the output to the  http.
// ResponseWriter. If the funcMap is non-nil, its elements override the
// existing names to functions mappings in the template. An attempt to define a
// new name to function mapping that is not already in the template will result
// in a panic. The template, data object and funcMap are contained in the
// TemplateResponse.
//
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the Response Writer.
func (DefaultDispatcher) ExecuteTemplate(rw http.ResponseWriter, resp TemplateResponse) error {
	t := *resp.Template
	x, ok := t.(*template.Template)
	if !ok {
		return fmt.Errorf("%T is not a safe template and it cannot be parsed and written", resp.Template)
	}
	if len(resp.FuncMap) == 0 {
		return x.Execute(rw, resp.Data)
	}
	cloned, err := x.Clone()
	if err != nil {
		return err
	}
	return cloned.Funcs(resp.FuncMap).Execute(rw, resp.Data)
}
<commit_msg>Remove token about unexported fields of the Template Response<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"encoding/json"
	"fmt"
	"github.com/google/safehtml"
	"github.com/google/safehtml/template"
	"io"
	"net/http"
)

// DefaultDispatcher is responsible for writing safe responses.
type DefaultDispatcher struct{}

// ContentType returns the Content-Type of a safe response if it's of a
// safe-type and an error otherwise.
func (DefaultDispatcher) ContentType(resp Response) (string, error) {
	switch resp.(type) {
	case safehtml.HTML, *template.Template:
		return "text/html; charset=utf-8", nil
	case JSONResponse:
		return "application/json; charset=utf-8", nil
	default:
		return "", fmt.Errorf("%T is not a safe response type, a Content-Type cannot be provided", resp)
	}
}

// Write writes the response to the Response Writer if it's safe HTML. It
// returns a non-nil error if the response is not safe HTML or if writing the
// response fails.
func (DefaultDispatcher) Write(rw http.ResponseWriter, resp Response) error {
	x, ok := resp.(safehtml.HTML)
	if !ok {
		return fmt.Errorf("%T is not a safe response type and it cannot be written", resp)
	}
	_, err := io.WriteString(rw, x.String())
	return err

}

// WriteJSON serialises and writes a JSON to the underlying http.ResponseWriter.
// If the provided response is not valid JSON or writing the response fails, the
// method will return an error.
func (DefaultDispatcher) WriteJSON(rw http.ResponseWriter, resp JSONResponse) error {
	io.WriteString(rw, ")]}',\n") // Break parsing of JavaScript in order to prevent XSSI.
	return json.NewEncoder(rw).Encode(resp.Data)
}

// ExecuteTemplate applies the parsed template to the provided data object, if
// the template is a safe HTML template, writing the output to the  http.
// ResponseWriter. If the funcMap is non-nil, its elements override the
// existing names to functions mappings in the template. An attempt to define a
// new name to function mapping that is not already in the template will result
// in a panic.
//
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the Response Writer.
func (DefaultDispatcher) ExecuteTemplate(rw http.ResponseWriter, resp TemplateResponse) error {
	t := *resp.Template
	x, ok := t.(*template.Template)
	if !ok {
		return fmt.Errorf("%T is not a safe template and it cannot be parsed and written", resp.Template)
	}
	if len(resp.FuncMap) == 0 {
		return x.Execute(rw, resp.Data)
	}
	cloned, err := x.Clone()
	if err != nil {
		return err
	}
	return cloned.Funcs(resp.FuncMap).Execute(rw, resp.Data)
}
<|endoftext|>


<commit_before>package apiactress

import (
	"encoding/json"
	"io"
	"net/url"
	"os"

	behavior "github.com/ikeikeikeike/gopkg/net/http"
)

const EndPoint = "http://apiactress.appspot.com/api"

var Kunrei = []string{
	"a", "i", "u", "e", "o",
	"ka", "ki", "ku", "ke", "ko",
	"sa", "si", "su", "se", "so",
	"ta", "ti", "tu", "te", "to",
	"na", "ni", "nu", "ne", "no",
	"ha", "hi", "hu", "he", "ho",
	"ma", "mi", "mu", "me", "mo",
	"ya", "yu", "yo",
	"ra", "ri", "ru", "re", "ro",
	"wa",
}

func tee(r io.Reader, debug bool) io.Reader {
	if !debug {
		return r
	}
	return io.TeeReader(r, os.Stdout)
}

type Client struct {
	*behavior.UserBehavior
	Debug bool
}

func NewClient() *Client {
	return &Client{
		UserBehavior: behavior.NewUserBehavior(),
		Debug:        false,
	}
}

type Actress struct {
	Id    int64  `json:"id"`
	Name  string `json:"name"`
	Gyou  string `json:"gyou"`
	Thumb string `json:"thumb"`
	Yomi  string `json:"yomi"`
	Oto   string `json:"oto"`
}

type ApiActress struct {
	Count     int       `json:"count"`
	Actresses []Actress `json:"Actresses"`
}

func (c *Client) Fetch(prefix string) (*ApiActress, error) {
	res, err := c.Get(EndPoint + "/1/getdata/" + url.QueryEscape(prefix))
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()

	r := new(ApiActress)
	err = json.NewDecoder(tee(res.Body, c.Debug)).Decode(&r)
	if err != nil {
		return nil, err
	}

	return r, nil
}

/*
	[Deplicated] Server is poverty.
*/
func (c *Client) FetchAll() []*ApiActress {
	var all []*ApiActress
	for _, g := range Kunrei {
		if r, err := c.Fetch(g); err != nil {
			continue
		} else {
			all = append(all, r)
		}
	}

	return all
}

/*
	[Deplicated] Server is poverty.
*/
func AsyncFetchAll() {}
<commit_msg>refactoring a deplicate method<commit_after>package apiactress

import (
	"encoding/json"
	"io"
	"net/url"
	"os"

	behavior "github.com/ikeikeikeike/gopkg/net/http"
)

const EndPoint = "http://apiactress.appspot.com/api"

var Kunrei = []string{
	"a", "i", "u", "e", "o",
	"ka", "ki", "ku", "ke", "ko",
	"sa", "si", "su", "se", "so",
	"ta", "ti", "tu", "te", "to",
	"na", "ni", "nu", "ne", "no",
	"ha", "hi", "hu", "he", "ho",
	"ma", "mi", "mu", "me", "mo",
	"ya", "yu", "yo",
	"ra", "ri", "ru", "re", "ro",
	"wa",
}

func tee(r io.Reader, debug bool) io.Reader {
	if !debug {
		return r
	}
	return io.TeeReader(r, os.Stdout)
}

type Client struct {
	*behavior.UserBehavior
	Debug bool
}

func NewClient() *Client {
	return &Client{
		UserBehavior: behavior.NewUserBehavior(),
		Debug:        false,
	}
}

type Actress struct {
	Id    int64  `json:"id"`
	Name  string `json:"name"`
	Gyou  string `json:"gyou"`
	Thumb string `json:"thumb"`
	Yomi  string `json:"yomi"`
	Oto   string `json:"oto"`
}

type ApiActress struct {
	Count     int       `json:"count"`
	Actresses []Actress `json:"Actresses"`
}

func (c *Client) Fetch(prefix string) (*ApiActress, error) {
	res, err := c.Get(EndPoint + "/1/getdata/" + url.QueryEscape(prefix))
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()

	r := new(ApiActress)
	err = json.NewDecoder(tee(res.Body, c.Debug)).Decode(&r)
	if err != nil {
		return nil, err
	}

	return r, nil
}

/*
	[Deplicated] Server is poverty.
*/
func (c *Client) FetchAll() []*ApiActress {
	var all []*ApiActress
	for _, g := range Kunrei {
		if r, err := c.Fetch(g); err == nil {
			all = append(all, r)
		}
	}

	return all
}

/*
	[Deplicated] Server is poverty.
*/
func AsyncFetchAll() {}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/juju/errors"
	"github.com/lxc/lxd/shared"
)

// TODO(ericsnow) We probably need to address some of the things that
// get handled in container/lxc/clonetemplate.go.

func (client *Client) addInstance(spec InstanceSpec) error {
	// TODO(ericsnow) Default to spec.ImageRemote.
	imageRemote := ""
	//remote := client.remote
	//remote := spec.ImageRemote
	if imageRemote == "" {
		imageRemote = client.remote
	}
	imageAlias := "ubuntu" // TODO(ericsnow) Do not hard-code.
	//imageAlias := spec.Image
	var profiles *[]string
	if len(spec.Profiles) > 0 {
		profiles = &spec.Profiles
	}

	// TODO(ericsnow) Copy the image first?

	resp, err := client.raw.Init(spec.Name, imageRemote, imageAlias, profiles, spec.Ephemeral)
	if err != nil {
		return errors.Trace(err)
	}

	// Init is an async operation, since the tar -xvf (or whatever) might
	// take a while; the result is an LXD operation id, which we can just
	// wait on until it is finished.
	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	if err := client.initInstanceConfig(spec); err != nil {
		if err := client.removeInstance(spec.Name); err != nil {
			logger.Errorf("could not remove container %q after configuring it failed", spec.Name)
		}
		return errors.Trace(err)
	}

	// TODO(ericsnow) Only do this if it's a state server...
	if err := client.exposeHostAPI(spec); err != nil {
		if err := client.removeInstance(spec.Name); err != nil {
			logger.Errorf("could not remove container %q after exposing the API sock failed", spec.Name)
		}
		return errors.Trace(err)
	}

	return nil
}

func (client *Client) initInstanceConfig(spec InstanceSpec) error {
	config := spec.config()
	for key, value := range config {
		err := client.raw.SetContainerConfig(spec.Name, key, value)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

func (client *Client) exposeHostAPI(spec InstanceSpec) error {
	// lxc config device add juju-container lxdsock disk \
	// source=/var/lib/lxd/unix.socket path=var/lib/lxd/unix.socket
	const apiDevName = "lxdsock"
	const devType = "disk"
	const filename = "/var/lib/lxd/unix.socket"
	props := []string{
		// TODO(ericsnow) hard-coded, unix-centric...
		"source=/var/lib/lxd/unix.socket",
		"path=var/lib/lxd/unix.socket",
	}
	resp, err := client.raw.ContainerDeviceAdd(spec.Name, apiDevName, devType, props)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

type execFailure struct {
	cmd    string
	code   int
	stderr string
}

// Error returns the string representation of the error.
func (err execFailure) Error() string {
	return fmt.Sprintf("got non-zero code from %q: (%d) %s", err.cmd, err.code, err.stderr)
}

func (client *Client) exec(spec InstanceSpec, cmd []string) error {
	var env map[string]string

	stdin, stdout, stderr, err := ioFiles()
	if err != nil {
		return errors.Trace(err)
	}

	cmdStr := strings.Join(cmd, " ")
	fmt.Println("running", cmdStr)

	rc, err := client.raw.Exec(spec.Name, cmd, env, stdin, stdout, stderr)
	if err != nil {
		return errors.Trace(err)
	} else if rc != 0 {
		msg := "<reason unknown>"
		if _, err := stdout.Seek(0, 0); err == nil {
			data, err := ioutil.ReadAll(stdout)
			if err == nil {
				msg = string(data)
			}
		}
		err := &execFailure{
			cmd:    cmdStr,
			code:   rc,
			stderr: msg,
		}
		return errors.Trace(err)
	}

	return nil
}

// TODO(ericsnow) We *should* be able to use bytes.Buffer instead...
func ioFiles() (*os.File, *os.File, *os.File, error) {
	infile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}

	outfile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}

	// We combine stdout and stderr...
	return infile, outfile, outfile, nil
}

func (client *Client) chmod(spec InstanceSpec, filename string, mode os.FileMode) error {
	cmd := []string{
		"/bin/chmod",
		fmt.Sprintf("%s", mode),
		filename,
	}

	if err := client.exec(spec, cmd); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func (client *Client) startInstance(spec InstanceSpec) error {
	timeout := -1
	force := false
	resp, err := client.raw.Action(spec.Name, shared.Start, timeout, force)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

func (client *Client) fixSockfile(spec InstanceSpec) error {
	const filename = "/var/lib/lxd/unix.socket"

	//info, err := os.Stat(filename)
	//if err != nil {
	//	return nil, errors.Trace(err)
	//}
	//gid := info.Sys().(*syscall.Stat_t).Gid

	//cmd := []string{
	//	"/usr/sbin/groupadd",
	//	fmt.Sprintf("--gid=%d", gid),
	//	"lxd",
	//}
	//if err := client.exec(spec, cmd); err != nil {
	//	return errors.Trace(err)
	//}

	//cmd = []string{
	//	"/usr/sbin/usermod",
	//	"-a",
	//	"-G", "lxd",
	//	"root",
	//}
	//if err := client.exec(spec, cmd); err != nil {
	//	return errors.Trace(err)
	//}

	// TODO(ericsnow) Instead of modifying the socket file, add the
	// "lxd" group, ensure the GID matches the one on the host, and add
	// the root user to that group.

	// TODO(ericsnow) For now, ensure that your local unix.socket is 0666...
	//if err := client.chmod(spec, filename, 0666); err != nil {
	//	fmt.Println("---- ", err)
	//	//return errors.Trace(err)
	//}

	return nil
}

// AddInstance creates a new instance based on the spec's data and
// returns it. The instance will be created using the client.
func (client *Client) AddInstance(spec InstanceSpec) (*Instance, error) {
	if err := client.addInstance(spec); err != nil {
		return nil, errors.Trace(err)
	}

	if err := client.startInstance(spec); err != nil {
		if err := client.removeInstance(spec.Name); err != nil {
			logger.Errorf("could not remove container %q after starting it failed", spec.Name)
		}
		return nil, errors.Trace(err)
	}

	// TODO(ericsnow) This is a hack tied to exposeHostAPI().
	if err := client.fixSockfile(spec); err != nil {
		return nil, errors.Trace(err)
	}

	inst, err := client.Instance(spec.Name)
	if err != nil {
		return nil, errors.Trace(err)
	}
	inst.spec = &spec

	return inst, nil
}

// Instance gets the up-to-date info about the given instance
// and returns it.
func (client *Client) Instance(name string) (*Instance, error) {
	info, err := client.raw.ContainerStatus(name)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst := newInstance(info, nil)
	return inst, nil
}

// Instances sends a request to the API for a list of all instances
// (in the Client's namespace) for which the name starts with the
// provided prefix. The result is also limited to those instances with
// one of the specified statuses (if any).
func (client *Client) Instances(prefix string, statuses ...string) ([]Instance, error) {
	infos, err := client.raw.ListContainers()
	if err != nil {
		return nil, errors.Trace(err)
	}

	var insts []Instance
	for _, info := range infos {
		name := info.State.Name
		if prefix != "" && !strings.HasPrefix(name, prefix) {
			continue
		}
		if len(statuses) > 0 && !checkStatus(info, statuses) {
			continue
		}

		inst := newInstance(&info.State, nil)
		insts = append(insts, *inst)
	}
	return insts, nil
}

func checkStatus(info shared.ContainerInfo, statuses []string) bool {
	for _, status := range statuses {
		statusCode := allStatuses[status]
		if info.State.Status.StatusCode == statusCode {
			return true
		}
	}
	return false
}

// removeInstance sends a request to the API to remove the instance
// with the provided ID. The call blocks until the instance is removed
// (or the request fails).
func (client *Client) removeInstance(name string) error {
	info, err := client.raw.ContainerStatus(name)
	if err != nil {
		return errors.Trace(err)
	}

	//if info.Status.StatusCode != 0 && info.Status.StatusCode != shared.Stopped {
	if info.Status.StatusCode != shared.Stopped {
		timeout := -1
		force := true
		resp, err := client.raw.Action(name, shared.Stop, timeout, force)
		if err != nil {
			return errors.Trace(err)
		}

		if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
			// TODO(ericsnow) Handle different failures (from the async
			// operation) differently?
			return errors.Trace(err)
		}
	}

	resp, err := client.raw.Delete(name)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

// RemoveInstances sends a request to the API to terminate all
// instances (in the Client's namespace) that match one of the
// provided IDs. If a prefix is provided, only IDs that start with the
// prefix will be considered. The call blocks until all the instances
// are removed or the request fails.
func (client *Client) RemoveInstances(prefix string, names ...string) error {
	if len(names) == 0 {
		return nil
	}

	instances, err := client.Instances(prefix)
	if err != nil {
		return errors.Annotatef(err, "while removing instances %v", names)
	}

	var failed []string
	for _, name := range names {
		if !checkInstanceName(name, instances) {
			// We ignore unknown instance names.
			continue
		}

		if err := client.removeInstance(name); err != nil {
			failed = append(failed, name)
			logger.Errorf("while removing instance %q: %v", name, err)
		}
	}
	if len(failed) != 0 {
		return errors.Errorf("some instance removals failed: %v", failed)
	}
	return nil
}

func checkInstanceName(name string, instances []Instance) bool {
	for _, inst := range instances {
		if inst.Name == name {
			return true
		}
	}
	return false
}
<commit_msg>Only call exposeHostAPI if using the Local remote.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/juju/errors"
	"github.com/lxc/lxd/shared"
)

// TODO(ericsnow) We probably need to address some of the things that
// get handled in container/lxc/clonetemplate.go.

func (client *Client) addInstance(spec InstanceSpec) error {
	// TODO(ericsnow) Default to spec.ImageRemote.
	imageRemote := ""
	//remote := client.remote
	//remote := spec.ImageRemote
	if imageRemote == "" {
		imageRemote = client.remote
	}
	imageAlias := "ubuntu" // TODO(ericsnow) Do not hard-code.
	//imageAlias := spec.Image
	var profiles *[]string
	if len(spec.Profiles) > 0 {
		profiles = &spec.Profiles
	}

	// TODO(ericsnow) Copy the image first?

	resp, err := client.raw.Init(spec.Name, imageRemote, imageAlias, profiles, spec.Ephemeral)
	if err != nil {
		return errors.Trace(err)
	}

	// Init is an async operation, since the tar -xvf (or whatever) might
	// take a while; the result is an LXD operation id, which we can just
	// wait on until it is finished.
	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	if err := client.initInstanceConfig(spec); err != nil {
		if err := client.removeInstance(spec.Name); err != nil {
			logger.Errorf("could not remove container %q after configuring it failed", spec.Name)
		}
		return errors.Trace(err)
	}

	if client.remote == Local.ID() {
		// TODO(ericsnow) Only do this if it's a state server...
		if err := client.exposeHostAPI(spec); err != nil {
			if err := client.removeInstance(spec.Name); err != nil {
				logger.Errorf("could not remove container %q after exposing the API sock failed", spec.Name)
			}
			return errors.Trace(err)
		}
	}

	return nil
}

func (client *Client) initInstanceConfig(spec InstanceSpec) error {
	config := spec.config()
	for key, value := range config {
		err := client.raw.SetContainerConfig(spec.Name, key, value)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

func (client *Client) exposeHostAPI(spec InstanceSpec) error {
	// lxc config device add juju-container lxdsock disk \
	// source=/var/lib/lxd/unix.socket path=var/lib/lxd/unix.socket
	const apiDevName = "lxdsock"
	const devType = "disk"
	const filename = "/var/lib/lxd/unix.socket"
	props := []string{
		// TODO(ericsnow) hard-coded, unix-centric...
		"source=/var/lib/lxd/unix.socket",
		"path=var/lib/lxd/unix.socket",
	}
	resp, err := client.raw.ContainerDeviceAdd(spec.Name, apiDevName, devType, props)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

type execFailure struct {
	cmd    string
	code   int
	stderr string
}

// Error returns the string representation of the error.
func (err execFailure) Error() string {
	return fmt.Sprintf("got non-zero code from %q: (%d) %s", err.cmd, err.code, err.stderr)
}

func (client *Client) exec(spec InstanceSpec, cmd []string) error {
	var env map[string]string

	stdin, stdout, stderr, err := ioFiles()
	if err != nil {
		return errors.Trace(err)
	}

	cmdStr := strings.Join(cmd, " ")
	fmt.Println("running", cmdStr)

	rc, err := client.raw.Exec(spec.Name, cmd, env, stdin, stdout, stderr)
	if err != nil {
		return errors.Trace(err)
	} else if rc != 0 {
		msg := "<reason unknown>"
		if _, err := stdout.Seek(0, 0); err == nil {
			data, err := ioutil.ReadAll(stdout)
			if err == nil {
				msg = string(data)
			}
		}
		err := &execFailure{
			cmd:    cmdStr,
			code:   rc,
			stderr: msg,
		}
		return errors.Trace(err)
	}

	return nil
}

// TODO(ericsnow) We *should* be able to use bytes.Buffer instead...
func ioFiles() (*os.File, *os.File, *os.File, error) {
	infile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}

	outfile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}

	// We combine stdout and stderr...
	return infile, outfile, outfile, nil
}

func (client *Client) chmod(spec InstanceSpec, filename string, mode os.FileMode) error {
	cmd := []string{
		"/bin/chmod",
		fmt.Sprintf("%s", mode),
		filename,
	}

	if err := client.exec(spec, cmd); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func (client *Client) startInstance(spec InstanceSpec) error {
	timeout := -1
	force := false
	resp, err := client.raw.Action(spec.Name, shared.Start, timeout, force)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

func (client *Client) fixSockfile(spec InstanceSpec) error {
	const filename = "/var/lib/lxd/unix.socket"

	//info, err := os.Stat(filename)
	//if err != nil {
	//	return nil, errors.Trace(err)
	//}
	//gid := info.Sys().(*syscall.Stat_t).Gid

	//cmd := []string{
	//	"/usr/sbin/groupadd",
	//	fmt.Sprintf("--gid=%d", gid),
	//	"lxd",
	//}
	//if err := client.exec(spec, cmd); err != nil {
	//	return errors.Trace(err)
	//}

	//cmd = []string{
	//	"/usr/sbin/usermod",
	//	"-a",
	//	"-G", "lxd",
	//	"root",
	//}
	//if err := client.exec(spec, cmd); err != nil {
	//	return errors.Trace(err)
	//}

	// TODO(ericsnow) Instead of modifying the socket file, add the
	// "lxd" group, ensure the GID matches the one on the host, and add
	// the root user to that group.

	// TODO(ericsnow) For now, ensure that your local unix.socket is 0666...
	//if err := client.chmod(spec, filename, 0666); err != nil {
	//	fmt.Println("---- ", err)
	//	//return errors.Trace(err)
	//}

	return nil
}

// AddInstance creates a new instance based on the spec's data and
// returns it. The instance will be created using the client.
func (client *Client) AddInstance(spec InstanceSpec) (*Instance, error) {
	if err := client.addInstance(spec); err != nil {
		return nil, errors.Trace(err)
	}

	if err := client.startInstance(spec); err != nil {
		if err := client.removeInstance(spec.Name); err != nil {
			logger.Errorf("could not remove container %q after starting it failed", spec.Name)
		}
		return nil, errors.Trace(err)
	}

	// TODO(ericsnow) This is a hack tied to exposeHostAPI().
	if err := client.fixSockfile(spec); err != nil {
		return nil, errors.Trace(err)
	}

	inst, err := client.Instance(spec.Name)
	if err != nil {
		return nil, errors.Trace(err)
	}
	inst.spec = &spec

	return inst, nil
}

// Instance gets the up-to-date info about the given instance
// and returns it.
func (client *Client) Instance(name string) (*Instance, error) {
	info, err := client.raw.ContainerStatus(name)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst := newInstance(info, nil)
	return inst, nil
}

// Instances sends a request to the API for a list of all instances
// (in the Client's namespace) for which the name starts with the
// provided prefix. The result is also limited to those instances with
// one of the specified statuses (if any).
func (client *Client) Instances(prefix string, statuses ...string) ([]Instance, error) {
	infos, err := client.raw.ListContainers()
	if err != nil {
		return nil, errors.Trace(err)
	}

	var insts []Instance
	for _, info := range infos {
		name := info.State.Name
		if prefix != "" && !strings.HasPrefix(name, prefix) {
			continue
		}
		if len(statuses) > 0 && !checkStatus(info, statuses) {
			continue
		}

		inst := newInstance(&info.State, nil)
		insts = append(insts, *inst)
	}
	return insts, nil
}

func checkStatus(info shared.ContainerInfo, statuses []string) bool {
	for _, status := range statuses {
		statusCode := allStatuses[status]
		if info.State.Status.StatusCode == statusCode {
			return true
		}
	}
	return false
}

// removeInstance sends a request to the API to remove the instance
// with the provided ID. The call blocks until the instance is removed
// (or the request fails).
func (client *Client) removeInstance(name string) error {
	info, err := client.raw.ContainerStatus(name)
	if err != nil {
		return errors.Trace(err)
	}

	//if info.Status.StatusCode != 0 && info.Status.StatusCode != shared.Stopped {
	if info.Status.StatusCode != shared.Stopped {
		timeout := -1
		force := true
		resp, err := client.raw.Action(name, shared.Stop, timeout, force)
		if err != nil {
			return errors.Trace(err)
		}

		if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
			// TODO(ericsnow) Handle different failures (from the async
			// operation) differently?
			return errors.Trace(err)
		}
	}

	resp, err := client.raw.Delete(name)
	if err != nil {
		return errors.Trace(err)
	}

	if err := client.raw.WaitForSuccess(resp.Operation); err != nil {
		// TODO(ericsnow) Handle different failures (from the async
		// operation) differently?
		return errors.Trace(err)
	}

	return nil
}

// RemoveInstances sends a request to the API to terminate all
// instances (in the Client's namespace) that match one of the
// provided IDs. If a prefix is provided, only IDs that start with the
// prefix will be considered. The call blocks until all the instances
// are removed or the request fails.
func (client *Client) RemoveInstances(prefix string, names ...string) error {
	if len(names) == 0 {
		return nil
	}

	instances, err := client.Instances(prefix)
	if err != nil {
		return errors.Annotatef(err, "while removing instances %v", names)
	}

	var failed []string
	for _, name := range names {
		if !checkInstanceName(name, instances) {
			// We ignore unknown instance names.
			continue
		}

		if err := client.removeInstance(name); err != nil {
			failed = append(failed, name)
			logger.Errorf("while removing instance %q: %v", name, err)
		}
	}
	if len(failed) != 0 {
		return errors.Errorf("some instance removals failed: %v", failed)
	}
	return nil
}

func checkInstanceName(name string, instances []Instance) bool {
	for _, inst := range instances {
		if inst.Name == name {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppdump

import (
	"fmt"
	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/measure"
	"github.com/ligato/vpp-agent/idxvpp"
	acl_api "github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/bin_api/acl"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/model/acl"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/vppcalls"
	"net"
	"time"
)

// DumpInterfaceAcls finds interface in VPP and returns its ACL configuration
func DumpInterfaceAcls(log logging.Logger, swIndex uint32, vppChannel *govppapi.Channel,
	timeLog measure.StopWatchEntry) (acl.AccessLists, error) {

	log.Info("DumpInterfaceAcls")
	// ACLInterfaceListDump time measurement
	alAcls := acl.AccessLists{
		Acl: []*acl.AccessLists_Acl{},
	}

	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	res, err := vppcalls.DumpInterface(swIndex, vppChannel, timeLog)
	log.Infof("Res: %+v\n", res)
	if err != nil {
		return alAcls, err
	}

	if res.SwIfIndex != swIndex {
		return alAcls, fmt.Errorf(fmt.Sprintf("Returned interface index %d does not match request",
			res.SwIfIndex))
	}

	for aidx := range res.Acls {
		ipAcl, err := getIPACLDetails(vppChannel, aidx)
		if err != nil {
			log.Error(err)
		} else {
			alAcls.Acl = append(alAcls.Acl, ipAcl)
		}
	}
	return alAcls, nil
}

// DumpIPAcl test function
func DumpIPAcl(log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// ACLDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.ACLDump{}
	req.ACLIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.ACLDetails{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		log.Infof("ACL index: %v, rule count: %v, tag: %v", msg.ACLIndex, msg.Count, string(msg.Tag[:]))

	}
	return nil
}

// DumpMacIPAcl test function
func DumpMacIPAcl(log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// MacipACLDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.MacipACLDump{}
	req.ACLIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.MacipACLDump{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		log.Info(msg.ACLIndex)
	}
	return nil
}

// DumpInterfaces test function
func DumpInterfaces(swIndexes idxvpp.NameToIdxRW, log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// ACLInterfaceListDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.ACLInterfaceListDump{}
	req.SwIfIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.ACLInterfaceListDetails{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		name, _, found := swIndexes.LookupName(msg.SwIfIndex)
		if !found {
			continue
		}
		log.Infof("Interface %v is in %v acl in direction %v and applied in %v",
			name, msg.Count, msg.NInput, msg.Acls)
	}
	return nil
}

// getIPACLDetails gets details for a given IP ACL from VPP and translates
// them from the binary VPP API format into the ACL Plugin's NB format.
func getIPACLDetails(vppChannel *govppapi.Channel, idx int) (*acl.AccessLists_Acl, error) {
	req := &acl_api.ACLDump{}
	req.ACLIndex = uint32(idx)

	reply := &acl_api.ACLDetails{}
	err := vppChannel.SendRequest(req).ReceiveReply(reply)
	if err != nil {
		return nil, err
	}

	rules := []*acl.AccessLists_Acl_Rule{}
	for _, r := range reply.R {
		rule := acl.AccessLists_Acl_Rule{}

		matches := acl.AccessLists_Acl_Rule_Matches{
			IpRule: getIPRule(r),
		}

		actions := acl.AccessLists_Acl_Rule_Actions{}
		if r.IsPermit > 0 {
			actions.AclAction = acl.AclAction_PERMIT
		} else {
			actions.AclAction = acl.AclAction_DENY
		}

		rule.Matches = &matches
		rule.Actions = &actions
		rules = append(rules, &rule)
	}

	return &acl.AccessLists_Acl{Rules: rules, AclName: string(reply.Tag)}, nil
}

// getIPRule translates an IP rule from the binary VPP API format into the
// ACL Plugin's NB format
func getIPRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule {
	ipRule := acl.AccessLists_Acl_Rule_Matches_IpRule{}

	saddr := net.IPNet{IP: r.SrcIPAddr, Mask: []byte{}}
	daddr := net.IPNet{IP: r.DstIPAddr, Mask: []byte{}}
	ip := acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{
		SourceNetwork:      fmt.Sprintf("%s/%d", saddr.String(), r.SrcIPPrefixLen),
		DestinationNetwork: fmt.Sprintf("%s/%d", daddr.String(), r.DstIPPrefixLen),
	}
	ipRule.Ip = &ip

	switch r.Proto {
	case vppcalls.TCPProto:
		ipRule.Tcp = getTCPMatchRule(r)
		break
	case vppcalls.UDPProto:
		ipRule.Udp = getUDPMatchRule(r)
		break
	case vppcalls.Icmpv4Proto:
	case vppcalls.Icmpv6Proto:
		ipRule.Icmp = getIcmpMatchRule(r)
		break
	default:
		ipRule.Other = &acl.AccessLists_Acl_Rule_Matches_IpRule_Other {
			Protocol: uint32(r.Proto),
		}
	}
	return &ipRule
}

// getTCPMatchRule translates a TCP match rule from the binary VPP API format
// into the ACL Plugin's NB format
func getTCPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp {
	dstPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_DestinationPortRange{
		LowerPort: uint32(r.DstportOrIcmpcodeFirst),
		UpperPort: uint32(r.DstportOrIcmpcodeLast),
	}
	srcPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_SourcePortRange{
		LowerPort: uint32(r.SrcportOrIcmptypeFirst),
		UpperPort: uint32(r.SrcportOrIcmptypeLast),
	}
	tcp := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp{
		DestinationPortRange: &dstPortRange,
		SourcePortRange: &srcPortRange,
		TcpFlagsMask: uint32(r.TCPFlagsMask),
		TcpFlagsValue: uint32(r.TCPFlagsValue),
	}
	return &tcp
}

// getUDPMatchRule translates a UDP match rule from the binary VPP API format
// into the ACL Plugin's NB format
func getUDPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Udp {
	dstPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_DestinationPortRange{
		LowerPort: uint32(r.DstportOrIcmpcodeFirst),
		UpperPort: uint32(r.DstportOrIcmpcodeLast),
	}
	srcPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_SourcePortRange{
		LowerPort: uint32(r.SrcportOrIcmptypeFirst),
		UpperPort: uint32(r.SrcportOrIcmptypeLast),
	}
	udp := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp{
		DestinationPortRange: &dstPortRange,
		SourcePortRange: &srcPortRange,
	}
	return &udp
}

// getIcmpMatchRule translates an ICMP match rule from the binary VPP API
// format into the ACL Plugin's NB format
func getIcmpMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp {
	codeRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp_IcmpCodeRange{}
	typeRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp_IcmpTypeRange{
	}

	icmp := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp{
		Icmpv6: r.IsIpv6 > 0,
		IcmpCodeRange: &codeRange,
		IcmpTypeRange: &typeRange,
	}
	return &icmp
}

<commit_msg>Fixed golint issues<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppdump

import (
	"fmt"
	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/measure"
	"github.com/ligato/vpp-agent/idxvpp"
	acl_api "github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/bin_api/acl"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/model/acl"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/vppcalls"
	"net"
	"time"
)

// DumpInterfaceAcls finds interface in VPP and returns its ACL configuration
func DumpInterfaceAcls(log logging.Logger, swIndex uint32, vppChannel *govppapi.Channel,
	timeLog measure.StopWatchEntry) (acl.AccessLists, error) {

	log.Info("DumpInterfaceAcls")
	// ACLInterfaceListDump time measurement
	alAcls := acl.AccessLists{
		Acl: []*acl.AccessLists_Acl{},
	}

	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	res, err := vppcalls.DumpInterface(swIndex, vppChannel, timeLog)
	log.Infof("Res: %+v\n", res)
	if err != nil {
		return alAcls, err
	}

	if res.SwIfIndex != swIndex {
		return alAcls, fmt.Errorf(fmt.Sprintf("Returned interface index %d does not match request",
			res.SwIfIndex))
	}

	for aidx := range res.Acls {
		ipACL, err := getIPACLDetails(vppChannel, aidx)
		if err != nil {
			log.Error(err)
		} else {
			alAcls.Acl = append(alAcls.Acl, ipACL)
		}
	}
	return alAcls, nil
}

// DumpIPAcl test function
func DumpIPAcl(log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// ACLDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.ACLDump{}
	req.ACLIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.ACLDetails{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		log.Infof("ACL index: %v, rule count: %v, tag: %v", msg.ACLIndex, msg.Count, string(msg.Tag[:]))

	}
	return nil
}

// DumpMacIPAcl test function
func DumpMacIPAcl(log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// MacipACLDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.MacipACLDump{}
	req.ACLIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.MacipACLDump{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		log.Info(msg.ACLIndex)
	}
	return nil
}

// DumpInterfaces test function
func DumpInterfaces(swIndexes idxvpp.NameToIdxRW, log logging.Logger, vppChannel *govppapi.Channel, timeLog measure.StopWatchEntry) error {
	// ACLInterfaceListDump time measurement
	start := time.Now()
	defer func() {
		if timeLog != nil {
			timeLog.LogTimeEntry(time.Since(start))
		}
	}()

	req := &acl_api.ACLInterfaceListDump{}
	req.SwIfIndex = 0xffffffff
	reqContext := vppChannel.SendMultiRequest(req)
	for {
		msg := &acl_api.ACLInterfaceListDetails{}
		stop, err := reqContext.ReceiveReply(msg)
		if err != nil {
			return err
		}
		if stop {
			break
		}
		name, _, found := swIndexes.LookupName(msg.SwIfIndex)
		if !found {
			continue
		}
		log.Infof("Interface %v is in %v acl in direction %v and applied in %v",
			name, msg.Count, msg.NInput, msg.Acls)
	}
	return nil
}

// getIPACLDetails gets details for a given IP ACL from VPP and translates
// them from the binary VPP API format into the ACL Plugin's NB format.
func getIPACLDetails(vppChannel *govppapi.Channel, idx int) (*acl.AccessLists_Acl, error) {
	req := &acl_api.ACLDump{}
	req.ACLIndex = uint32(idx)

	reply := &acl_api.ACLDetails{}
	err := vppChannel.SendRequest(req).ReceiveReply(reply)
	if err != nil {
		return nil, err
	}

	rules := []*acl.AccessLists_Acl_Rule{}
	for _, r := range reply.R {
		rule := acl.AccessLists_Acl_Rule{}

		matches := acl.AccessLists_Acl_Rule_Matches{
			IpRule: getIPRule(r),
		}

		actions := acl.AccessLists_Acl_Rule_Actions{}
		if r.IsPermit > 0 {
			actions.AclAction = acl.AclAction_PERMIT
		} else {
			actions.AclAction = acl.AclAction_DENY
		}

		rule.Matches = &matches
		rule.Actions = &actions
		rules = append(rules, &rule)
	}

	return &acl.AccessLists_Acl{Rules: rules, AclName: string(reply.Tag)}, nil
}

// getIPRule translates an IP rule from the binary VPP API format into the
// ACL Plugin's NB format
func getIPRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule {
	ipRule := acl.AccessLists_Acl_Rule_Matches_IpRule{}

	saddr := net.IPNet{IP: r.SrcIPAddr, Mask: []byte{}}
	daddr := net.IPNet{IP: r.DstIPAddr, Mask: []byte{}}
	ip := acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{
		SourceNetwork:      fmt.Sprintf("%s/%d", saddr.String(), r.SrcIPPrefixLen),
		DestinationNetwork: fmt.Sprintf("%s/%d", daddr.String(), r.DstIPPrefixLen),
	}
	ipRule.Ip = &ip

	switch r.Proto {
	case vppcalls.TCPProto:
		ipRule.Tcp = getTCPMatchRule(r)
		break
	case vppcalls.UDPProto:
		ipRule.Udp = getUDPMatchRule(r)
		break
	case vppcalls.Icmpv4Proto:
	case vppcalls.Icmpv6Proto:
		ipRule.Icmp = getIcmpMatchRule(r)
		break
	default:
		ipRule.Other = &acl.AccessLists_Acl_Rule_Matches_IpRule_Other {
			Protocol: uint32(r.Proto),
		}
	}
	return &ipRule
}

// getTCPMatchRule translates a TCP match rule from the binary VPP API format
// into the ACL Plugin's NB format
func getTCPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp {
	dstPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_DestinationPortRange{
		LowerPort: uint32(r.DstportOrIcmpcodeFirst),
		UpperPort: uint32(r.DstportOrIcmpcodeLast),
	}
	srcPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_SourcePortRange{
		LowerPort: uint32(r.SrcportOrIcmptypeFirst),
		UpperPort: uint32(r.SrcportOrIcmptypeLast),
	}
	tcp := acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp{
		DestinationPortRange: &dstPortRange,
		SourcePortRange: &srcPortRange,
		TcpFlagsMask: uint32(r.TCPFlagsMask),
		TcpFlagsValue: uint32(r.TCPFlagsValue),
	}
	return &tcp
}

// getUDPMatchRule translates a UDP match rule from the binary VPP API format
// into the ACL Plugin's NB format
func getUDPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Udp {
	dstPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_DestinationPortRange{
		LowerPort: uint32(r.DstportOrIcmpcodeFirst),
		UpperPort: uint32(r.DstportOrIcmpcodeLast),
	}
	srcPortRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_SourcePortRange{
		LowerPort: uint32(r.SrcportOrIcmptypeFirst),
		UpperPort: uint32(r.SrcportOrIcmptypeLast),
	}
	udp := acl.AccessLists_Acl_Rule_Matches_IpRule_Udp{
		DestinationPortRange: &dstPortRange,
		SourcePortRange: &srcPortRange,
	}
	return &udp
}

// getIcmpMatchRule translates an ICMP match rule from the binary VPP API
// format into the ACL Plugin's NB format
func getIcmpMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp {
	codeRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp_IcmpCodeRange{}
	typeRange := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp_IcmpTypeRange{
	}

	icmp := acl.AccessLists_Acl_Rule_Matches_IpRule_Icmp{
		Icmpv6: r.IsIpv6 > 0,
		IcmpCodeRange: &codeRange,
		IcmpTypeRange: &typeRange,
	}
	return &icmp
}

<|endoftext|>


<commit_before>package host_agent_consumer

import (
	"bufio"
	"encoding/json"
	"log"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
	"github.com/influxdata/telegraf/proto/metrics"
	zmq "github.com/pebbe/zmq4"
)

type HostAgent struct {
	sync.Mutex

	SubscriberPort int
	CloudAuthUrl string
	CloudUser string
	CloudPassword string
	CloudTenant string
	CloudProvider string

	subscriber *zmq.Socket

	msgs chan []string
	done chan struct{}

	cloudInstances map[string]CloudInstance

	acc telegraf.Accumulator

	prevTime  time.Time
	prevValue int64
	currValue int64
}

type CloudInstances struct {
	Instances []CloudInstance `json:"instances,required"`
}

type CloudInstance struct {
	Id             string   `json:"id,required"`
	Name           string   `json:"name,required"`
}

var sampleConfig = `
  ## host agent subscriber port
  subscriberPort = 40003
  ## cloud Auth URL string
  cloudAuthUrl = ""
  ## cloud user name
  cloudUser = ""
  ## cloud password
  cloudPassword = ""
  ## cloud tenant
  cloudTenant = ""
  ## cloud type
  cloudProvider = ""
`

func (h *HostAgent) SampleConfig() string {
	return sampleConfig
}

func (h *HostAgent) Description() string {
	return "Read metrics from host agents"
}

func (h *HostAgent) Start(acc telegraf.Accumulator) error {
	h.Lock()
	defer h.Unlock()

	h.acc = acc

	h.msgs = make(chan []string)
	h.done = make(chan struct{})

	h.cloudInstances = make(map[string]CloudInstance)

	h.prevTime = time.Now()
	h.prevValue = 0

	h.subscriber, _ = zmq.NewSocket(zmq.SUB)
	h.subscriber.Bind("tcp://*:" + strconv.Itoa(h.SubscriberPort))
	h.subscriber.SetSubscribe("")

	// Initialize Cloud Names
	h.initCloudNames()

	// Start the zmq message subscriber
	go h.subscribe()

	log.Printf("Started the host agent consumer service. Subscribing on *:%d\n", h.SubscriberPort)

	return nil
}

func (h *HostAgent) Stop() {
	h.Lock()
	defer h.Unlock()

	close(h.done)
	log.Printf("Stopping the host agent consumer service\n")
	if err := h.subscriber.Close(); err != nil {
		log.Printf("Error closing host agent consumer service: %s\n", err.Error())
	}
}

func (h *HostAgent) Gather(acc telegraf.Accumulator) error {
	currTime := time.Now()
	diffTime := currTime.Sub(h.prevTime) / time.Second
	h.prevTime = currTime
	diffValue := h.currValue - h.prevValue
	h.prevValue = h.currValue

	if diffTime == 0 {
		return nil
	}

	rate := float64(diffValue) / float64(diffTime)
	log.Printf("Processed %f host agent metrics per second\n", rate)
	return nil
}

// subscribe() reads all incoming messages from the host agents, and parses them into
// influxdb metric points.
func (h *HostAgent) subscribe() {
	go h.processMessages()
	for {
		msg, err := h.subscriber.RecvMessage(0)
		if err != nil {
			break
		} else {
			h.msgs <- msg
		}
	}
}

func (h *HostAgent) processMessages() {
	for {
		select {
		case <-h.done:
			return
		case msg := <-h.msgs:
			go func(msg []string) {
				metricsMsg := &metrics.Metrics{}
				err := proto.Unmarshal([]byte(msg[0]), metricsMsg)
				if err != nil {
					log.Fatal("unmarshaling error: ", err)
				}
				metricsList := metricsMsg.GetMetrics()
				for _, metric := range metricsList {
					values := make(map[string]interface{})
					for _, v := range metric.Values {
						switch v.Value.(type) {
						case *metrics.MetricValue_DoubleValue:
							values[*v.Name] = v.GetDoubleValue()
						case *metrics.MetricValue_Int64Value:
							values[*v.Name] = v.GetInt64Value()
						default:
							panic("unreachable")
						}
					}
					dimensions := make(map[string]string)
					for _, d := range metric.Dimensions {
						dimensions[*d.Name] = *d.Value
						if *metric.Name == "host_proc_metrics" ||
							*metric.Name == "libvirt_domain_metrics" ||
							*metric.Name == "libvirt_domain_block_metrics" ||
							*metric.Name == "libvirt_domain_interface_metrics" {
							if *d.Name == "libvirt_uuid" {
								cloudInstance, ok := h.cloudInstances[*d.Value]
								if ok {
									dimensions["instance_name"] = cloudInstance.Name
								}
							}
						}
					}
					h.acc.AddFields(*metric.Name, values, dimensions, time.Unix(0, *metric.Timestamp))
					h.currValue++
				}
			}(msg)
		}
	}
}

func (h *HostAgent) initCloudNames() {
	cmd := exec.Command("./glimpse",
		"-auth-url", h.CloudAuthUrl,
		"-user", h.CloudUser,
		"-pass", h.CloudPassword,
		"-tenant", h.CloudTenant,
		"-provider", h.CloudProvider,
		"list", "instances")

	cmdReader, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("Error creating StdoutPipe: %s", err.Error())
		return
	}
	// read the data from stdout
	buf := bufio.NewReader(cmdReader)

	err = cmd.Start()
	if err != nil {
		log.Printf("Error starting glimpse: %s", err.Error())
		return
	}

	output, _ := buf.ReadString('\n')

	var instances CloudInstances
	json.Unmarshal([]byte(output), &instances)

	for _, instance := range instances.Instances {
		h.cloudInstances[instance.Id] = instance
	}
}

func init() {
	inputs.Add("host_agent_consumer", func() telegraf.Input {
		return &HostAgent{}
	})
}
<commit_msg>Add support for getting network_name from glimpse for libvirt_domain_interface_metrics<commit_after>package host_agent_consumer

import (
	"bufio"
	"encoding/json"
	"log"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
	"github.com/influxdata/telegraf/proto/metrics"
	zmq "github.com/pebbe/zmq4"
)

type HostAgent struct {
	sync.Mutex

	SubscriberPort int
	CloudAuthUrl   string
	CloudUser      string
	CloudPassword  string
	CloudTenant    string
	CloudProvider  string

	subscriber *zmq.Socket

	msgs chan []string
	done chan struct{}

	cloudInstances    map[string]CloudInstance
	cloudNetworkPorts map[string]CloudNetworkPort

	acc telegraf.Accumulator

	prevTime  time.Time
	prevValue int64
	currValue int64
}

type CloudInstances struct {
	Instances []CloudInstance `json:"instances,required"`
}

type CloudInstance struct {
	Id   string `json:"id,required"`
	Name string `json:"name,required"`
}

type CloudNetworkPorts struct {
	NetworkPorts []CloudNetworkPort `json:"network_ports,required"`
}

type CloudNetworkPort struct {
	MacAddress  string `json:"mac_address,required"`
	NetworkName string `json:"network_name,required"`
}

var sampleConfig = `
  ## host agent subscriber port
  subscriberPort = 40003
  ## cloud Auth URL string
  cloudAuthUrl = ""
  ## cloud user name
  cloudUser = ""
  ## cloud password
  cloudPassword = ""
  ## cloud tenant
  cloudTenant = ""
  ## cloud type
  cloudProvider = ""
`

func (h *HostAgent) SampleConfig() string {
	return sampleConfig
}

func (h *HostAgent) Description() string {
	return "Read metrics from host agents"
}

func (h *HostAgent) Start(acc telegraf.Accumulator) error {
	h.Lock()
	defer h.Unlock()

	h.acc = acc

	h.msgs = make(chan []string)
	h.done = make(chan struct{})

	h.prevTime = time.Now()
	h.prevValue = 0

	h.subscriber, _ = zmq.NewSocket(zmq.SUB)
	h.subscriber.Bind("tcp://*:" + strconv.Itoa(h.SubscriberPort))
	h.subscriber.SetSubscribe("")

	// Initialize Cloud Instances
	h.loadCloudInstances()

	// Initialize Cloud Network Ports
	h.loadCloudNetworkPorts()

	// Start the zmq message subscriber
	go h.subscribe()

	log.Printf("Started the host agent consumer service. Subscribing on *:%d\n", h.SubscriberPort)

	return nil
}

func (h *HostAgent) Stop() {
	h.Lock()
	defer h.Unlock()

	close(h.done)
	log.Printf("Stopping the host agent consumer service\n")
	if err := h.subscriber.Close(); err != nil {
		log.Printf("Error closing host agent consumer service: %s\n", err.Error())
	}
}

func (h *HostAgent) Gather(acc telegraf.Accumulator) error {
	currTime := time.Now()
	diffTime := currTime.Sub(h.prevTime) / time.Second
	h.prevTime = currTime
	diffValue := h.currValue - h.prevValue
	h.prevValue = h.currValue

	if diffTime == 0 {
		return nil
	}

	rate := float64(diffValue) / float64(diffTime)
	log.Printf("Processed %f host agent metrics per second\n", rate)
	return nil
}

// subscribe() reads all incoming messages from the host agents, and parses them into
// influxdb metric points.
func (h *HostAgent) subscribe() {
	go h.processMessages()
	for {
		msg, err := h.subscriber.RecvMessage(0)
		if err != nil {
			break
		} else {
			h.msgs <- msg
		}
	}
}

func (h *HostAgent) processMessages() {
	for {
		select {
		case <-h.done:
			return
		case msg := <-h.msgs:
			go func(msg []string) {
				metricsMsg := &metrics.Metrics{}
				err := proto.Unmarshal([]byte(msg[0]), metricsMsg)
				if err != nil {
					log.Fatal("unmarshaling error: ", err)
				}
				metricsList := metricsMsg.GetMetrics()
				for _, metric := range metricsList {
					values := make(map[string]interface{})
					for _, v := range metric.Values {
						switch v.Value.(type) {
						case *metrics.MetricValue_DoubleValue:
							values[*v.Name] = v.GetDoubleValue()
						case *metrics.MetricValue_Int64Value:
							values[*v.Name] = v.GetInt64Value()
						default:
							panic("unreachable")
						}
					}
					dimensions := make(map[string]string)
					for _, d := range metric.Dimensions {
						dimensions[*d.Name] = *d.Value
						if *metric.Name == "host_proc_metrics" ||
							*metric.Name == "libvirt_domain_metrics" ||
							*metric.Name == "libvirt_domain_block_metrics" ||
							*metric.Name == "libvirt_domain_interface_metrics" {
							if *d.Name == "libvirt_uuid" && len(*d.Value) > 0 {
								cloudInstance, ok := h.cloudInstances[*d.Value]
								if ok {
									dimensions["instance_name"] = cloudInstance.Name
								} else {
									// reload cloud instances - looks like new instance was instantiated
									h.loadCloudInstances()
									cloudInstance, ok := h.cloudInstances[*d.Value]
									if ok {
										dimensions["instance_name"] = cloudInstance.Name
									} else {
										dimensions["instance_name"] = "unknown"
									}
								}
							}
							if *d.Name == "mac_addr" {
								networkPort, ok := h.cloudNetworkPorts[*d.Value]
								if ok {
									dimensions["network_name"] = networkPort.NetworkName
								} else {
									// reload cloud network ports - looks like new network was instantiated
									h.loadCloudNetworkPorts()
									networkPort, ok := h.cloudNetworkPorts[*d.Value]
									if ok {
										dimensions["network_name"] = networkPort.NetworkName
									} else {
										dimensions["network_name"] = "unknown"
									}
								}
							}
						}
					}
					h.acc.AddFields(*metric.Name, values, dimensions, time.Unix(0, *metric.Timestamp))
					h.currValue++
				}
			}(msg)
		}
	}
}

func (h *HostAgent) loadCloudInstances() {
	cmd := exec.Command("./glimpse",
		"-auth-url", h.CloudAuthUrl,
		"-user", h.CloudUser,
		"-pass", h.CloudPassword,
		"-tenant", h.CloudTenant,
		"-provider", h.CloudProvider,
		"list", "instances")

	cmdReader, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("Error creating StdoutPipe for glimpse to list instances: %s", err.Error())
		return
	}
	// read the data from stdout
	buf := bufio.NewReader(cmdReader)

	err = cmd.Start()
	if err != nil {
		log.Printf("Error starting glimpse to list instances: %s", err.Error())
		return
	}

	output, _ := buf.ReadString('\n')

	cmd.Process.Kill()
	cmd.Wait()

	var instances CloudInstances
	json.Unmarshal([]byte(output), &instances)

	h.cloudInstances = make(map[string]CloudInstance)
	for _, instance := range instances.Instances {
		h.cloudInstances[instance.Id] = instance
	}
}

func (h *HostAgent) loadCloudNetworkPorts() {
	cmd := exec.Command("./glimpse",
		"-auth-url", h.CloudAuthUrl,
		"-user", h.CloudUser,
		"-pass", h.CloudPassword,
		"-tenant", h.CloudTenant,
		"-provider", h.CloudProvider,
		"list", "network-ports")

	cmdReader, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("Error creating StdoutPipe for glimpse to list network-ports: %s", err.Error())
		return
	}
	// read the data from stdout
	buf := bufio.NewReader(cmdReader)

	err = cmd.Start()
	if err != nil {
		log.Printf("Error starting glimpse to list network-ports: %s", err.Error())
		return
	}

	output, _ := buf.ReadString('\n')

	cmd.Process.Kill()
	cmd.Wait()

	var networkPorts CloudNetworkPorts
	json.Unmarshal([]byte(output), &networkPorts)

	h.cloudNetworkPorts = make(map[string]CloudNetworkPort)
	for _, networkPort := range networkPorts.NetworkPorts {
		h.cloudNetworkPorts[networkPort.MacAddress] = networkPort
	}
}

func init() {
	inputs.Add("host_agent_consumer", func() telegraf.Input {
		return &HostAgent{}
	})
}
<|endoftext|>


<commit_before>package build

type image struct {
	// default ports the service will run on.
	// for example, 3306 for mysql. Note that a service
	// may expose multiple prots, for example, Riak
	// exposes 8087 and 8089.
	Ports []string

	// tag of the docker image to pull in order
	// to run this service.
	Tag string

	// display name of the image type
	Name string
}

// List of 3rd party services (database, queue, etc) that
// are known to work with this Build utility.
var services = map[string]*image{

	// neo4j
	"neo4j": {
		Ports: []string{"7474"},
		Tag:   "bradrydzewski/neo4j:1.9",
		Name:  "neo4j",
	},
	"neo4j:1.9": {
		Ports: []string{"7474"},
		Tag:   "bradrydzewski/neo4j:1.9",
		Name:  "neo4j",
	},

	// elasticsearch servers
	"elasticsearch": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.90",
		Name:  "elasticsearch",
	},
	"elasticsearch:0.20": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.20",
		Name:  "elasticsearch",
	},
	"elasticsearch:0.90": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.90",
		Name:  "elasticsearch",
	},

	// redis servers
	"redis": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.8",
		Name:  "redis",
	},
	"redis:2.8": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.8",
		Name:  "redis",
	},
	"redis:2.6": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.6",
		Name:  "redis",
	},

	// mysql servers
	"mysql": {
		Tag:   "bradrydzewski/mysql:5.5",
		Ports: []string{"3306"},
		Name:  "mysql",
	},
	"mysql:5.5": {
		Tag:   "bradrydzewski/mysql:5.5",
		Ports: []string{"3306"},
		Name:  "mysql",
	},

	// memcached
	"memcached": {
		Ports: []string{"11211"},
		Tag:   "bradrydzewski/memcached",
		Name:  "memcached",
	},

	// mongodb
	"mongodb": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.4",
		Name:  "mongodb",
	},
	"mongodb:2.4": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.4",
		Name:  "mongodb",
	},
	"mongodb:2.2": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.2",
		Name:  "mongodb",
	},

	// postgres
	"postgres": {
		Ports: []string{"5432"},
		Tag:   "bradrydzewski/postgres:9.1",
		Name:  "postgres",
	},
	"postgres:9.1": {
		Ports: []string{"5432"},
		Tag:   "bradrydzewski/postgres:9.1",
		Name:  "postgres",
	},

	// couchdb
	"couchdb": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.5",
		Name:  "couchdb",
	},
	"couchdb:1.0": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.0",
		Name:  "couchdb",
	},
	"couchdb:1.4": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.4",
		Name:  "couchdb",
	},
	"couchdb:1.5": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.5",
		Name:  "couchdb",
	},

	// rabbitmq
	"rabbitmq": {
		Ports: []string{"5672", "15672"},
		Tag:   "bradrydzewski/rabbitmq:3.2",
		Name:  "rabbitmq",
	},
	"rabbitmq:3.2": {
		Ports: []string{"5672", "15672"},
		Tag:   "bradrydzewski/rabbitmq:3.2",
		Name:  "rabbitmq",
	},

	// experimental images from 3rd parties

	"zookeeper": {
		Ports: []string{"2181"},
		Tag:   "jplock/zookeeper:3.4.5",
		Name:  "zookeeper",
	},

	// cassandra
	"cassandra": {
		Ports: []string{"9042", "7000", "7001", "7199", "9160", "49183"},
		Tag:   "relateiq/cassandra",
		Name:  "cassandra",
	},

	// riak - TESTED
	"riak": {
		Ports: []string{"8087", "8098"},
		Tag:   "guillermo/riak",
		Name:  "riak",
	},
}

// List of official Drone build images.
var builders = map[string]*image{

	// Clojure build images
	"lein": {Tag: "bradrydzewski/lein"},

	// Dart build images
	"dart":        {Tag: "bradrydzewski/dart:stable"},
	"dart_stable": {Tag: "bradrydzewski/dart:stable"},
	"dart_dev":    {Tag: "bradrydzewski/dart:dev"},

	// Erlang build images
	"erlang":       {Tag: "bradrydzewski/erlang:R16B02"},
	"erlangR16B":   {Tag: "bradrydzewski/erlang:R16B"},
	"erlangR16B02": {Tag: "bradrydzewski/erlang:R16B02"},
	"erlangR16B01": {Tag: "bradrydzewski/erlang:R16B01"},

	// GCC build images
	"gcc":    {Tag: "bradrydzewski/gcc:4.6"},
	"gcc4.6": {Tag: "bradrydzewski/gcc:4.6"},
	"gcc4.8": {Tag: "bradrydzewski/gcc:4.8"},

	// Golang build images
	"go":    {Tag: "bradrydzewski/go:1.3"},
	"go1":   {Tag: "bradrydzewski/go:1.0"},
	"go1.1": {Tag: "bradrydzewski/go:1.1"},
	"go1.2": {Tag: "bradrydzewski/go:1.2"},
	"go1.3": {Tag: "bradrydzewski/go:1.3"},

	// Haskell build images
	"haskell":    {Tag: "bradrydzewski/haskell:7.4"},
	"haskell7.4": {Tag: "bradrydzewski/haskell:7.4"},

	// Java build images
	"java":       {Tag: "bradrydzewski/java:openjdk7"},
	"openjdk6":   {Tag: "bradrydzewski/java:openjdk6"},
	"openjdk7":   {Tag: "bradrydzewski/java:openjdk7"},
	"oraclejdk7": {Tag: "bradrydzewski/java:oraclejdk7"},
	"oraclejdk8": {Tag: "bradrydzewski/java:oraclejdk8"},

	// Node build images
	"node":     {Tag: "bradrydzewski/node:0.10"},
	"node0.10": {Tag: "bradrydzewski/node:0.10"},
	"node0.8":  {Tag: "bradrydzewski/node:0.8"},

	// PHP build images
	"php":    {Tag: "bradrydzewski/php:5.5"},
	"php5.5": {Tag: "bradrydzewski/php:5.5"},
	"php5.4": {Tag: "bradrydzewski/php:5.4"},

	// Python build images
	"python":    {Tag: "bradrydzewski/python:2.7"},
	"python2.7": {Tag: "bradrydzewski/python:2.7"},
	"python3.2": {Tag: "bradrydzewski/python:3.2"},
	"python3.3": {Tag: "bradrydzewski/python:3.3"},
	"pypy":      {Tag: "bradrydzewski/python:pypy"},

	// Ruby build images
	"ruby":      {Tag: "bradrydzewski/ruby:2.0.0"},
	"ruby2.0.0": {Tag: "bradrydzewski/ruby:2.0.0"},
	"ruby1.9.3": {Tag: "bradrydzewski/ruby:1.9.3"},

	// Scala build images
	"scala":       {Tag: "bradrydzewski/scala:2.10.3"},
	"scala2.10.3": {Tag: "bradrydzewski/scala:2.10.3"},
	"scala2.9.3":  {Tag: "bradrydzewski/scala:2.9.3"},
}
<commit_msg>shared/build/images.go: add go1.4 tag<commit_after>package build

type image struct {
	// default ports the service will run on.
	// for example, 3306 for mysql. Note that a service
	// may expose multiple prots, for example, Riak
	// exposes 8087 and 8089.
	Ports []string

	// tag of the docker image to pull in order
	// to run this service.
	Tag string

	// display name of the image type
	Name string
}

// List of 3rd party services (database, queue, etc) that
// are known to work with this Build utility.
var services = map[string]*image{

	// neo4j
	"neo4j": {
		Ports: []string{"7474"},
		Tag:   "bradrydzewski/neo4j:1.9",
		Name:  "neo4j",
	},
	"neo4j:1.9": {
		Ports: []string{"7474"},
		Tag:   "bradrydzewski/neo4j:1.9",
		Name:  "neo4j",
	},

	// elasticsearch servers
	"elasticsearch": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.90",
		Name:  "elasticsearch",
	},
	"elasticsearch:0.20": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.20",
		Name:  "elasticsearch",
	},
	"elasticsearch:0.90": {
		Ports: []string{"9200"},
		Tag:   "bradrydzewski/elasticsearch:0.90",
		Name:  "elasticsearch",
	},

	// redis servers
	"redis": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.8",
		Name:  "redis",
	},
	"redis:2.8": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.8",
		Name:  "redis",
	},
	"redis:2.6": {
		Ports: []string{"6379"},
		Tag:   "bradrydzewski/redis:2.6",
		Name:  "redis",
	},

	// mysql servers
	"mysql": {
		Tag:   "bradrydzewski/mysql:5.5",
		Ports: []string{"3306"},
		Name:  "mysql",
	},
	"mysql:5.5": {
		Tag:   "bradrydzewski/mysql:5.5",
		Ports: []string{"3306"},
		Name:  "mysql",
	},

	// memcached
	"memcached": {
		Ports: []string{"11211"},
		Tag:   "bradrydzewski/memcached",
		Name:  "memcached",
	},

	// mongodb
	"mongodb": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.4",
		Name:  "mongodb",
	},
	"mongodb:2.4": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.4",
		Name:  "mongodb",
	},
	"mongodb:2.2": {
		Ports: []string{"27017"},
		Tag:   "bradrydzewski/mongodb:2.2",
		Name:  "mongodb",
	},

	// postgres
	"postgres": {
		Ports: []string{"5432"},
		Tag:   "bradrydzewski/postgres:9.1",
		Name:  "postgres",
	},
	"postgres:9.1": {
		Ports: []string{"5432"},
		Tag:   "bradrydzewski/postgres:9.1",
		Name:  "postgres",
	},

	// couchdb
	"couchdb": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.5",
		Name:  "couchdb",
	},
	"couchdb:1.0": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.0",
		Name:  "couchdb",
	},
	"couchdb:1.4": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.4",
		Name:  "couchdb",
	},
	"couchdb:1.5": {
		Ports: []string{"5984"},
		Tag:   "bradrydzewski/couchdb:1.5",
		Name:  "couchdb",
	},

	// rabbitmq
	"rabbitmq": {
		Ports: []string{"5672", "15672"},
		Tag:   "bradrydzewski/rabbitmq:3.2",
		Name:  "rabbitmq",
	},
	"rabbitmq:3.2": {
		Ports: []string{"5672", "15672"},
		Tag:   "bradrydzewski/rabbitmq:3.2",
		Name:  "rabbitmq",
	},

	// experimental images from 3rd parties

	"zookeeper": {
		Ports: []string{"2181"},
		Tag:   "jplock/zookeeper:3.4.5",
		Name:  "zookeeper",
	},

	// cassandra
	"cassandra": {
		Ports: []string{"9042", "7000", "7001", "7199", "9160", "49183"},
		Tag:   "relateiq/cassandra",
		Name:  "cassandra",
	},

	// riak - TESTED
	"riak": {
		Ports: []string{"8087", "8098"},
		Tag:   "guillermo/riak",
		Name:  "riak",
	},
}

// List of official Drone build images.
var builders = map[string]*image{

	// Clojure build images
	"lein": {Tag: "bradrydzewski/lein"},

	// Dart build images
	"dart":        {Tag: "bradrydzewski/dart:stable"},
	"dart_stable": {Tag: "bradrydzewski/dart:stable"},
	"dart_dev":    {Tag: "bradrydzewski/dart:dev"},

	// Erlang build images
	"erlang":       {Tag: "bradrydzewski/erlang:R16B02"},
	"erlangR16B":   {Tag: "bradrydzewski/erlang:R16B"},
	"erlangR16B02": {Tag: "bradrydzewski/erlang:R16B02"},
	"erlangR16B01": {Tag: "bradrydzewski/erlang:R16B01"},

	// GCC build images
	"gcc":    {Tag: "bradrydzewski/gcc:4.6"},
	"gcc4.6": {Tag: "bradrydzewski/gcc:4.6"},
	"gcc4.8": {Tag: "bradrydzewski/gcc:4.8"},

	// Golang build images
	"go":    {Tag: "bradrydzewski/go:1.3"},
	"go1":   {Tag: "bradrydzewski/go:1.0"},
	"go1.1": {Tag: "bradrydzewski/go:1.1"},
	"go1.2": {Tag: "bradrydzewski/go:1.2"},
	"go1.3": {Tag: "bradrydzewski/go:1.3"},
	"go1.4": {Tag: "bradrydzewski/go:1.4"},

	// Haskell build images
	"haskell":    {Tag: "bradrydzewski/haskell:7.4"},
	"haskell7.4": {Tag: "bradrydzewski/haskell:7.4"},

	// Java build images
	"java":       {Tag: "bradrydzewski/java:openjdk7"},
	"openjdk6":   {Tag: "bradrydzewski/java:openjdk6"},
	"openjdk7":   {Tag: "bradrydzewski/java:openjdk7"},
	"oraclejdk7": {Tag: "bradrydzewski/java:oraclejdk7"},
	"oraclejdk8": {Tag: "bradrydzewski/java:oraclejdk8"},

	// Node build images
	"node":     {Tag: "bradrydzewski/node:0.10"},
	"node0.10": {Tag: "bradrydzewski/node:0.10"},
	"node0.8":  {Tag: "bradrydzewski/node:0.8"},

	// PHP build images
	"php":    {Tag: "bradrydzewski/php:5.5"},
	"php5.5": {Tag: "bradrydzewski/php:5.5"},
	"php5.4": {Tag: "bradrydzewski/php:5.4"},

	// Python build images
	"python":    {Tag: "bradrydzewski/python:2.7"},
	"python2.7": {Tag: "bradrydzewski/python:2.7"},
	"python3.2": {Tag: "bradrydzewski/python:3.2"},
	"python3.3": {Tag: "bradrydzewski/python:3.3"},
	"pypy":      {Tag: "bradrydzewski/python:pypy"},

	// Ruby build images
	"ruby":      {Tag: "bradrydzewski/ruby:2.0.0"},
	"ruby2.0.0": {Tag: "bradrydzewski/ruby:2.0.0"},
	"ruby1.9.3": {Tag: "bradrydzewski/ruby:1.9.3"},

	// Scala build images
	"scala":       {Tag: "bradrydzewski/scala:2.10.3"},
	"scala2.10.3": {Tag: "bradrydzewski/scala:2.10.3"},
	"scala2.9.3":  {Tag: "bradrydzewski/scala:2.9.3"},
}
<|endoftext|>


<commit_before>package auth

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

func DaltonLogin(username string, password string) (map[string]interface{}, string, error) {
	hc := http.Client{}

	form := url.Values{}
    form.Add("username", username)
    form.Add("password", password)

	req, err := http.NewRequest("POST", "https://hsregistration.dalton.org/src/server/index.phplogin", strings.NewReader(form.Encode()))
	if err != nil {
		return nil, "An internal server error occurred while signing you in.", err
	}
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Add("Referer", "https://hsregistration.dalton.org/")
    req.Header.Add("Origin", "https://hsregistration.dalton.org")

    resp, err := hc.Do(req)
	if err != nil {
		return nil, "An internal server error occurred while signing you in.", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	var data map[string]interface{}
	if err := json.Unmarshal([]byte(body), &data); err != nil {
		return nil, "The response from the Dalton login server was malformed.", err
    }
	if data["logged_in"] == false {
		return nil, "The username or password was incorrect.", nil
	}

	return data, "", nil
}
<commit_msg>Add friendly help messages to the errors.<commit_after>package auth

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

func DaltonLogin(username string, password string) (map[string]interface{}, string, error) {
	hc := http.Client{}

	form := url.Values{}
    form.Add("username", username)
    form.Add("password", password)

	req, err := http.NewRequest("POST", "https://hsregistration.dalton.org/src/server/index.phplogin", strings.NewReader(form.Encode()))
	if err != nil {
		return nil, "An internal server error occurred while signing you in. (Contact us at hello@myhomework.space for support.)", err
	}
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Add("Referer", "https://hsregistration.dalton.org/")
    req.Header.Add("Origin", "https://hsregistration.dalton.org")

    resp, err := hc.Do(req)
	if err != nil {
		return nil, "An internal server error occurred while signing you in. (Contact us at hello@myhomework.space for support.)", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	var data map[string]interface{}
	if err := json.Unmarshal([]byte(body), &data); err != nil {
		return nil, "The response from the Dalton login server was malformed. (Don't blame us!)", err
    }
	if data["logged_in"] == false {
		return nil, "The username or password was incorrect. If you don't know your password, you can visit https://tr.im/1v9f2", nil
	}

	return data, "", nil
}
<|endoftext|>