<commit_before>// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/revel/revel, strictly for use in testing.

// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/revel/revel (exports: Controller,Params,Request,Router; functions: HTTP_QUERY)

// Package revel is a stub of github.com/revel/revel, generated by depstubber.
package revel

import (
	context "context"
	io "io"
	multipart "mime/multipart"
	http "net/http"
	url "net/url"
	os "os"
	reflect "reflect"
	regexp "regexp"
	time "time"
)

type AcceptLanguage struct {
	Language string
	Quality  float32
}

type AcceptLanguages []AcceptLanguage

func (_ AcceptLanguages) Len() int {
	return 0
}

func (_ AcceptLanguages) Less(_ int, _ int) bool {
	return false
}

func (_ AcceptLanguages) String() string {
	return ""
}

func (_ AcceptLanguages) Swap(_ int, _ int) {}

type ActionDefinition struct {
	Host   string
	Method string
	URL    string
	Action string
	Star   bool
	Args   map[string]string
}

func (_ *ActionDefinition) String() string {
	return ""
}

type ContentDisposition string

type Controller struct {
	Name          string
	Type          *ControllerType
	MethodName    string
	MethodType    *MethodType
	AppController interface{}
	Action        string
	ClientIP      string
	Request       *Request
	Response      *Response
	Result        Result
	Flash         Flash
	Session       interface{}
	Params        *Params
	Args          map[string]interface{}
	ViewArgs      map[string]interface{}
	Validation    *Validation
	Log           interface{}
}

func (_ *Controller) Destroy() {}

func (_ *Controller) FlashParams() {}

func (_ *Controller) Forbidden(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Message(_ string, _ ...interface{}) string {
	return ""
}

func (_ *Controller) NotFound(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Redirect(_ interface{}, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Render(_ ...interface{}) Result {
	return nil
}

func (_ *Controller) RenderBinary(_ io.Reader, _ string, _ ContentDisposition, _ time.Time) Result {
	return nil
}

func (_ *Controller) RenderError(_ error) Result {
	return nil
}

func (_ *Controller) RenderFile(_ *os.File, _ ContentDisposition) Result {
	return nil
}

func (_ *Controller) RenderFileName(_ string, _ ContentDisposition) Result {
	return nil
}

func (_ *Controller) RenderHTML(_ string) Result {
	return nil
}

func (_ *Controller) RenderJSON(_ interface{}) Result {
	return nil
}

func (_ *Controller) RenderJSONP(_ string, _ interface{}) Result {
	return nil
}

func (_ *Controller) RenderTemplate(_ string) Result {
	return nil
}

func (_ *Controller) RenderText(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) RenderXML(_ interface{}) Result {
	return nil
}

func (_ *Controller) SetAction(_ string, _ string) error {
	return nil
}

func (_ *Controller) SetController(_ ServerContext) {}

func (_ *Controller) SetCookie(_ *http.Cookie) {}

func (_ *Controller) SetTypeAction(_ string, _ string, _ *ControllerType) error {
	return nil
}

func (_ *Controller) Stats() map[string]interface{} {
	return nil
}

func (_ *Controller) TemplateOutput(_ string) ([]byte, error) {
	return nil, nil
}

func (_ *Controller) Todo() Result {
	return nil
}

type ControllerFieldPath struct {
	IsPointer      bool
	FieldIndexPath []int
	FunctionCall   reflect.Value
}

func (_ *ControllerFieldPath) Invoke(_ reflect.Value, _ []reflect.Value) []reflect.Value {
	return nil
}

type ControllerType struct {
	Namespace         string
	ModuleSource      *Module
	Type              reflect.Type
	Methods           []*MethodType
	ControllerIndexes [][]int
	ControllerEvents  *ControllerTypeEvents
}

func (_ *ControllerType) Method(_ string) *MethodType {
	return nil
}

func (_ *ControllerType) Name() string {
	return ""
}

func (_ *ControllerType) ShortName() string {
	return ""
}

type ControllerTypeEvents struct {
	Before  []*ControllerFieldPath
	After   []*ControllerFieldPath
	Finally []*ControllerFieldPath
	Panic   []*ControllerFieldPath
}

type Error struct {
	SourceType  string
	Title       string
	Path        string
	Description string
	Line        int
	Column      int
	SourceLines []string
	Stack       string
	MetaError   string
	Link        string
}

func (_ *Error) ContextSource() []SourceLine {
	return nil
}

func (_ *Error) Error() string {
	return ""
}

func (_ *Error) SetLink(_ string) {}

type Flash struct {
	Data map[string]string
	Out  map[string]string
}

func (_ Flash) Error(_ string, _ ...interface{}) {}

func (_ Flash) Success(_ string, _ ...interface{}) {}

var HTTP_QUERY int = 0

type MethodArg struct {
	Name string
	Type reflect.Type
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	Index          int
}

type Module struct {
	Name               string
	ImportPath         string
	Path               string
	ControllerTypeList []*ControllerType
	Log                interface{}
}

func (_ *Module) AddController(_ *ControllerType) {}

func (_ *Module) ControllerByName(_ string, _ string) *ControllerType {
	return nil
}

func (_ *Module) Namespace() string {
	return ""
}

type MultipartForm struct {
	File  map[string][]*multipart.FileHeader
	Value url.Values
}

type OutResponse struct {
	Server ServerResponse
}

func (_ *OutResponse) Destroy() {}

func (_ *OutResponse) Header() *RevelHeader {
	return nil
}

func (_ *OutResponse) Write(_ []byte) (int, error) {
	return 0, nil
}

type Params struct {
	Values url.Values
	Fixed  url.Values
	Route  url.Values
	Query  url.Values
	Form   url.Values
	Files  map[string][]*multipart.FileHeader
	JSON   []byte
}

func (_ Params) Add(_ string, _ string) {}

func (_ Params) Del(_ string) {}

func (_ Params) Encode() string {
	return ""
}

func (_ Params) Get(_ string) string {
	return ""
}

func (_ Params) Set(_ string, _ string) {}

func (_ *Params) Bind(_ interface{}, _ string) {}

func (_ *Params) BindJSON(_ interface{}) error {
	return nil
}

type Request struct {
	In              ServerRequest
	Header          *RevelHeader
	ContentType     string
	Format          string
	AcceptLanguages AcceptLanguages
	Locale          string
	WebSocket       ServerWebSocket
	Method          string
	RemoteAddr      string
	Host            string
	URL             *url.URL
	Form            url.Values
	MultipartForm   *MultipartForm
}

func (_ *Request) Args() map[string]interface{} {
	return nil
}

func (_ *Request) Context() context.Context {
	return nil
}

func (_ *Request) Cookie(_ string) (ServerCookie, error) {
	return nil, nil
}

func (_ *Request) Destroy() {}

func (_ *Request) FormValue(_ string) string {
	return ""
}

func (_ *Request) GetBody() io.Reader {
	return nil
}

func (_ *Request) GetForm() (url.Values, error) {
	return nil, nil
}

func (_ *Request) GetHttpHeader(_ string) string {
	return ""
}

func (_ *Request) GetMultipartForm() (ServerMultipartForm, error) {
	return nil, nil
}

func (_ *Request) GetPath() string {
	return ""
}

func (_ *Request) GetQuery() url.Values {
	return nil
}

func (_ *Request) GetRequestURI() string {
	return ""
}

func (_ *Request) GetValue(_ int) interface{} {
	return nil
}

func (_ *Request) MultipartReader() (*multipart.Reader, error) {
	return nil, nil
}

func (_ *Request) ParseForm() error {
	return nil
}

func (_ *Request) ParseMultipartForm(_ int64) error {
	return nil
}

func (_ *Request) PostFormValue(_ string) string {
	return ""
}

func (_ *Request) Referer() string {
	return ""
}

func (_ *Request) SetRequest(_ ServerRequest) {}

func (_ *Request) UserAgent() string {
	return ""
}

type Response struct {
	Status      int
	ContentType string
	Out         OutResponse
}

func (_ *Response) Destroy() {}

func (_ *Response) GetStreamWriter() StreamWriter {
	return nil
}

func (_ *Response) GetWriter() io.Writer {
	return nil
}

func (_ *Response) SetResponse(_ ServerResponse) {}

func (_ *Response) SetStatus(_ int) {}

func (_ *Response) SetWriter(_ io.Writer) bool {
	return false
}

func (_ *Response) WriteHeader(_ int, _ string) {}

type Result interface {
	Apply(_ *Request, _ *Response)
}

type RevelHeader struct {
	Server ServerHeader
}

func (_ *RevelHeader) Add(_ string, _ string) {}

func (_ *RevelHeader) Destroy() {}

func (_ *RevelHeader) Get(_ string) string {
	return ""
}

func (_ *RevelHeader) GetAll(_ string) []string {
	return nil
}

func (_ *RevelHeader) Set(_ string, _ string) {}

func (_ *RevelHeader) SetCookie(_ string) {}

func (_ *RevelHeader) SetStatus(_ int) {}

type Route struct {
	ModuleSource        *Module
	Method              string
	Path                string
	Action              string
	ControllerNamespace string
	ControllerName      string
	MethodName          string
	FixedParams         []string
	TreePath            string
	TypeOfController    *ControllerType
}

func (_ *Route) ActionPath() string {
	return ""
}

type RouteMatch struct {
	Action           string
	ControllerName   string
	MethodName       string
	FixedParams      []string
	Params           map[string][]string
	TypeOfController *ControllerType
	ModuleSource     *Module
}

type Router struct {
	Routes []*Route
	Tree   interface{}
	Module string
}

func (_ *Router) Refresh() *Error {
	return nil
}

func (_ *Router) Reverse(_ string, _ map[string]string) *ActionDefinition {
	return nil
}

func (_ *Router) ReverseError(_ string, _ map[string]string, _ *Request) (*ActionDefinition, error) {
	return nil, nil
}

func (_ *Router) Route(_ *Request) *RouteMatch {
	return nil
}

type ServerContext interface {
	GetRequest() ServerRequest
	GetResponse() ServerResponse
}

type ServerCookie interface {
	GetValue() string
}

type ServerHeader interface {
	Add(_ string, _ string)
	Del(_ string)
	Get(_ string) []string
	GetCookie(_ string) (ServerCookie, error)
	GetKeys() []string
	Set(_ string, _ string)
	SetCookie(_ string)
	SetStatus(_ int)
}

type ServerMultipartForm interface {
	GetFiles() map[string][]*multipart.FileHeader
	GetValues() url.Values
	RemoveAll() error
}

type ServerRequest interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	Set(_ int, _ interface{}) bool
}

type ServerResponse interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	Set(_ int, _ interface{}) bool
}

type ServerWebSocket interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	MessageReceive(_ interface{}) error
	MessageReceiveJSON(_ interface{}) error
	MessageSend(_ interface{}) error
	MessageSendJSON(_ interface{}) error
	Set(_ int, _ interface{}) bool
}

type SourceLine struct {
	Source  string
	Line    int
	IsError bool
}

type StreamWriter interface {
	WriteStream(_ string, _ int64, _ time.Time, _ io.Reader) error
}

type Validation struct {
	Errors     []*ValidationError
	Request    *Request
	Translator func(string, string, ...interface{}) string
}

func (_ *Validation) Check(_ interface{}, _ ...Validator) *ValidationResult {
	return nil
}

func (_ *Validation) Clear() {}

func (_ *Validation) Domain(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Email(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Error(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) ErrorKey(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) ErrorMap() map[string]*ValidationError {
	return nil
}

func (_ *Validation) FilePath(_ string, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) HasErrors() bool {
	return false
}

func (_ *Validation) IPAddr(_ string, _ ...int) *ValidationResult {
	return nil
}

func (_ *Validation) Keep() {}

func (_ *Validation) Length(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MacAddr(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Match(_ string, _ *regexp.Regexp) *ValidationResult {
	return nil
}

func (_ *Validation) Max(_ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MaxFloat(_ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) MaxSize(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) Min(_ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MinFloat(_ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) MinSize(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) PureText(_ string, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) Range(_ int, _ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) RangeFloat(_ float64, _ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) Required(_ interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) URL(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) ValidationResult(_ bool) *ValidationResult {
	return nil
}

type ValidationError struct {
	Message string
	Key     string
}

func (_ *ValidationError) String() string {
	return ""
}

type ValidationResult struct {
	Error      *ValidationError
	Ok         bool
	Locale     string
	Translator func(string, string, ...interface{}) string
}

func (_ *ValidationResult) Key(_ string) *ValidationResult {
	return nil
}

func (_ *ValidationResult) Message(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *ValidationResult) MessageKey(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

type Validator interface {
	DefaultMessage() string
	IsSatisfied(_ interface{}) bool
}
<commit_msg>Fix stub for Revel<commit_after>// Code generated by depstubber. It has been edited to fix a problem with embedded fields.
// This is a simple stub for github.com/revel/revel, strictly for use in testing.

// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/revel/revel (exports: Controller,Params,Request,Router; functions: HTTP_QUERY)

// Package revel is a stub of github.com/revel/revel, generated by depstubber, with minor edits.
package revel

import (
	context "context"
	io "io"
	multipart "mime/multipart"
	http "net/http"
	url "net/url"
	os "os"
	reflect "reflect"
	regexp "regexp"
	time "time"
)

type AcceptLanguage struct {
	Language string
	Quality  float32
}

type AcceptLanguages []AcceptLanguage

func (_ AcceptLanguages) Len() int {
	return 0
}

func (_ AcceptLanguages) Less(_ int, _ int) bool {
	return false
}

func (_ AcceptLanguages) String() string {
	return ""
}

func (_ AcceptLanguages) Swap(_ int, _ int) {}

type ActionDefinition struct {
	Host   string
	Method string
	URL    string
	Action string
	Star   bool
	Args   map[string]string
}

func (_ *ActionDefinition) String() string {
	return ""
}

type ContentDisposition string

type Controller struct {
	Name          string
	Type          *ControllerType
	MethodName    string
	MethodType    *MethodType
	AppController interface{}
	Action        string
	ClientIP      string
	Request       *Request
	Response      *Response
	Result        Result
	Flash         Flash
	Session       interface{}
	Params        *Params
	Args          map[string]interface{}
	ViewArgs      map[string]interface{}
	Validation    *Validation
	Log           interface{}
}

func (_ *Controller) Destroy() {}

func (_ *Controller) FlashParams() {}

func (_ *Controller) Forbidden(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Message(_ string, _ ...interface{}) string {
	return ""
}

func (_ *Controller) NotFound(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Redirect(_ interface{}, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) Render(_ ...interface{}) Result {
	return nil
}

func (_ *Controller) RenderBinary(_ io.Reader, _ string, _ ContentDisposition, _ time.Time) Result {
	return nil
}

func (_ *Controller) RenderError(_ error) Result {
	return nil
}

func (_ *Controller) RenderFile(_ *os.File, _ ContentDisposition) Result {
	return nil
}

func (_ *Controller) RenderFileName(_ string, _ ContentDisposition) Result {
	return nil
}

func (_ *Controller) RenderHTML(_ string) Result {
	return nil
}

func (_ *Controller) RenderJSON(_ interface{}) Result {
	return nil
}

func (_ *Controller) RenderJSONP(_ string, _ interface{}) Result {
	return nil
}

func (_ *Controller) RenderTemplate(_ string) Result {
	return nil
}

func (_ *Controller) RenderText(_ string, _ ...interface{}) Result {
	return nil
}

func (_ *Controller) RenderXML(_ interface{}) Result {
	return nil
}

func (_ *Controller) SetAction(_ string, _ string) error {
	return nil
}

func (_ *Controller) SetController(_ ServerContext) {}

func (_ *Controller) SetCookie(_ *http.Cookie) {}

func (_ *Controller) SetTypeAction(_ string, _ string, _ *ControllerType) error {
	return nil
}

func (_ *Controller) Stats() map[string]interface{} {
	return nil
}

func (_ *Controller) TemplateOutput(_ string) ([]byte, error) {
	return nil, nil
}

func (_ *Controller) Todo() Result {
	return nil
}

type ControllerFieldPath struct {
	IsPointer      bool
	FieldIndexPath []int
	FunctionCall   reflect.Value
}

func (_ *ControllerFieldPath) Invoke(_ reflect.Value, _ []reflect.Value) []reflect.Value {
	return nil
}

type ControllerType struct {
	Namespace         string
	ModuleSource      *Module
	Type              reflect.Type
	Methods           []*MethodType
	ControllerIndexes [][]int
	ControllerEvents  *ControllerTypeEvents
}

func (_ *ControllerType) Method(_ string) *MethodType {
	return nil
}

func (_ *ControllerType) Name() string {
	return ""
}

func (_ *ControllerType) ShortName() string {
	return ""
}

type ControllerTypeEvents struct {
	Before  []*ControllerFieldPath
	After   []*ControllerFieldPath
	Finally []*ControllerFieldPath
	Panic   []*ControllerFieldPath
}

type Error struct {
	SourceType  string
	Title       string
	Path        string
	Description string
	Line        int
	Column      int
	SourceLines []string
	Stack       string
	MetaError   string
	Link        string
}

func (_ *Error) ContextSource() []SourceLine {
	return nil
}

func (_ *Error) Error() string {
	return ""
}

func (_ *Error) SetLink(_ string) {}

type Flash struct {
	Data map[string]string
	Out  map[string]string
}

func (_ Flash) Error(_ string, _ ...interface{}) {}

func (_ Flash) Success(_ string, _ ...interface{}) {}

var HTTP_QUERY int = 0

type MethodArg struct {
	Name string
	Type reflect.Type
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	Index          int
}

type Module struct {
	Name               string
	ImportPath         string
	Path               string
	ControllerTypeList []*ControllerType
	Log                interface{}
}

func (_ *Module) AddController(_ *ControllerType) {}

func (_ *Module) ControllerByName(_ string, _ string) *ControllerType {
	return nil
}

func (_ *Module) Namespace() string {
	return ""
}

type MultipartForm struct {
	File  map[string][]*multipart.FileHeader
	Value url.Values
}

type OutResponse struct {
	Server ServerResponse
}

func (_ *OutResponse) Destroy() {}

func (_ *OutResponse) Header() *RevelHeader {
	return nil
}

func (_ *OutResponse) Write(_ []byte) (int, error) {
	return 0, nil
}

type Params struct {
	url.Values
	Fixed url.Values
	Route url.Values
	Query url.Values
	Form  url.Values
	Files map[string][]*multipart.FileHeader
	JSON  []byte
}

func (_ *Params) Bind(_ interface{}, _ string) {}

func (_ *Params) BindJSON(_ interface{}) error {
	return nil
}

type Request struct {
	In              ServerRequest
	Header          *RevelHeader
	ContentType     string
	Format          string
	AcceptLanguages AcceptLanguages
	Locale          string
	WebSocket       ServerWebSocket
	Method          string
	RemoteAddr      string
	Host            string
	URL             *url.URL
	Form            url.Values
	MultipartForm   *MultipartForm
}

func (_ *Request) Args() map[string]interface{} {
	return nil
}

func (_ *Request) Context() context.Context {
	return nil
}

func (_ *Request) Cookie(_ string) (ServerCookie, error) {
	return nil, nil
}

func (_ *Request) Destroy() {}

func (_ *Request) FormValue(_ string) string {
	return ""
}

func (_ *Request) GetBody() io.Reader {
	return nil
}

func (_ *Request) GetForm() (url.Values, error) {
	return nil, nil
}

func (_ *Request) GetHttpHeader(_ string) string {
	return ""
}

func (_ *Request) GetMultipartForm() (ServerMultipartForm, error) {
	return nil, nil
}

func (_ *Request) GetPath() string {
	return ""
}

func (_ *Request) GetQuery() url.Values {
	return nil
}

func (_ *Request) GetRequestURI() string {
	return ""
}

func (_ *Request) GetValue(_ int) interface{} {
	return nil
}

func (_ *Request) MultipartReader() (*multipart.Reader, error) {
	return nil, nil
}

func (_ *Request) ParseForm() error {
	return nil
}

func (_ *Request) ParseMultipartForm(_ int64) error {
	return nil
}

func (_ *Request) PostFormValue(_ string) string {
	return ""
}

func (_ *Request) Referer() string {
	return ""
}

func (_ *Request) SetRequest(_ ServerRequest) {}

func (_ *Request) UserAgent() string {
	return ""
}

type Response struct {
	Status      int
	ContentType string
	Out         OutResponse
}

func (_ *Response) Destroy() {}

func (_ *Response) GetStreamWriter() StreamWriter {
	return nil
}

func (_ *Response) GetWriter() io.Writer {
	return nil
}

func (_ *Response) SetResponse(_ ServerResponse) {}

func (_ *Response) SetStatus(_ int) {}

func (_ *Response) SetWriter(_ io.Writer) bool {
	return false
}

func (_ *Response) WriteHeader(_ int, _ string) {}

type Result interface {
	Apply(_ *Request, _ *Response)
}

type RevelHeader struct {
	Server ServerHeader
}

func (_ *RevelHeader) Add(_ string, _ string) {}

func (_ *RevelHeader) Destroy() {}

func (_ *RevelHeader) Get(_ string) string {
	return ""
}

func (_ *RevelHeader) GetAll(_ string) []string {
	return nil
}

func (_ *RevelHeader) Set(_ string, _ string) {}

func (_ *RevelHeader) SetCookie(_ string) {}

func (_ *RevelHeader) SetStatus(_ int) {}

type Route struct {
	ModuleSource        *Module
	Method              string
	Path                string
	Action              string
	ControllerNamespace string
	ControllerName      string
	MethodName          string
	FixedParams         []string
	TreePath            string
	TypeOfController    *ControllerType
}

func (_ *Route) ActionPath() string {
	return ""
}

type RouteMatch struct {
	Action           string
	ControllerName   string
	MethodName       string
	FixedParams      []string
	Params           map[string][]string
	TypeOfController *ControllerType
	ModuleSource     *Module
}

type Router struct {
	Routes []*Route
	Tree   interface{}
	Module string
}

func (_ *Router) Refresh() *Error {
	return nil
}

func (_ *Router) Reverse(_ string, _ map[string]string) *ActionDefinition {
	return nil
}

func (_ *Router) ReverseError(_ string, _ map[string]string, _ *Request) (*ActionDefinition, error) {
	return nil, nil
}

func (_ *Router) Route(_ *Request) *RouteMatch {
	return nil
}

type ServerContext interface {
	GetRequest() ServerRequest
	GetResponse() ServerResponse
}

type ServerCookie interface {
	GetValue() string
}

type ServerHeader interface {
	Add(_ string, _ string)
	Del(_ string)
	Get(_ string) []string
	GetCookie(_ string) (ServerCookie, error)
	GetKeys() []string
	Set(_ string, _ string)
	SetCookie(_ string)
	SetStatus(_ int)
}

type ServerMultipartForm interface {
	GetFiles() map[string][]*multipart.FileHeader
	GetValues() url.Values
	RemoveAll() error
}

type ServerRequest interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	Set(_ int, _ interface{}) bool
}

type ServerResponse interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	Set(_ int, _ interface{}) bool
}

type ServerWebSocket interface {
	Get(_ int) (interface{}, error)
	GetRaw() interface{}
	MessageReceive(_ interface{}) error
	MessageReceiveJSON(_ interface{}) error
	MessageSend(_ interface{}) error
	MessageSendJSON(_ interface{}) error
	Set(_ int, _ interface{}) bool
}

type SourceLine struct {
	Source  string
	Line    int
	IsError bool
}

type StreamWriter interface {
	WriteStream(_ string, _ int64, _ time.Time, _ io.Reader) error
}

type Validation struct {
	Errors     []*ValidationError
	Request    *Request
	Translator func(string, string, ...interface{}) string
}

func (_ *Validation) Check(_ interface{}, _ ...Validator) *ValidationResult {
	return nil
}

func (_ *Validation) Clear() {}

func (_ *Validation) Domain(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Email(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Error(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) ErrorKey(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) ErrorMap() map[string]*ValidationError {
	return nil
}

func (_ *Validation) FilePath(_ string, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) HasErrors() bool {
	return false
}

func (_ *Validation) IPAddr(_ string, _ ...int) *ValidationResult {
	return nil
}

func (_ *Validation) Keep() {}

func (_ *Validation) Length(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MacAddr(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) Match(_ string, _ *regexp.Regexp) *ValidationResult {
	return nil
}

func (_ *Validation) Max(_ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MaxFloat(_ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) MaxSize(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) Min(_ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) MinFloat(_ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) MinSize(_ interface{}, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) PureText(_ string, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) Range(_ int, _ int, _ int) *ValidationResult {
	return nil
}

func (_ *Validation) RangeFloat(_ float64, _ float64, _ float64) *ValidationResult {
	return nil
}

func (_ *Validation) Required(_ interface{}) *ValidationResult {
	return nil
}

func (_ *Validation) URL(_ string) *ValidationResult {
	return nil
}

func (_ *Validation) ValidationResult(_ bool) *ValidationResult {
	return nil
}

type ValidationError struct {
	Message string
	Key     string
}

func (_ *ValidationError) String() string {
	return ""
}

type ValidationResult struct {
	Error      *ValidationError
	Ok         bool
	Locale     string
	Translator func(string, string, ...interface{}) string
}

func (_ *ValidationResult) Key(_ string) *ValidationResult {
	return nil
}

func (_ *ValidationResult) Message(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

func (_ *ValidationResult) MessageKey(_ string, _ ...interface{}) *ValidationResult {
	return nil
}

type Validator interface {
	DefaultMessage() string
	IsSatisfied(_ interface{}) bool
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEc2Tag() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEc2TagCreate,
		Read:   resourceAwsEc2TagRead,
		Delete: resourceAwsEc2TagDelete,

		Schema: map[string]*schema.Schema{
			"resource_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"value": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func extractResourceIdFromEc2TagId(d *schema.ResourceData) (string, error) {
	i := d.Id()
	parts := strings.Split(i, "-")

	if len(parts) != 2 {
		return "", fmt.Errorf("Invalid resource ID; cannot look up subnet: %s", i)
	}

	return parts[0], nil
}

func resourceAwsEc2TagCreate(d *schema.ResourceData, meta interface{}) error {
	d.SetId(fmt.Sprintf("%s-%s", d.Get("subnet_id"), d.Get("key")))
	return resourceAwsEc2TagRead(d, meta)
}

func resourceAwsEc2TagRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	id, err := extractResourceIdFromEc2TagId(d)

	if err != nil {
		return err
	}

	key := d.Get("key").(string)

	tags, err := conn.DescribeTags(&ec2.DescribeTagsInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String("resource-id"),
				Values: []*string{aws.String(id)},
			},
			{
				Name:   aws.String("key"),
				Values: []*string{aws.String(key)},
			},
		},
	})

	if err != nil {
		return err
	}

	if len(tags.Tags) != 1 {
		return fmt.Errorf("Expected exactly 1 tag, got %d tags for key %s", len(tags.Tags), key)
	}

	tag := tags.Tags[0]
	d.Set("value", aws.StringValue(tag.Value))

	return nil
}

func resourceAwsEc2TagDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	id, err := extractResourceIdFromEc2TagId(d)

	if err != nil {
		return err
	}

	_, err = conn.DeleteTags(&ec2.DeleteTagsInput{
		Resources: []*string{aws.String(id)},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String(d.Get("tag").(string)),
				Value: aws.String(d.Get("value").(string)),
			},
		},
	})

	return nil
}
<commit_msg>Get tests working minus the VPC resource causing a dirty plan.<commit_after>package aws

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEc2Tag() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEc2TagCreate,
		Read:   resourceAwsEc2TagRead,
		Delete: resourceAwsEc2TagDelete,

		Schema: map[string]*schema.Schema{
			"resource_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"value": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func extractResourceIdFromEc2TagId(d *schema.ResourceData) (string, error) {
	i := d.Id()
	parts := strings.Split(i, ":")

	if len(parts) != 2 {
		return "", fmt.Errorf("Invalid resource ID; cannot look up resource: %s", i)
	}

	return parts[0], nil
}

func resourceAwsEc2TagCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	resourceID := d.Get("resource_id").(string)

	_, err := conn.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{aws.String(resourceID)},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String(d.Get("key").(string)),
				Value: aws.String(d.Get("value").(string)),
			},
		},
	})

	if err != nil {
		return err
	}

	d.SetId(fmt.Sprintf("%s:%s", resourceID, d.Get("key").(string)))
	return resourceAwsEc2TagRead(d, meta)
}

func resourceAwsEc2TagRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	id, err := extractResourceIdFromEc2TagId(d)

	if err != nil {
		return err
	}

	key := d.Get("key").(string)

	tags, err := conn.DescribeTags(&ec2.DescribeTagsInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String("resource-id"),
				Values: []*string{aws.String(id)},
			},
			{
				Name:   aws.String("key"),
				Values: []*string{aws.String(key)},
			},
		},
	})

	if err != nil {
		return err
	}

	if len(tags.Tags) != 1 {
		return fmt.Errorf("Expected exactly 1 tag, got %d tags for key %s", len(tags.Tags), key)
	}

	tag := tags.Tags[0]
	d.Set("value", aws.StringValue(tag.Value))

	return nil
}

func resourceAwsEc2TagDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	id, err := extractResourceIdFromEc2TagId(d)

	if err != nil {
		return err
	}

	_, err = conn.DeleteTags(&ec2.DeleteTagsInput{
		Resources: []*string{aws.String(id)},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String(d.Get("key").(string)),
				Value: aws.String(d.Get("value").(string)),
			},
		},
	})

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 flushfs_test

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path"
	"sync"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/flushfs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFlushFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FlushFSTest struct {
	samples.SampleTest

	mu sync.Mutex

	// GUARDED_BY(mu)
	flushes  []string
	flushErr error

	// GUARDED_BY(mu)
	fsyncs   []string
	fsyncErr error
}

func init() { RegisterTestSuite(&FlushFSTest{}) }

func (t *FlushFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a file system.
	reportTo := func(slice *[]string, err *error) func(string) error {
		return func(s string) error {
			t.mu.Lock()
			defer t.mu.Unlock()

			*slice = append(*slice, s)
			return *err
		}
	}

	t.FileSystem, err = flushfs.NewFileSystem(
		reportTo(&t.flushes, &t.flushErr),
		reportTo(&t.fsyncs, &t.fsyncErr))

	if err != nil {
		panic(err)
	}

	// Mount it.
	t.SampleTest.SetUp(ti)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

// Match byte slices equal to the supplied string.
func byteSliceEq(expected string) Matcher {
	pred := func(c interface{}) error {
		slice, ok := c.([]byte)
		if !ok {
			return errors.New("which is not []byte")
		}

		if string(slice) != expected {
			return fmt.Errorf("which is string \"%s\"", string(slice))
		}

		return nil
	}

	return NewMatcher(
		pred,
		fmt.Sprintf("byte slice equal to string \"%s\"", expected))
}

// Return a copy of the current contents of t.flushes.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFlushes() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.flushes))
	copy(p, t.flushes)
	return
}

// Return a copy of the current contents of t.fsyncs.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFsyncs() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.fsyncs))
	copy(p, t.fsyncs)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FlushFSTest) CloseReports_ReadWrite() {
	var n int
	var off int64
	var err error
	buf := make([]byte, 1024)

	// Open the file.
	f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
	AssertEq(nil, err)

	defer func() {
		if f != nil {
			ExpectEq(nil, f.Close())
		}
	}()

	// Write some contents to the file.
	n, err = f.Write([]byte("taco"))
	AssertEq(nil, err)
	AssertEq(4, n)

	// Seek and read them back.
	off, err = f.Seek(0, 0)
	AssertEq(nil, err)
	AssertEq(0, off)

	n, err = f.Read(buf)
	AssertThat(err, AnyOf(nil, io.EOF))
	AssertEq("taco", string(buf[:n]))

	// At this point, no flushes or fsyncs should have happened.
	AssertThat(t.getFlushes(), ElementsAre())
	AssertThat(t.getFsyncs(), ElementsAre())

	// Close the file.
	err = f.Close()
	f = nil
	AssertEq(nil, err)

	// Now we should have received the flush operation (but still no fsync).
	ExpectThat(t.getFlushes(), ElementsAre(byteSliceEq("taco")))
	ExpectThat(t.getFsyncs(), ElementsAre())
}

func (t *FlushFSTest) CloseReports_ReadOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_WriteOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_NonOverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_OverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseError() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncReports() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncError() {
	AssertTrue(false, "TODO")
}
<commit_msg>FlushFSTest.CloseReports_ReadOnly<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 flushfs_test

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path"
	"sync"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/flushfs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFlushFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FlushFSTest struct {
	samples.SampleTest

	mu sync.Mutex

	// GUARDED_BY(mu)
	flushes  []string
	flushErr error

	// GUARDED_BY(mu)
	fsyncs   []string
	fsyncErr error
}

func init() { RegisterTestSuite(&FlushFSTest{}) }

func (t *FlushFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a file system.
	reportTo := func(slice *[]string, err *error) func(string) error {
		return func(s string) error {
			t.mu.Lock()
			defer t.mu.Unlock()

			*slice = append(*slice, s)
			return *err
		}
	}

	t.FileSystem, err = flushfs.NewFileSystem(
		reportTo(&t.flushes, &t.flushErr),
		reportTo(&t.fsyncs, &t.fsyncErr))

	if err != nil {
		panic(err)
	}

	// Mount it.
	t.SampleTest.SetUp(ti)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

// Match byte slices equal to the supplied string.
func byteSliceEq(expected string) Matcher {
	pred := func(c interface{}) error {
		slice, ok := c.([]byte)
		if !ok {
			return errors.New("which is not []byte")
		}

		if string(slice) != expected {
			return fmt.Errorf("which is string \"%s\"", string(slice))
		}

		return nil
	}

	return NewMatcher(
		pred,
		fmt.Sprintf("byte slice equal to string \"%s\"", expected))
}

// Return a copy of the current contents of t.flushes.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFlushes() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.flushes))
	copy(p, t.flushes)
	return
}

// Return a copy of the current contents of t.fsyncs.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFsyncs() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.fsyncs))
	copy(p, t.fsyncs)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FlushFSTest) CloseReports_ReadWrite() {
	var n int
	var off int64
	var err error
	buf := make([]byte, 1024)

	// Open the file.
	f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
	AssertEq(nil, err)

	defer func() {
		if f != nil {
			ExpectEq(nil, f.Close())
		}
	}()

	// Write some contents to the file.
	n, err = f.Write([]byte("taco"))
	AssertEq(nil, err)
	AssertEq(4, n)

	// Seek and read them back.
	off, err = f.Seek(0, 0)
	AssertEq(nil, err)
	AssertEq(0, off)

	n, err = f.Read(buf)
	AssertThat(err, AnyOf(nil, io.EOF))
	AssertEq("taco", string(buf[:n]))

	// At this point, no flushes or fsyncs should have happened.
	AssertThat(t.getFlushes(), ElementsAre())
	AssertThat(t.getFsyncs(), ElementsAre())

	// Close the file.
	err = f.Close()
	f = nil
	AssertEq(nil, err)

	// Now we should have received the flush operation (but still no fsync).
	ExpectThat(t.getFlushes(), ElementsAre(byteSliceEq("taco")))
	ExpectThat(t.getFsyncs(), ElementsAre())
}

func (t *FlushFSTest) CloseReports_ReadOnly() {
	var err error

	// Open the file.
	f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDONLY, 0)
	AssertEq(nil, err)

	defer func() {
		if f != nil {
			ExpectEq(nil, f.Close())
		}
	}()

	// At this point, no flushes or fsyncs should have happened.
	AssertThat(t.getFlushes(), ElementsAre())
	AssertThat(t.getFsyncs(), ElementsAre())

	// Close the file.
	err = f.Close()
	f = nil
	AssertEq(nil, err)

	// Now we should have received the flush operation (but still no fsync).
	ExpectThat(t.getFlushes(), ElementsAre(byteSliceEq("")))
	ExpectThat(t.getFsyncs(), ElementsAre())
}

func (t *FlushFSTest) CloseReports_WriteOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_NonOverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_OverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseError() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncReports() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncError() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"github.com/Azure/azure-sdk-for-go/arm/disk"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"log"
	"net/http"
	"strings"
)

func resourceArmManagedDisk() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmManagedDiskCreate,
		Read:   resourceArmManagedDiskRead,
		Update: resourceArmManagedDiskCreate,
		Delete: resourceArmManagedDiskDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"location": locationSchema(),

			"resource_group_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"storage_account_type": {
				Type:     schema.TypeString,
				Required: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.PremiumLRS),
					string(disk.StandardLRS),
				}, true),
			},

			"create_option": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.Import),
					string(disk.Empty),
					string(disk.Copy),
				}, true),
			},

			"source_uri": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"source_resource_id": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"os_type": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.Windows),
					string(disk.Linux),
				}, true),
			},

			"disk_size_gb": {
				Type:         schema.TypeInt,
				Optional:     true,
				ValidateFunc: validateDiskSizeGB,
			},

			"tags": tagsSchema(),
		},
	}
}

func validateDiskSizeGB(v interface{}, k string) (ws []string, errors []error) {
	value := v.(int)
	if value < 1 || value > 1023 {
		errors = append(errors, fmt.Errorf(
			"The `disk_size_gb` can only be between 1 and 1023"))
	}
	return
}

func resourceArmManagedDiskCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient)
	diskClient := client.diskClient

	log.Printf("[INFO] preparing arguments for Azure ARM Managed Disk creation.")

	name := d.Get("name").(string)
	location := d.Get("location").(string)
	resGroup := d.Get("resource_group_name").(string)
	tags := d.Get("tags").(map[string]interface{})
	expandedTags := expandTags(tags)

	createDisk := disk.Model{
		Name:     &name,
		Location: &location,
		Tags:     expandedTags,
	}

	storageAccountType := d.Get("storage_account_type").(string)
	osType := d.Get("os_type").(string)

	createDisk.Properties = &disk.Properties{
		AccountType: disk.StorageAccountTypes(storageAccountType),
		OsType:      disk.OperatingSystemTypes(osType),
	}

	if v := d.Get("disk_size_gb"); v != 0 {
		diskSize := int32(v.(int))
		createDisk.Properties.DiskSizeGB = &diskSize
	}
	createOption := d.Get("create_option").(string)

	creationData := &disk.CreationData{
		CreateOption: disk.CreateOption(createOption),
	}

	if strings.EqualFold(createOption, string(disk.Import)) {
		if sourceUri := d.Get("source_uri").(string); sourceUri != "" {
			creationData.SourceURI = &sourceUri
		} else {
			return fmt.Errorf("[ERROR] source_uri must be specified when create_option is `%s`", disk.Import)
		}
	} else if strings.EqualFold(createOption, string(disk.Copy)) {
		if sourceResourceId := d.Get("source_resource_id").(string); sourceResourceId != "" {
			creationData.SourceResourceID = &sourceResourceId
		} else {
			return fmt.Errorf("[ERROR] source_resource_id must be specified when create_option is `%s`", disk.Copy)
		}
	}

	createDisk.CreationData = creationData

	_, diskErr := diskClient.CreateOrUpdate(resGroup, name, createDisk, make(chan struct{}))
	if diskErr != nil {
		return diskErr
	}

	read, err := diskClient.Get(resGroup, name)
	if err != nil {
		return err
	}
	if read.ID == nil {
		return fmt.Errorf("[ERROR] Cannot read Managed Disk %s (resource group %s) ID", name, resGroup)
	}

	d.SetId(*read.ID)

	return resourceArmManagedDiskRead(d, meta)
}

func resourceArmManagedDiskRead(d *schema.ResourceData, meta interface{}) error {
	diskClient := meta.(*ArmClient).diskClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["disks"]

	resp, err := diskClient.Get(resGroup, name)
	if err != nil {
		if resp.StatusCode == http.StatusNotFound {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("[ERROR] Error making Read request on Azure Managed Disk %s (resource group %s): %s", name, resGroup, err)
	}

	d.Set("name", resp.Name)
	d.Set("resource_group_name", resGroup)
	d.Set("location", resp.Location)

	if resp.Properties != nil {
		m := flattenAzureRmManagedDiskProperties(resp.Properties)
		d.Set("storage_account_type", m["storage_account_type"])
		d.Set("disk_size_gb", m["disk_size_gb"])
		if m["os_type"] != nil {
			d.Set("os_type", m["os_type"])
		}
	}

	if resp.CreationData != nil {
		m := flattenAzureRmManagedDiskCreationData(resp.CreationData)
		d.Set("create_option", m["create_option"])
		if m["source_uri"] != nil {
			d.Set("source_uri", m["source_uri"])
		}
		if m["source_resource_id"] != nil {
			d.Set("source_resource_id", m["source_resource_id"])
		}
	}

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmManagedDiskDelete(d *schema.ResourceData, meta interface{}) error {
	diskClient := meta.(*ArmClient).diskClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["disks"]

	if _, err = diskClient.Delete(resGroup, name, make(chan struct{})); err != nil {
		return err
	}

	return nil
}

func flattenAzureRmManagedDiskProperties(properties *disk.Properties) map[string]interface{} {
	result := make(map[string]interface{})
	result["storage_account_type"] = string(properties.AccountType)
	if properties.DiskSizeGB != nil {
		result["disk_size_gb"] = *properties.DiskSizeGB
	}
	if properties.OsType != "" {
		result["os_type"] = string(properties.OsType)
	}

	return result
}

func flattenAzureRmManagedDiskCreationData(creationData *disk.CreationData) map[string]interface{} {
	result := make(map[string]interface{})
	result["create_option"] = string(creationData.CreateOption)
	if creationData.SourceURI != nil {
		result["source_uri"] = *creationData.SourceURI
	}

	return result
}
<commit_msg>disk_size_gb is required<commit_after>package azurerm

import (
	"fmt"
	"github.com/Azure/azure-sdk-for-go/arm/disk"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"log"
	"net/http"
	"strings"
)

func resourceArmManagedDisk() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmManagedDiskCreate,
		Read:   resourceArmManagedDiskRead,
		Update: resourceArmManagedDiskCreate,
		Delete: resourceArmManagedDiskDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"location": locationSchema(),

			"resource_group_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"storage_account_type": {
				Type:     schema.TypeString,
				Required: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.PremiumLRS),
					string(disk.StandardLRS),
				}, true),
			},

			"create_option": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.Import),
					string(disk.Empty),
					string(disk.Copy),
				}, true),
			},

			"source_uri": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"source_resource_id": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"os_type": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(disk.Windows),
					string(disk.Linux),
				}, true),
			},

			"disk_size_gb": {
				Type:         schema.TypeInt,
				Required:     true,
				ValidateFunc: validateDiskSizeGB,
			},

			"tags": tagsSchema(),
		},
	}
}

func validateDiskSizeGB(v interface{}, k string) (ws []string, errors []error) {
	value := v.(int)
	if value < 1 || value > 1023 {
		errors = append(errors, fmt.Errorf(
			"The `disk_size_gb` can only be between 1 and 1023"))
	}
	return
}

func resourceArmManagedDiskCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient)
	diskClient := client.diskClient

	log.Printf("[INFO] preparing arguments for Azure ARM Managed Disk creation.")

	name := d.Get("name").(string)
	location := d.Get("location").(string)
	resGroup := d.Get("resource_group_name").(string)
	tags := d.Get("tags").(map[string]interface{})
	expandedTags := expandTags(tags)

	createDisk := disk.Model{
		Name:     &name,
		Location: &location,
		Tags:     expandedTags,
	}

	storageAccountType := d.Get("storage_account_type").(string)
	osType := d.Get("os_type").(string)

	createDisk.Properties = &disk.Properties{
		AccountType: disk.StorageAccountTypes(storageAccountType),
		OsType:      disk.OperatingSystemTypes(osType),
	}

	if v := d.Get("disk_size_gb"); v != 0 {
		diskSize := int32(v.(int))
		createDisk.Properties.DiskSizeGB = &diskSize
	}
	createOption := d.Get("create_option").(string)

	creationData := &disk.CreationData{
		CreateOption: disk.CreateOption(createOption),
	}

	if strings.EqualFold(createOption, string(disk.Import)) {
		if sourceUri := d.Get("source_uri").(string); sourceUri != "" {
			creationData.SourceURI = &sourceUri
		} else {
			return fmt.Errorf("[ERROR] source_uri must be specified when create_option is `%s`", disk.Import)
		}
	} else if strings.EqualFold(createOption, string(disk.Copy)) {
		if sourceResourceId := d.Get("source_resource_id").(string); sourceResourceId != "" {
			creationData.SourceResourceID = &sourceResourceId
		} else {
			return fmt.Errorf("[ERROR] source_resource_id must be specified when create_option is `%s`", disk.Copy)
		}
	}

	createDisk.CreationData = creationData

	_, diskErr := diskClient.CreateOrUpdate(resGroup, name, createDisk, make(chan struct{}))
	if diskErr != nil {
		return diskErr
	}

	read, err := diskClient.Get(resGroup, name)
	if err != nil {
		return err
	}
	if read.ID == nil {
		return fmt.Errorf("[ERROR] Cannot read Managed Disk %s (resource group %s) ID", name, resGroup)
	}

	d.SetId(*read.ID)

	return resourceArmManagedDiskRead(d, meta)
}

func resourceArmManagedDiskRead(d *schema.ResourceData, meta interface{}) error {
	diskClient := meta.(*ArmClient).diskClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["disks"]

	resp, err := diskClient.Get(resGroup, name)
	if err != nil {
		if resp.StatusCode == http.StatusNotFound {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("[ERROR] Error making Read request on Azure Managed Disk %s (resource group %s): %s", name, resGroup, err)
	}

	d.Set("name", resp.Name)
	d.Set("resource_group_name", resGroup)
	d.Set("location", resp.Location)

	if resp.Properties != nil {
		m := flattenAzureRmManagedDiskProperties(resp.Properties)
		d.Set("storage_account_type", m["storage_account_type"])
		d.Set("disk_size_gb", m["disk_size_gb"])
		if m["os_type"] != nil {
			d.Set("os_type", m["os_type"])
		}
	}

	if resp.CreationData != nil {
		m := flattenAzureRmManagedDiskCreationData(resp.CreationData)
		d.Set("create_option", m["create_option"])
		if m["source_uri"] != nil {
			d.Set("source_uri", m["source_uri"])
		}
		if m["source_resource_id"] != nil {
			d.Set("source_resource_id", m["source_resource_id"])
		}
	}

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmManagedDiskDelete(d *schema.ResourceData, meta interface{}) error {
	diskClient := meta.(*ArmClient).diskClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["disks"]

	if _, err = diskClient.Delete(resGroup, name, make(chan struct{})); err != nil {
		return err
	}

	return nil
}

func flattenAzureRmManagedDiskProperties(properties *disk.Properties) map[string]interface{} {
	result := make(map[string]interface{})
	result["storage_account_type"] = string(properties.AccountType)
	if properties.DiskSizeGB != nil {
		result["disk_size_gb"] = *properties.DiskSizeGB
	}
	if properties.OsType != "" {
		result["os_type"] = string(properties.OsType)
	}

	return result
}

func flattenAzureRmManagedDiskCreationData(creationData *disk.CreationData) map[string]interface{} {
	result := make(map[string]interface{})
	result["create_option"] = string(creationData.CreateOption)
	if creationData.SourceURI != nil {
		result["source_uri"] = *creationData.SourceURI
	}

	return result
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
)

func resourceComputeSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceComputeSnapshotCreate,
		Read:   resourceComputeSnapshotRead,
		Delete: resourceComputeSnapshotDelete,
		Exists: resourceComputeSnapshotExists,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"snapshot_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"snapshot_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"source_disk_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"source_disk_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"source_disk": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"self_link": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceComputeSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Build the snapshot parameter
	snapshot := &compute.Snapshot{
		Name: d.Get("name").(string),
	}

	source_disk := d.Get("source_disk").(string)

	if v, ok := d.GetOk("snapshot_encryption_key_raw"); ok {
		snapshot.SnapshotEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SnapshotEncryptionKey.RawKey = v.(string)
	}

	if v, ok := d.GetOk("source_disk_encryption_key_raw"); ok {
		snapshot.SourceDiskEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SourceDiskEncryptionKey.RawKey = v.(string)
	}

	op, err := config.clientCompute.Disks.CreateSnapshot(
		project, d.Get("zone").(string), source_disk, snapshot).Do()
	if err != nil {
		return fmt.Errorf("Error creating snapshot: %s", err)
	}

	// It probably maybe worked, so store the ID now
	d.SetId(snapshot.Name)

	err = computeOperationWaitZone(config, op, project, d.Get("zone").(string), "Creating Snapshot")
	if err != nil {
		return err
	}
	return resourceComputeSnapshotRead(d, meta)
}

func resourceComputeSnapshotRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	snapshot, err := config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading snapshot: %s", err)
	}

	d.Set("self_link", snapshot.SelfLink)

	if snapshot.SnapshotEncryptionKey != nil && snapshot.SnapshotEncryptionKey.Sha256 != "" {
		d.Set("snapshot_encryption_key_sha256", snapshot.SnapshotEncryptionKey.Sha256)
	}

	if snapshot.SourceDiskEncryptionKey != nil && snapshot.SourceDiskEncryptionKey.Sha256 != "" {
		d.Set("source_disk_encryption_key_sha256", snapshot.SourceDiskEncryptionKey.Sha256)
	}

	d.Set("source_disk", snapshot.SourceDisk)

	return nil
}

func resourceComputeSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Delete the snapshot
	op, err := config.clientCompute.Snapshots.Delete(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error deleting snapshot: %s", err)
	}

	err = computeOperationWaitGlobal(config, op, project, "Deleting Snapshot")
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceComputeSnapshotExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return false, err
	}

	_, err = config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return false, err
		}
		return true, err
	}
	return true, nil
}
<commit_msg>Added a new attribute : source_disk_link<commit_after>package google

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
)

func resourceComputeSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceComputeSnapshotCreate,
		Read:   resourceComputeSnapshotRead,
		Delete: resourceComputeSnapshotDelete,
		Exists: resourceComputeSnapshotExists,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"snapshot_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"snapshot_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"source_disk_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"source_disk_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"source_disk": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"source_disk_link": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"self_link": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceComputeSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Build the snapshot parameter
	snapshot := &compute.Snapshot{
		Name: d.Get("name").(string),
	}

	source_disk := d.Get("source_disk").(string)

	if v, ok := d.GetOk("snapshot_encryption_key_raw"); ok {
		snapshot.SnapshotEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SnapshotEncryptionKey.RawKey = v.(string)
	}

	if v, ok := d.GetOk("source_disk_encryption_key_raw"); ok {
		snapshot.SourceDiskEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SourceDiskEncryptionKey.RawKey = v.(string)
	}

	op, err := config.clientCompute.Disks.CreateSnapshot(
		project, d.Get("zone").(string), source_disk, snapshot).Do()
	if err != nil {
		return fmt.Errorf("Error creating snapshot: %s", err)
	}

	// It probably maybe worked, so store the ID now
	d.SetId(snapshot.Name)

	err = computeOperationWaitZone(config, op, project, d.Get("zone").(string), "Creating Snapshot")
	if err != nil {
		return err
	}
	return resourceComputeSnapshotRead(d, meta)
}

func resourceComputeSnapshotRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	snapshot, err := config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading snapshot: %s", err)
	}

	d.Set("self_link", snapshot.SelfLink)
	d.Set("source_disk_link", snapshot.SourceDisk)
	d.Set("name", snapshot.Name)

	if snapshot.SnapshotEncryptionKey != nil && snapshot.SnapshotEncryptionKey.Sha256 != "" {
		d.Set("snapshot_encryption_key_sha256", snapshot.SnapshotEncryptionKey.Sha256)
	}

	if snapshot.SourceDiskEncryptionKey != nil && snapshot.SourceDiskEncryptionKey.Sha256 != "" {
		d.Set("source_disk_encryption_key_sha256", snapshot.SourceDiskEncryptionKey.Sha256)
	}

	return nil
}

func resourceComputeSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Delete the snapshot
	op, err := config.clientCompute.Snapshots.Delete(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error deleting snapshot: %s", err)
	}

	err = computeOperationWaitGlobal(config, op, project, "Deleting Snapshot")
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceComputeSnapshotExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return false, err
	}

	_, err = config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return false, err
		}
		return true, err
	}
	return true, nil
}
<|endoftext|>


<commit_before>package linux_backend

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden-linux/sysinfo"
	"github.com/pivotal-golang/lager"
)

//go:generate counterfeiter . Container
type Container interface {
	ID() string
	HasProperties(garden.Properties) bool
	GraceTime() time.Duration

	Start() error

	Snapshot(io.Writer) error
	ResourceSpec() LinuxContainerSpec
	Restore(LinuxContainerSpec) error
	Cleanup() error

	garden.Container
}

//go:generate counterfeiter . ResourcePool
type ResourcePool interface {
	Setup() error
	Acquire(garden.ContainerSpec) (LinuxContainerSpec, error)
	Restore(io.Reader) (LinuxContainerSpec, error)
	Release(LinuxContainerSpec) error
	Prune(keep map[string]bool) error
	MaxContainers() int
}

//go:generate counterfeiter . ContainerProvider
type ContainerProvider interface {
	ProvideContainer(LinuxContainerSpec) Container
}

type ContainerRepository interface {
	All() []Container
	Add(Container)
	FindByHandle(string) (Container, error)
	Query(filter func(Container) bool, logger lager.Logger) []Container
	Delete(Container)
}

//go:generate counterfeiter . HealthChecker
type HealthChecker interface {
	HealthCheck() error
}

type LinuxBackend struct {
	logger lager.Logger

	resourcePool ResourcePool
	systemInfo   sysinfo.Provider
	healthCheck  HealthChecker

	snapshotsPath string
	maxContainers int

	containerRepo     ContainerRepository
	containerProvider ContainerProvider
}

type HandleExistsError struct {
	Handle string
}

func (e HandleExistsError) Error() string {
	return fmt.Sprintf("handle already exists: %s", e.Handle)
}

type FailedToSnapshotError struct {
	OriginalError error
}

func (e FailedToSnapshotError) Error() string {
	return fmt.Sprintf("failed to save snapshot: %s", e.OriginalError)
}

type MaxContainersReachedError struct {
	MaxContainers int
}

func (e MaxContainersReachedError) Error() string {
	return fmt.Sprintf("cannot create more than %d containers", e.MaxContainers)
}

func New(
	logger lager.Logger,
	resourcePool ResourcePool,
	containerRepo ContainerRepository,
	containerProvider ContainerProvider,
	systemInfo sysinfo.Provider,
	healthCheck HealthChecker,
	snapshotsPath string,
	maxContainers int,
) *LinuxBackend {
	return &LinuxBackend{
		logger: logger.Session("backend"),

		resourcePool:  resourcePool,
		systemInfo:    systemInfo,
		healthCheck:   healthCheck,
		snapshotsPath: snapshotsPath,
		maxContainers: maxContainers,

		containerRepo:     containerRepo,
		containerProvider: containerProvider,
	}
}

func (b *LinuxBackend) Setup() error {
	return b.resourcePool.Setup()
}

func (b *LinuxBackend) Start() error {
	if b.snapshotsPath != "" {
		_, err := os.Stat(b.snapshotsPath)
		if err == nil {
			b.restoreSnapshots()
			os.RemoveAll(b.snapshotsPath)
		}

		err = os.MkdirAll(b.snapshotsPath, 0755)
		if err != nil {
			return err
		}
	}

	keep := map[string]bool{}

	containers := b.containerRepo.All()

	for _, container := range containers {
		keep[container.ID()] = true
	}

	if err := mountSysFs(); err != nil {
		return err
	}

	return b.resourcePool.Prune(keep)
}

func (b *LinuxBackend) Ping() error {
	if err := b.healthCheck.HealthCheck(); err != nil {
		return garden.UnrecoverableError{err.Error()}
	}

	return nil
}

func (b *LinuxBackend) Capacity() (garden.Capacity, error) {
	totalMemory, err := b.systemInfo.TotalMemory()
	if err != nil {
		return garden.Capacity{}, err
	}

	totalDisk, err := b.systemInfo.TotalDisk()
	if err != nil {
		return garden.Capacity{}, err
	}

	maxContainers := b.resourcePool.MaxContainers()
	if b.maxContainers > 0 && maxContainers > b.maxContainers {
		maxContainers = b.maxContainers
	}

	return garden.Capacity{
		MemoryInBytes: totalMemory,
		DiskInBytes:   totalDisk,
		MaxContainers: uint64(maxContainers),
	}, nil
}

func (b *LinuxBackend) Create(spec garden.ContainerSpec) (garden.Container, error) {
	if _, err := b.containerRepo.FindByHandle(spec.Handle); spec.Handle != "" && err == nil {
		return nil, HandleExistsError{Handle: spec.Handle}
	}

	if b.maxContainers > 0 {
		containers := b.containerRepo.All()
		if len(containers) >= b.maxContainers {
			return nil, MaxContainersReachedError{
				MaxContainers: b.maxContainers,
			}
		}
	}

	containerSpec, err := b.resourcePool.Acquire(spec)
	if err != nil {
		return nil, err
	}

	container := b.containerProvider.ProvideContainer(containerSpec)

	if err := container.Start(); err != nil {
		b.resourcePool.Release(containerSpec)
		return nil, err
	}

	if err := b.ApplyLimits(container, spec.Limits); err != nil {
		b.resourcePool.Release(containerSpec)
		return nil, err
	}

	b.containerRepo.Add(container)

	return container, nil
}

func (b *LinuxBackend) ApplyLimits(container garden.Container, limits garden.Limits) error {
	if limits.CPU != (garden.CPULimits{}) {
		if err := container.LimitCPU(limits.CPU); err != nil {
			return err
		}
	}

	if limits.Disk != (garden.DiskLimits{}) {
		if err := container.LimitDisk(limits.Disk); err != nil {
			return err
		}
	}

	if limits.Bandwidth != (garden.BandwidthLimits{}) {
		if err := container.LimitBandwidth(limits.Bandwidth); err != nil {
			return err
		}
	}

	if limits.Memory != (garden.MemoryLimits{}) {
		if err := container.LimitMemory(limits.Memory); err != nil {
			return err
		}
	}

	return nil
}

func (b *LinuxBackend) Destroy(handle string) error {
	container, err := b.containerRepo.FindByHandle(handle)
	if err != nil {
		return err
	}

	err = container.Cleanup()
	if err != nil {
		return err
	}

	err = b.resourcePool.Release(container.ResourceSpec())
	if err != nil {
		return err
	}

	b.containerRepo.Delete(container)

	return nil
}

func (b *LinuxBackend) Containers(props garden.Properties) ([]garden.Container, error) {
	logger := b.logger.Session("containers")
	logger.Debug("started")
	containers := toGardenContainers(b.containerRepo.Query(withProperties(props), logger))
	logger.Debug("ending", lager.Data{"handles": handles(containers)})
	return containers, nil
}

func handles(containers []garden.Container) []string {
	handles := []string{}
	for _, container := range containers {
		handles = append(handles, container.Handle())
	}
	return handles
}

func (b *LinuxBackend) Lookup(handle string) (garden.Container, error) {
	return b.containerRepo.FindByHandle(handle)
}

func (b *LinuxBackend) BulkInfo(handles []string) (map[string]garden.ContainerInfoEntry, error) {
	containers := b.containerRepo.Query(withHandles(handles), nil)

	infos := make(map[string]garden.ContainerInfoEntry)
	for _, container := range containers {
		info, err := container.Info()
		if err != nil {
			infos[container.Handle()] = garden.ContainerInfoEntry{
				Err: garden.NewError(err.Error()),
			}
		} else {
			infos[container.Handle()] = garden.ContainerInfoEntry{
				Info: info,
			}
		}
	}

	return infos, nil
}

func (b *LinuxBackend) BulkMetrics(handles []string) (map[string]garden.ContainerMetricsEntry, error) {
	containers := b.containerRepo.Query(withHandles(handles), nil)

	metrics := make(map[string]garden.ContainerMetricsEntry)
	for _, container := range containers {
		metric, err := container.Metrics()
		if err != nil {
			metrics[container.Handle()] = garden.ContainerMetricsEntry{
				Err: garden.NewError(err.Error()),
			}
		} else {
			metrics[container.Handle()] = garden.ContainerMetricsEntry{
				Metrics: metric,
			}
		}
	}

	return metrics, nil
}

func (b *LinuxBackend) GraceTime(container garden.Container) time.Duration {
	return container.(Container).GraceTime()
}

func (b *LinuxBackend) Stop() {
	for _, container := range b.containerRepo.All() {
		container.Cleanup()
		err := b.saveSnapshot(container)
		if err != nil {
			b.logger.Error("failed-to-save-snapshot", err, lager.Data{
				"container": container.ID(),
			})
		}
	}
}

func (b *LinuxBackend) restoreSnapshots() {
	sLog := b.logger.Session("restore")

	entries, err := ioutil.ReadDir(b.snapshotsPath)
	if err != nil {
		b.logger.Error("failed-to-read-snapshots", err, lager.Data{
			"from": b.snapshotsPath,
		})
	}

	for _, entry := range entries {
		snapshot := path.Join(b.snapshotsPath, entry.Name())

		lLog := sLog.Session("load", lager.Data{
			"snapshot": entry.Name(),
		})

		lLog.Debug("loading")

		file, err := os.Open(snapshot)
		if err != nil {
			lLog.Error("failed-to-open", err)
		}

		_, err = b.restore(file)
		if err != nil {
			lLog.Error("failed-to-restore", err)
		}
	}
}

func (b *LinuxBackend) saveSnapshot(container Container) error {
	if b.snapshotsPath == "" {
		return nil
	}

	b.logger.Info("save-snapshot", lager.Data{
		"container": container.ID(),
	})

	snapshotPath := path.Join(b.snapshotsPath, container.ID())
	snapshot, err := os.Create(snapshotPath)
	if err != nil {
		return &FailedToSnapshotError{err}
	}

	err = container.Snapshot(snapshot)
	if err != nil {
		return &FailedToSnapshotError{err}
	}

	return snapshot.Close()
}

func (b *LinuxBackend) restore(snapshot io.Reader) (garden.Container, error) {
	containerSpec, err := b.resourcePool.Restore(snapshot)
	if err != nil {
		return nil, err
	}

	container := b.containerProvider.ProvideContainer(containerSpec)
	container.Restore(containerSpec)

	b.containerRepo.Add(container)
	return container, nil
}

func withHandles(handles []string) func(Container) bool {
	return func(c Container) bool {
		for _, e := range handles {
			if e == c.Handle() {
				return true
			}
		}
		return false
	}
}

func withProperties(props garden.Properties) func(Container) bool {
	return func(c Container) bool {
		return c.HasProperties(props)
	}
}

func toGardenContainers(cs []Container) []garden.Container {
	var result []garden.Container
	for _, c := range cs {
		result = append(result, c)
	}

	return result
}

func mountSysFs() error {
	// mntpoint, err := os.Stat("/sys")
	// if err != nil {
	// 	return err
	// }

	// parent, err := os.Stat("/")
	// if err != nil {
	// 	return err
	// }

	//mount sysfs if not mounted already
	//if mntpoint.Sys().(*syscall.Stat_t).Dev == parent.Sys().(*syscall.Stat_t).Dev {
	//	err = syscall.Mount("sysfs", "/sys", "sysfs", uintptr(0), "")
	//	if err != nil {
	//		return fmt.Errorf("Mounting sysfs failed: %s", err)
	//	}
	//}

	return nil
}
<commit_msg>Linux Backend uses Linux container implementation with LimitDisk<commit_after>package linux_backend

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden-linux/sysinfo"
	"github.com/pivotal-golang/lager"
)

//go:generate counterfeiter . Container

type Container interface {
	ID() string
	HasProperties(garden.Properties) bool
	GraceTime() time.Duration

	Start() error

	Snapshot(io.Writer) error
	ResourceSpec() LinuxContainerSpec
	Restore(LinuxContainerSpec) error
	Cleanup() error

	LimitDisk(limits garden.DiskLimits) error

	garden.Container
}

//go:generate counterfeiter . ResourcePool

type ResourcePool interface {
	Setup() error
	Acquire(garden.ContainerSpec) (LinuxContainerSpec, error)
	Restore(io.Reader) (LinuxContainerSpec, error)
	Release(LinuxContainerSpec) error
	Prune(keep map[string]bool) error
	MaxContainers() int
}

//go:generate counterfeiter . ContainerProvider

type ContainerProvider interface {
	ProvideContainer(LinuxContainerSpec) Container
}

type ContainerRepository interface {
	All() []Container
	Add(Container)
	FindByHandle(string) (Container, error)
	Query(filter func(Container) bool, logger lager.Logger) []Container
	Delete(Container)
}

//go:generate counterfeiter . HealthChecker

type HealthChecker interface {
	HealthCheck() error
}

type LinuxBackend struct {
	logger lager.Logger

	resourcePool ResourcePool
	systemInfo   sysinfo.Provider
	healthCheck  HealthChecker

	snapshotsPath string
	maxContainers int

	containerRepo     ContainerRepository
	containerProvider ContainerProvider
}

type HandleExistsError struct {
	Handle string
}

func (e HandleExistsError) Error() string {
	return fmt.Sprintf("handle already exists: %s", e.Handle)
}

type FailedToSnapshotError struct {
	OriginalError error
}

func (e FailedToSnapshotError) Error() string {
	return fmt.Sprintf("failed to save snapshot: %s", e.OriginalError)
}

type MaxContainersReachedError struct {
	MaxContainers int
}

func (e MaxContainersReachedError) Error() string {
	return fmt.Sprintf("cannot create more than %d containers", e.MaxContainers)
}

func New(
	logger lager.Logger,
	resourcePool ResourcePool,
	containerRepo ContainerRepository,
	containerProvider ContainerProvider,
	systemInfo sysinfo.Provider,
	healthCheck HealthChecker,
	snapshotsPath string,
	maxContainers int,
) *LinuxBackend {
	return &LinuxBackend{
		logger: logger.Session("backend"),

		resourcePool:  resourcePool,
		systemInfo:    systemInfo,
		healthCheck:   healthCheck,
		snapshotsPath: snapshotsPath,
		maxContainers: maxContainers,

		containerRepo:     containerRepo,
		containerProvider: containerProvider,
	}
}

func (b *LinuxBackend) Setup() error {
	return b.resourcePool.Setup()
}

func (b *LinuxBackend) Start() error {
	if b.snapshotsPath != "" {
		_, err := os.Stat(b.snapshotsPath)
		if err == nil {
			b.restoreSnapshots()
			os.RemoveAll(b.snapshotsPath)
		}

		err = os.MkdirAll(b.snapshotsPath, 0755)
		if err != nil {
			return err
		}
	}

	keep := map[string]bool{}

	containers := b.containerRepo.All()

	for _, container := range containers {
		keep[container.ID()] = true
	}

	if err := mountSysFs(); err != nil {
		return err
	}

	return b.resourcePool.Prune(keep)
}

func (b *LinuxBackend) Ping() error {
	if err := b.healthCheck.HealthCheck(); err != nil {
		return garden.UnrecoverableError{err.Error()}
	}

	return nil
}

func (b *LinuxBackend) Capacity() (garden.Capacity, error) {
	totalMemory, err := b.systemInfo.TotalMemory()
	if err != nil {
		return garden.Capacity{}, err
	}

	totalDisk, err := b.systemInfo.TotalDisk()
	if err != nil {
		return garden.Capacity{}, err
	}

	maxContainers := b.resourcePool.MaxContainers()
	if b.maxContainers > 0 && maxContainers > b.maxContainers {
		maxContainers = b.maxContainers
	}

	return garden.Capacity{
		MemoryInBytes: totalMemory,
		DiskInBytes:   totalDisk,
		MaxContainers: uint64(maxContainers),
	}, nil
}

func (b *LinuxBackend) Create(spec garden.ContainerSpec) (garden.Container, error) {
	if _, err := b.containerRepo.FindByHandle(spec.Handle); spec.Handle != "" && err == nil {
		return nil, HandleExistsError{Handle: spec.Handle}
	}

	if b.maxContainers > 0 {
		containers := b.containerRepo.All()
		if len(containers) >= b.maxContainers {
			return nil, MaxContainersReachedError{
				MaxContainers: b.maxContainers,
			}
		}
	}

	containerSpec, err := b.resourcePool.Acquire(spec)
	if err != nil {
		return nil, err
	}

	container := b.containerProvider.ProvideContainer(containerSpec)

	if err := container.Start(); err != nil {
		b.resourcePool.Release(containerSpec)
		return nil, err
	}

	if err := b.ApplyLimits(container, spec.Limits); err != nil {
		b.resourcePool.Release(containerSpec)
		return nil, err
	}

	b.containerRepo.Add(container)

	return container, nil
}

func (b *LinuxBackend) ApplyLimits(container Container, limits garden.Limits) error {
	if limits.CPU != (garden.CPULimits{}) {
		if err := container.LimitCPU(limits.CPU); err != nil {
			return err
		}
	}

	if limits.Disk != (garden.DiskLimits{}) {
		if err := container.LimitDisk(limits.Disk); err != nil {
			return err
		}
	}

	if limits.Bandwidth != (garden.BandwidthLimits{}) {
		if err := container.LimitBandwidth(limits.Bandwidth); err != nil {
			return err
		}
	}

	if limits.Memory != (garden.MemoryLimits{}) {
		if err := container.LimitMemory(limits.Memory); err != nil {
			return err
		}
	}

	return nil
}

func (b *LinuxBackend) Destroy(handle string) error {
	container, err := b.containerRepo.FindByHandle(handle)
	if err != nil {
		return err
	}

	err = container.Cleanup()
	if err != nil {
		return err
	}

	err = b.resourcePool.Release(container.ResourceSpec())
	if err != nil {
		return err
	}

	b.containerRepo.Delete(container)

	return nil
}

func (b *LinuxBackend) Containers(props garden.Properties) ([]garden.Container, error) {
	logger := b.logger.Session("containers")
	logger.Debug("started")
	containers := toGardenContainers(b.containerRepo.Query(withProperties(props), logger))
	logger.Debug("ending", lager.Data{"handles": handles(containers)})
	return containers, nil
}

func handles(containers []garden.Container) []string {
	handles := []string{}
	for _, container := range containers {
		handles = append(handles, container.Handle())
	}
	return handles
}

func (b *LinuxBackend) Lookup(handle string) (garden.Container, error) {
	return b.containerRepo.FindByHandle(handle)
}

func (b *LinuxBackend) BulkInfo(handles []string) (map[string]garden.ContainerInfoEntry, error) {
	containers := b.containerRepo.Query(withHandles(handles), nil)

	infos := make(map[string]garden.ContainerInfoEntry)
	for _, container := range containers {
		info, err := container.Info()
		if err != nil {
			infos[container.Handle()] = garden.ContainerInfoEntry{
				Err: garden.NewError(err.Error()),
			}
		} else {
			infos[container.Handle()] = garden.ContainerInfoEntry{
				Info: info,
			}
		}
	}

	return infos, nil
}

func (b *LinuxBackend) BulkMetrics(handles []string) (map[string]garden.ContainerMetricsEntry, error) {
	containers := b.containerRepo.Query(withHandles(handles), nil)

	metrics := make(map[string]garden.ContainerMetricsEntry)
	for _, container := range containers {
		metric, err := container.Metrics()
		if err != nil {
			metrics[container.Handle()] = garden.ContainerMetricsEntry{
				Err: garden.NewError(err.Error()),
			}
		} else {
			metrics[container.Handle()] = garden.ContainerMetricsEntry{
				Metrics: metric,
			}
		}
	}

	return metrics, nil
}

func (b *LinuxBackend) GraceTime(container garden.Container) time.Duration {
	return container.(Container).GraceTime()
}

func (b *LinuxBackend) Stop() {
	for _, container := range b.containerRepo.All() {
		container.Cleanup()
		err := b.saveSnapshot(container)
		if err != nil {
			b.logger.Error("failed-to-save-snapshot", err, lager.Data{
				"container": container.ID(),
			})
		}
	}
}

func (b *LinuxBackend) restoreSnapshots() {
	sLog := b.logger.Session("restore")

	entries, err := ioutil.ReadDir(b.snapshotsPath)
	if err != nil {
		b.logger.Error("failed-to-read-snapshots", err, lager.Data{
			"from": b.snapshotsPath,
		})
	}

	for _, entry := range entries {
		snapshot := path.Join(b.snapshotsPath, entry.Name())

		lLog := sLog.Session("load", lager.Data{
			"snapshot": entry.Name(),
		})

		lLog.Debug("loading")

		file, err := os.Open(snapshot)
		if err != nil {
			lLog.Error("failed-to-open", err)
		}

		_, err = b.restore(file)
		if err != nil {
			lLog.Error("failed-to-restore", err)
		}
	}
}

func (b *LinuxBackend) saveSnapshot(container Container) error {
	if b.snapshotsPath == "" {
		return nil
	}

	b.logger.Info("save-snapshot", lager.Data{
		"container": container.ID(),
	})

	snapshotPath := path.Join(b.snapshotsPath, container.ID())
	snapshot, err := os.Create(snapshotPath)
	if err != nil {
		return &FailedToSnapshotError{err}
	}

	err = container.Snapshot(snapshot)
	if err != nil {
		return &FailedToSnapshotError{err}
	}

	return snapshot.Close()
}

func (b *LinuxBackend) restore(snapshot io.Reader) (garden.Container, error) {
	containerSpec, err := b.resourcePool.Restore(snapshot)
	if err != nil {
		return nil, err
	}

	container := b.containerProvider.ProvideContainer(containerSpec)
	container.Restore(containerSpec)

	b.containerRepo.Add(container)
	return container, nil
}

func withHandles(handles []string) func(Container) bool {
	return func(c Container) bool {
		for _, e := range handles {
			if e == c.Handle() {
				return true
			}
		}
		return false
	}
}

func withProperties(props garden.Properties) func(Container) bool {
	return func(c Container) bool {
		return c.HasProperties(props)
	}
}

func toGardenContainers(cs []Container) []garden.Container {
	var result []garden.Container
	for _, c := range cs {
		result = append(result, c)
	}

	return result
}

func mountSysFs() error {
	// mntpoint, err := os.Stat("/sys")
	// if err != nil {
	// 	return err
	// }

	// parent, err := os.Stat("/")
	// if err != nil {
	// 	return err
	// }

	//mount sysfs if not mounted already
	//if mntpoint.Sys().(*syscall.Stat_t).Dev == parent.Sys().(*syscall.Stat_t).Dev {
	//	err = syscall.Mount("sysfs", "/sys", "sysfs", uintptr(0), "")
	//	if err != nil {
	//		return fmt.Errorf("Mounting sysfs failed: %s", err)
	//	}
	//}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Gravitational, Inc.

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 utils

import (
	"bytes"
	"io"
)

// NewSyncBuffer returns new in memory buffer
func NewSyncBuffer() *SyncBuffer {
	reader, writer := io.Pipe()
	buf := &bytes.Buffer{}
	go func() {
		io.Copy(buf, reader)
	}()
	return &SyncBuffer{
		reader: reader,
		writer: writer,
		buf:    buf,
	}
}

// SyncBuffer is in memory bytes buffer that is
// safe for concurrent writes
type SyncBuffer struct {
	reader *io.PipeReader
	writer *io.PipeWriter
	buf    *bytes.Buffer
}

func (b *SyncBuffer) Write(data []byte) (n int, err error) {
	return b.writer.Write(data)
}

// String returns contents of the buffer
// after this call, all writes will fail
func (b *SyncBuffer) String() string {
	b.Close()
	return b.buf.String()
}

// Bytes returns contents of the buffer
// after this call, all writes will fail
func (b *SyncBuffer) Bytes() []byte {
	b.Close()
	return b.buf.Bytes()
}

// Close closes reads and writes on the buffer
func (b *SyncBuffer) Close() error {
	err := b.reader.Close()
	err2 := b.writer.Close()
	if err != nil {
		return err
	}
	return err2
}
<commit_msg>Fix a data race in utils.SyncBuffer<commit_after>/*
Copyright 2018 Gravitational, Inc.

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 utils

import (
	"bytes"
	"io"
)

// NewSyncBuffer returns new in memory buffer
func NewSyncBuffer() *SyncBuffer {
	reader, writer := io.Pipe()
	buf := &bytes.Buffer{}
	copyDone := make(chan struct{})
	go func() {
		defer close(copyDone)
		io.Copy(buf, reader)
	}()
	return &SyncBuffer{
		reader:   reader,
		writer:   writer,
		buf:      buf,
		copyDone: copyDone,
	}
}

// SyncBuffer is in memory bytes buffer that is
// safe for concurrent writes
type SyncBuffer struct {
	reader *io.PipeReader
	writer *io.PipeWriter
	buf    *bytes.Buffer
	// copyDone makes SyncBuffer.Close block until io.Copy goroutine finishes.
	// This prevents data races between io.Copy and SyncBuffer.String/Bytes.
	copyDone chan struct{}
}

func (b *SyncBuffer) Write(data []byte) (n int, err error) {
	return b.writer.Write(data)
}

// String returns contents of the buffer
// after this call, all writes will fail
func (b *SyncBuffer) String() string {
	b.Close()
	return b.buf.String()
}

// Bytes returns contents of the buffer
// after this call, all writes will fail
func (b *SyncBuffer) Bytes() []byte {
	b.Close()
	return b.buf.Bytes()
}

// Close closes reads and writes on the buffer
func (b *SyncBuffer) Close() error {
	err := b.reader.Close()
	err2 := b.writer.Close()

	// Explicitly wait for io.Copy goroutine to finish.
	<-b.copyDone

	if err != nil {
		return err
	}
	return err2
}
<|endoftext|>


<commit_before>package types

import (
	"github.com/asuleymanov/golos-go/encoding/transaction"
)

//CommentOperation represents comment operation data.
type CommentOperation struct {
	ParentAuthor   string           `json:"parent_author"`
	ParentPermlink string           `json:"parent_permlink"`
	Author         string           `json:"author"`
	Permlink       string           `json:"permlink"`
	Title          string           `json:"title"`
	Body           string           `json:"body"`
	JSONMetadata   *ContentMetadata `json:"json_metadata"`
}

//Type function that defines the type of operation CommentOperation.
func (op *CommentOperation) Type() OpType {
	return TypeComment
}

//Data returns the operation data CommentOperation.
func (op *CommentOperation) Data() interface{} {
	return op
}

//IsStoryOperation function specifies the type of publication.
func (op *CommentOperation) IsStoryOperation() bool {
	return op.ParentAuthor == ""
}

//MarshalTransaction is a function of converting type CommentOperation to bytes.
func (op *CommentOperation) MarshalTransaction(encoder *transaction.Encoder) error {
	enc := transaction.NewRollingEncoder(encoder)
	enc.EncodeUVarint(uint64(TypeComment.Code()))
	if !op.IsStoryOperation() {
		enc.Encode(op.ParentAuthor)
	} else {
		enc.Encode(byte(0))
	}
	enc.Encode(op.ParentPermlink)
	enc.Encode(op.Author)
	enc.Encode(op.Permlink)
	enc.Encode(op.Title)
	enc.Encode(op.Body)
	enc.Encode(op.JSONMetadata)
	return enc.Err()
}
<commit_msg>Update operation_comment.go<commit_after>package types

import (
	"github.com/asuleymanov/golos-go/encoding/transaction"
)

//CommentOperation represents comment operation data.
type CommentOperation struct {
	ParentAuthor   string           `json:"parent_author"`
	ParentPermlink string           `json:"parent_permlink"`
	Author         string           `json:"author"`
	Permlink       string           `json:"permlink"`
	Title          string           `json:"title"`
	Body           string           `json:"body"`
	JSONMetadata   *ContentMetadata `json:"json_metadata"`
}

//Type function that defines the type of operation CommentOperation.
func (op *CommentOperation) Type() OpType {
	return TypeComment
}

//Data returns the operation data CommentOperation.
func (op *CommentOperation) Data() interface{} {
	return op
}

//IsStoryOperation function specifies the type of publication.
func (op *CommentOperation) IsStory() bool {
	return op.ParentAuthor == ""
}

//MarshalTransaction is a function of converting type CommentOperation to bytes.
func (op *CommentOperation) MarshalTransaction(encoder *transaction.Encoder) error {
	enc := transaction.NewRollingEncoder(encoder)
	enc.EncodeUVarint(uint64(TypeComment.Code()))
	if !op.IsStoryOperation() {
		enc.Encode(op.ParentAuthor)
	} else {
		enc.Encode(byte(0))
	}
	enc.Encode(op.ParentPermlink)
	enc.Encode(op.Author)
	enc.Encode(op.Permlink)
	enc.Encode(op.Title)
	enc.Encode(op.Body)
	enc.Encode(op.JSONMetadata)
	return enc.Err()
}
<|endoftext|>