<commit_before>package helpers

import (
	"fmt"
	"os"

	"github.com/BurntSushi/toml"
	"github.com/pkg/errors"
)

type BuildpackTOML struct {
	API       string `toml:"api"`
	Buildpack struct {
		ID       string `toml:"id"`
		Name     string `toml:"name"`
		Version  string `toml:"version"`
		Homepage string `toml:"homepage,omitempty"`
	} `toml:"buildpack"`
	Metadata Metadata `toml:"metadata"`
	Orders   []Order  `toml:"order"`
	Stacks   []Stack  `toml:"stacks"`
}

type Metadata map[string]interface{}

type Order struct {
	Group []Group `toml:"group"`
}

type Group struct {
	ID       string `toml:"id"`
	Version  string `toml:"version"`
	Optional bool   `toml:"optional,omitempty"`
}

type Stack struct {
	ID     string   `toml:"id"`
	Mixins []string `toml:"mixins,omitempty"`
}

type Dependency struct {
	DeprecationDate string   `mapstructure:"deprecation_date" toml:"deprecation_date,omitempty"`
	ID              string   `toml:"id"`
	Name            string   `toml:"name,omitempty"`
	SHA256          string   `toml:"sha256"`
	Source          string   `toml:"source,omitempty"`
	SourceSHA256    string   `mapstructure:"source_sha256" toml:"source_sha256,omitempty"`
	Stacks          []string `toml:"stacks"`
	URI             string   `toml:"uri"`
	Version         string   `toml:"version"`
}

const (
	IncludeFilesKey    = "include_files"
	PrePackageKey      = "pre_package"
	DependenciesKey    = "dependencies"
	DefaultVersionsKey = "default-versions"
	RuntimeToSDKsKey   = "runtime-to-sdks"
)

// This wont work until golang 1.13
//func (buildpackTOML *BuildpackTOML) RemoveEmptyMetadataFields() {
//	for k, v := range buildpackTOML.Metadata {
//		value := reflect.ValueOf(v)
//		if value.IsZero(v) {
//			delete(buildpackTOML.Metadata, k)
//		}
//	}
//}

func (buildpackTOML BuildpackTOML) WriteToFile(filepath string) error {
	buildpackTOMLFile, err := os.Create(filepath)
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("failed to open buildpack.toml at: %s", filepath))
	}
	defer buildpackTOMLFile.Close()

	if err := toml.NewEncoder(buildpackTOMLFile).Encode(buildpackTOML); err != nil {
		return errors.Wrap(err, "failed to update the buildpack.toml")
	}
	return nil
}
<commit_msg>Omit empty version field in buildpack.toml<commit_after>package helpers

import (
	"fmt"
	"os"

	"github.com/BurntSushi/toml"
	"github.com/pkg/errors"
)

type BuildpackTOML struct {
	API       string `toml:"api"`
	Buildpack struct {
		ID       string `toml:"id"`
		Name     string `toml:"name"`
		Version  string `toml:"version,omitempty"`
		Homepage string `toml:"homepage,omitempty"`
	} `toml:"buildpack"`
	Metadata Metadata `toml:"metadata"`
	Orders   []Order  `toml:"order"`
	Stacks   []Stack  `toml:"stacks"`
}

type Metadata map[string]interface{}

type Order struct {
	Group []Group `toml:"group"`
}

type Group struct {
	ID       string `toml:"id"`
	Version  string `toml:"version"`
	Optional bool   `toml:"optional,omitempty"`
}

type Stack struct {
	ID     string   `toml:"id"`
	Mixins []string `toml:"mixins,omitempty"`
}

type Dependency struct {
	DeprecationDate string   `mapstructure:"deprecation_date" toml:"deprecation_date,omitempty"`
	ID              string   `toml:"id"`
	Name            string   `toml:"name,omitempty"`
	SHA256          string   `toml:"sha256"`
	Source          string   `toml:"source,omitempty"`
	SourceSHA256    string   `mapstructure:"source_sha256" toml:"source_sha256,omitempty"`
	Stacks          []string `toml:"stacks"`
	URI             string   `toml:"uri"`
	Version         string   `toml:"version"`
}

const (
	IncludeFilesKey    = "include_files"
	PrePackageKey      = "pre_package"
	DependenciesKey    = "dependencies"
	DefaultVersionsKey = "default-versions"
	RuntimeToSDKsKey   = "runtime-to-sdks"
)

// This wont work until golang 1.13
//func (buildpackTOML *BuildpackTOML) RemoveEmptyMetadataFields() {
//	for k, v := range buildpackTOML.Metadata {
//		value := reflect.ValueOf(v)
//		if value.IsZero(v) {
//			delete(buildpackTOML.Metadata, k)
//		}
//	}
//}

func (buildpackTOML BuildpackTOML) WriteToFile(filepath string) error {
	buildpackTOMLFile, err := os.Create(filepath)
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("failed to open buildpack.toml at: %s", filepath))
	}
	defer buildpackTOMLFile.Close()

	if err := toml.NewEncoder(buildpackTOMLFile).Encode(buildpackTOML); err != nil {
		return errors.Wrap(err, "failed to update the buildpack.toml")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/logging"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
)

// Begin mock declarations
type mockHandler struct {
	mock.Mock
}

func (m *mockHandler) HandleRequest(workerID int, inRequest CaduceusRequest) {
	return
}

type mockHealthTracker struct {
	mock.Mock
}

func (m *mockHealthTracker) SendEvent(health.HealthFunc) {
	return
}

func (m *mockHealthTracker) IncrementBucket(inSize int) {
	return
}

// Begin test functions
func TestMain(m *testing.M) {
	os.Exit(m.Run())
}

func TestServeHTTP(t *testing.T) {
	assert := assert.New(t)

	logger := logging.DefaultLogger()
	fakeHandler := &mockHandler{}
	fakeHealth := &mockHealthTracker{}

	requestSuccessful := func(func(workerID int)) error {
		return nil
	}

	serverWrapper := &ServerHandler{
		Logger:          logger,
		caduceusHandler: fakeHandler,
		caduceusHealth:  fakeHealth,
		doJob:           requestSuccessful,
	}

	req := httptest.NewRequest("POST", "localhost:8080", strings.NewReader("Test payload."))

	t.Run("TestHappyPath", func(t *testing.T) {
		req.Header.Set("Content-Type", "text/plain")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(202, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestTooManyHeaders", func(t *testing.T) {
		req.Header.Add("Content-Type", "too/many/headers")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(400, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestWrongHeader", func(t *testing.T) {
		req.Header.Del("Content-Type")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(400, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestFullQueue", func(t *testing.T) {
		req.Header.Set("Content-Type", "text/plain")

		w := httptest.NewRecorder()
		requestTimeout := func(func(workerID int)) error {
			return errors.New("Intentional error.")
		}
		serverWrapper.doJob = requestTimeout
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(408, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})
}
<commit_msg>Adding test functions for the worker pool functionality.<commit_after>package main

import (
	"errors"
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/logging"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
)

// Begin mock declarations
type mockHandler struct {
	mock.Mock
}

func (m *mockHandler) HandleRequest(workerID int, inRequest CaduceusRequest) {
	return
}

type mockHealthTracker struct {
	mock.Mock
}

func (m *mockHealthTracker) SendEvent(health.HealthFunc) {
	return
}

func (m *mockHealthTracker) IncrementBucket(inSize int) {
	return
}

// Begin test functions
func TestMain(m *testing.M) {
	os.Exit(m.Run())
}

func TestWorkerPool(t *testing.T) {
	assert := assert.New(t)

	workerPool := WorkerPoolFactory{
		NumWorkers: 1,
		QueueSize:  1,
	}.New()

	t.Run("TestWorkerPoolCreation", func(t *testing.T) {
		assert.NotNil(workerPool)
	})

	t.Run("TestWorkerPoolSend", func(t *testing.T) {
		err := workerPool.Send(func(workerID int) {
			// do nothing
		})

		assert.Nil(err)
	})

	workerPool = WorkerPoolFactory{
		NumWorkers: 1,
		QueueSize:  0,
	}.New()

	t.Run("TestWorkerPoolFullQueue", func(t *testing.T) {
		err := workerPool.Send(func(workerID int) {
			// do nothing
		})

		assert.NotNil(err)
	})
}

func TestServeHTTP(t *testing.T) {
	assert := assert.New(t)

	logger := logging.DefaultLogger()
	fakeHandler := &mockHandler{}
	fakeHealth := &mockHealthTracker{}

	requestSuccessful := func(func(workerID int)) error {
		return nil
	}

	serverWrapper := &ServerHandler{
		Logger:          logger,
		caduceusHandler: fakeHandler,
		caduceusHealth:  fakeHealth,
		doJob:           requestSuccessful,
	}

	req := httptest.NewRequest("POST", "localhost:8080", strings.NewReader("Test payload."))

	t.Run("TestHappyPath", func(t *testing.T) {
		req.Header.Set("Content-Type", "text/plain")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(202, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestTooManyHeaders", func(t *testing.T) {
		req.Header.Add("Content-Type", "too/many/headers")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(400, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestWrongHeader", func(t *testing.T) {
		req.Header.Del("Content-Type")

		w := httptest.NewRecorder()
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(400, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})

	t.Run("TestFullQueue", func(t *testing.T) {
		req.Header.Set("Content-Type", "text/plain")

		w := httptest.NewRecorder()
		requestTimeout := func(func(workerID int)) error {
			return errors.New("Intentional error.")
		}
		serverWrapper.doJob = requestTimeout
		serverWrapper.ServeHTTP(w, req)
		resp := w.Result()

		assert.Equal(408, resp.StatusCode)
		fakeHandler.AssertExpectations(t)
		fakeHealth.AssertExpectations(t)
	})
}
<|endoftext|>


<commit_before>package app_files

import (
	"cf/models"
	"crypto/sha1"
	cffileutils "fileutils"
	"fmt"
	"github.com/cloudfoundry/gofileutils/fileutils"
	"io/ioutil"
	"os"
	"path/filepath"
)

var DefaultIgnoreFiles = []string{
	".cfignore",
	".gitignore",
	".git",
	".svn",
	"_darcs",
	".DS_Store",
}

func AppFilesInDir(dir string) (appFiles []models.AppFileFields, err error) {
	dir, err = filepath.Abs(dir)
	if err != nil {
		return
	}

	err = WalkAppFiles(dir, func(fileName string, fullPath string) (err error) {
		fileInfo, err := os.Lstat(fullPath)
		if err != nil {
			return
		}

		appFile := models.AppFileFields{
			Path: filepath.ToSlash(fileName),
			Size: fileInfo.Size(),
		}

		if fileInfo.IsDir() {
			appFile.Sha1 = "0"
		} else {
			hash := sha1.New()
			err = fileutils.CopyPathToWriter(fullPath, hash)
			if err != nil {
				return
			}
			appFile.Sha1 = fmt.Sprintf("%x", hash.Sum(nil))
		}

		appFiles = append(appFiles, appFile)
		return
	})
	return
}

func CopyFiles(appFiles []models.AppFileFields, fromDir, toDir string) (err error) {
	if err != nil {
		return
	}

	for _, file := range appFiles {
		fromPath := filepath.Join(fromDir, file.Path)
		toPath := filepath.Join(toDir, file.Path)
		err = fileutils.CopyPathToPath(fromPath, toPath)
		if err != nil {
			return
		}
	}
	return
}

func CountFiles(directory string) uint64 {
	var count uint64
	WalkAppFiles(directory, func(_, _ string) error {
		count++
		return nil
	})
	return count
}

func WalkAppFiles(dir string, onEachFile func(string, string) error) (err error) {
	cfIgnore := loadIgnoreFile(dir)
	walkFunc := func(fullPath string, f os.FileInfo, inErr error) (err error) {
		err = inErr
		if err != nil {
			return
		}

		if fullPath == dir {
			return
		}

		if !cffileutils.IsRegular(f) && !f.IsDir() {
			return
		}

		fileRelativePath, _ := filepath.Rel(dir, fullPath)
		fileRelativeUnixPath := filepath.ToSlash(fileRelativePath)

		if !cfIgnore.FileShouldBeIgnored(fileRelativeUnixPath) {
			err = onEachFile(fileRelativePath, fullPath)
		}

		return
	}

	err = filepath.Walk(dir, walkFunc)
	return
}

func loadIgnoreFile(dir string) CfIgnore {
	fileContents, err := ioutil.ReadFile(filepath.Join(dir, ".cfignore"))
	if err == nil {
		return NewCfIgnore(string(fileContents))
	} else {
		return NewCfIgnore("")
	}
}
<commit_msg>Ignore Mercurial metadata by default<commit_after>package app_files

import (
	"cf/models"
	"crypto/sha1"
	cffileutils "fileutils"
	"fmt"
	"github.com/cloudfoundry/gofileutils/fileutils"
	"io/ioutil"
	"os"
	"path/filepath"
)

var DefaultIgnoreFiles = []string{
	".cfignore",
	".gitignore",
	".git",
	".hg",
	".svn",
	"_darcs",
	".DS_Store",
}

func AppFilesInDir(dir string) (appFiles []models.AppFileFields, err error) {
	dir, err = filepath.Abs(dir)
	if err != nil {
		return
	}

	err = WalkAppFiles(dir, func(fileName string, fullPath string) (err error) {
		fileInfo, err := os.Lstat(fullPath)
		if err != nil {
			return
		}

		appFile := models.AppFileFields{
			Path: filepath.ToSlash(fileName),
			Size: fileInfo.Size(),
		}

		if fileInfo.IsDir() {
			appFile.Sha1 = "0"
		} else {
			hash := sha1.New()
			err = fileutils.CopyPathToWriter(fullPath, hash)
			if err != nil {
				return
			}
			appFile.Sha1 = fmt.Sprintf("%x", hash.Sum(nil))
		}

		appFiles = append(appFiles, appFile)
		return
	})
	return
}

func CopyFiles(appFiles []models.AppFileFields, fromDir, toDir string) (err error) {
	if err != nil {
		return
	}

	for _, file := range appFiles {
		fromPath := filepath.Join(fromDir, file.Path)
		toPath := filepath.Join(toDir, file.Path)
		err = fileutils.CopyPathToPath(fromPath, toPath)
		if err != nil {
			return
		}
	}
	return
}

func CountFiles(directory string) uint64 {
	var count uint64
	WalkAppFiles(directory, func(_, _ string) error {
		count++
		return nil
	})
	return count
}

func WalkAppFiles(dir string, onEachFile func(string, string) error) (err error) {
	cfIgnore := loadIgnoreFile(dir)
	walkFunc := func(fullPath string, f os.FileInfo, inErr error) (err error) {
		err = inErr
		if err != nil {
			return
		}

		if fullPath == dir {
			return
		}

		if !cffileutils.IsRegular(f) && !f.IsDir() {
			return
		}

		fileRelativePath, _ := filepath.Rel(dir, fullPath)
		fileRelativeUnixPath := filepath.ToSlash(fileRelativePath)

		if !cfIgnore.FileShouldBeIgnored(fileRelativeUnixPath) {
			err = onEachFile(fileRelativePath, fullPath)
		}

		return
	}

	err = filepath.Walk(dir, walkFunc)
	return
}

func loadIgnoreFile(dir string) CfIgnore {
	fileContents, err := ioutil.ReadFile(filepath.Join(dir, ".cfignore"))
	if err == nil {
		return NewCfIgnore(string(fileContents))
	} else {
		return NewCfIgnore("")
	}
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"net/http"
	"runtime"
	"strings"
)

// StatusError wraps a std error and stores more information (status code, display title/msg and caller info)
type StatusError struct {
	Err     error
	Status  int
	Title   string
	Message string
	File    string
	Line    int
}

// Error returns the underling error string - it should not be shown in production
func (e *StatusError) Error() string {
	return fmt.Sprintf("Status %d at %s : %s", e.Status, e.FileLine(), e.Err)
}

// String returns a string represenation of this error, useful for debugging
func (e *StatusError) String() string {
	return fmt.Sprintf("Status %d at %s : %s %s %s", e.Status, e.FileLine(), e.Title, e.Message, e.Err)
}

// FileLine returns file name and line of error
func (e *StatusError) FileLine() string {
	parts := strings.Split(e.File, "/")
	f := strings.Join(parts[len(parts)-4:len(parts)], "/")
	return fmt.Sprintf("%s:%d", f, e.Line)
}

func (e *StatusError) setupFromArgs(args ...string) *StatusError {
	if e.Err == nil {
		e.Err = fmt.Errorf("Error:%d", e.Status)
	}
	if len(args) > 0 {
		e.Title = args[0]
	}
	if len(args) > 1 {
		e.Message = args[1]
	}
	return e
}

// NotFoundError returns a new StatusError with Status StatusNotFound and optional Title and Message
// Usage return router.NotFoundError(err,"Optional Title", "Optional user-friendly Message")
func NotFoundError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusNotFound, "Not Found", "Sorry, the page you're looking for couldn't be found.")
	return err.setupFromArgs(args...)
}

// InternalError returns a new StatusError with Status StatusInternalServerError and optional Title and Message
// Usage: return router.InternalError(err)
func InternalError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusInternalServerError, "Server Error", "Sorry, something went wrong, please let us know.")
	return err.setupFromArgs(args...)
}

// NotAuthorizedError returns a new StatusError with Status StatusUnauthorized and optional Title and Message
func NotAuthorizedError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusUnauthorized, "Not Allowed", "Sorry, I can't let you do that.")
	return err.setupFromArgs(args...)
}

// BadRequestError returns a new StatusError with Status StatusBadRequest and optional Title and Message
func BadRequestError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusBadRequest, "Bad Request", "Sorry, there was an error processing your request, please check your data.")
	return err.setupFromArgs(args...)
}

// Error returns a new StatusError with code StatusInternalServerError and a generic message
func Error(e error, s int, t string, m string) *StatusError {
	// Get runtime info - use zero values if none available
	_, f, l, _ := runtime.Caller(3)
	err := &StatusError{
		Status:  s,
		Err:     e,
		Title:   t,
		Message: m,
		File:    f,
		Line:    l,
	}
	return err
}

// ToStatusError returns a *StatusError or wraps a standard error in a 500 StatusError
func ToStatusError(e error) *StatusError {
	if err, ok := e.(*StatusError); ok {
		return err
	}
	return Error(e, http.StatusInternalServerError, "Error", "Sorry, an error occurred.")
}
<commit_msg>Updated error stack depth for new mux<commit_after>package server

import (
	"fmt"
	"net/http"
	"runtime"
	"strings"
)

// StatusError wraps a std error and stores more information (status code, display title/msg and caller info)
type StatusError struct {
	Err     error
	Status  int
	Title   string
	Message string
	File    string
	Line    int
}

// Error returns the underling error string - it should not be shown in production
func (e *StatusError) Error() string {
	return fmt.Sprintf("Status %d at %s : %s", e.Status, e.FileLine(), e.Err)
}

// String returns a string represenation of this error, useful for debugging
func (e *StatusError) String() string {
	return fmt.Sprintf("Status %d at %s : %s %s %s", e.Status, e.FileLine(), e.Title, e.Message, e.Err)
}

// FileLine returns file name and line of error
func (e *StatusError) FileLine() string {
	parts := strings.Split(e.File, "/")
	f := strings.Join(parts[len(parts)-4:len(parts)], "/")
	return fmt.Sprintf("%s:%d", f, e.Line)
}

func (e *StatusError) setupFromArgs(args ...string) *StatusError {
	if e.Err == nil {
		e.Err = fmt.Errorf("Error:%d", e.Status)
	}
	if len(args) > 0 {
		e.Title = args[0]
	}
	if len(args) > 1 {
		e.Message = args[1]
	}
	return e
}

// NotFoundError returns a new StatusError with Status StatusNotFound and optional Title and Message
// Usage return router.NotFoundError(err,"Optional Title", "Optional user-friendly Message")
func NotFoundError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusNotFound, "Not Found", "Sorry, the page you're looking for couldn't be found.")
	return err.setupFromArgs(args...)
}

// InternalError returns a new StatusError with Status StatusInternalServerError and optional Title and Message
// Usage: return router.InternalError(err)
func InternalError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusInternalServerError, "Server Error", "Sorry, something went wrong, please let us know.")
	return err.setupFromArgs(args...)
}

// NotAuthorizedError returns a new StatusError with Status StatusUnauthorized and optional Title and Message
func NotAuthorizedError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusUnauthorized, "Not Allowed", "Sorry, I can't let you do that.")
	return err.setupFromArgs(args...)
}

// BadRequestError returns a new StatusError with Status StatusBadRequest and optional Title and Message
func BadRequestError(e error, args ...string) *StatusError {
	err := Error(e, http.StatusBadRequest, "Bad Request", "Sorry, there was an error processing your request, please check your data.")
	return err.setupFromArgs(args...)
}

// Error returns a new StatusError with code StatusInternalServerError and a generic message
func Error(e error, s int, t string, m string) *StatusError {
	// Get runtime info - use zero values if none available
	_, f, l, _ := runtime.Caller(2)
	err := &StatusError{
		Status:  s,
		Err:     e,
		Title:   t,
		Message: m,
		File:    f,
		Line:    l,
	}
	return err
}

// ToStatusError returns a *StatusError or wraps a standard error in a 500 StatusError
func ToStatusError(e error) *StatusError {
	if err, ok := e.(*StatusError); ok {
		return err
	}
	return Error(e, http.StatusInternalServerError, "Error", "Sorry, an error occurred.")
}
<|endoftext|>


<commit_before>package vld

import "fmt"

const (
	ErrValidation    = "ErrValidation"
	ErrRequired      = "ErrRequired"
	ErrStringGT      = "ErrStringGT"
	ErrStringGTE     = "ErrStringGTE"
	ErrStringLT      = "ErrStringLT"
	ErrStringLTE     = "ErrStringLTE"
	ErrStringLength  = "ErrStringLength"
	ErrStringLen     = "ErrStringLen"
	ErrStringMatch   = "ErrStringMatch"
	ErrStringOneOf   = "ErrStringOneOf"
	ErrStringIsEmail = "ErrStringIsEmail"
	ErrNumberRange   = "ErrNumberRange"
	ErrNumberGT      = "ErrNumberGT"
	ErrNumberGTE     = "ErrNumberGTE"
	ErrNumberLT      = "ErrNumberLT"
	ErrNumberLTE     = "ErrNumberLTE"
)

var defaultErrMessage = map[string]string{
	// Used in String, StrPtr, Number
	// ErrValidation when validation add some errors
	ErrValidation: "validation for '%v' failed: %v",

	// ErrRequired when value is required
	ErrRequired: "required",

	// Used in String, StrPtr
	// ErrStringGT when length is not greater than
	ErrStringGT: "length is not greater than %v",

	// ErrStringGTE when length is not greater or equal than
	ErrStringGTE: "length is not greater or equal than %v",

	// ErrStringLT when length is not smaller than
	ErrStringLT: "length is not smaller than %v",

	// ErrStringLTE when length is not smaller or equal than
	ErrStringLTE: "length is not smaller or equal than %v",

	// ErrStringLength when value is out of length
	ErrStringLength: "out of length(min:%v max:%v)",

	// ErrStringLen when value is out of len
	ErrStringLen: "out of len(%v)",

	// ErrStringMatch when value does not match with regex
	ErrStringMatch: "does not match",

	// ErrStringIn value is not one of
	ErrStringOneOf: "value is not one of %v",

	// ErrStringIsEmail value is not a valid email
	ErrStringIsEmail: "value is not a valid email",

	// Used in Number
	// ErrNumberRange when value is out of range
	ErrNumberRange: "out of range(min:%v max:%v)",

	// ErrNumberGT when value is not greater than
	ErrNumberGT: "value is not greater than %v",

	// ErrNumberGTE when value is not greater or equal than
	ErrNumberGTE: "value is not greater or equal than %v",

	// ErrNumberLT when value is not smaller than
	ErrNumberLT: "value is not smaller than %v",

	// ErrNumberLTE when value is not smaller or equal than
	ErrNumberLTE: "value is not smaller or equal than %v",
}

type FormatMessageFunc func(errorID string, args Args) string

var FormatMessage FormatMessageFunc = func(errorID string, args Args) string {
	if format, ok := defaultErrMessage[errorID]; ok {
		return fmt.Sprintf(format, args...)
	}
	return fmt.Sprint(errorID, args)
}
<commit_msg>change comments errors<commit_after>package vld

import "fmt"

const (
	// ErrValidation when validation add some errors
	// Used in String, StrPtr, Number
	ErrValidation = "ErrValidation"

	// ErrRequired when value is required
	ErrRequired = "ErrRequired"

	// ErrStringGT when length is not greater than
	// Used in String, StrPtr
	ErrStringGT = "ErrStringGT"

	// ErrStringGTE when length is not greater or equal than
	ErrStringGTE = "ErrStringGTE"

	// ErrStringLT when length is not smaller than
	ErrStringLT = "ErrStringLT"

	// ErrStringLTE when length is not smaller or equal than
	ErrStringLTE = "ErrStringLTE"

	// ErrStringLength when value is out of length
	ErrStringLength = "ErrStringLength"

	// ErrStringLen when value is out of len
	ErrStringLen = "ErrStringLen"

	// ErrStringMatch when value does not match with regex
	ErrStringMatch = "ErrStringMatch"

	// ErrStringOneOf value is not one of
	ErrStringOneOf = "ErrStringOneOf"

	// ErrStringIsEmail value is not a valid email
	ErrStringIsEmail = "ErrStringIsEmail"

	// ErrNumberRange when value is out of range
	// Used in Number
	ErrNumberRange = "ErrNumberRange"

	// ErrNumberGT when value is not greater than
	ErrNumberGT = "ErrNumberGT"

	// ErrNumberGTE when value is not greater or equal than
	ErrNumberGTE = "ErrNumberGTE"

	// ErrNumberLT when value is not smaller than
	ErrNumberLT = "ErrNumberLT"

	// ErrNumberLTE when value is not smaller or equal than
	ErrNumberLTE = "ErrNumberLTE"
)

var defaultErrMessage = map[string]string{
	ErrValidation:    "validation for '%v' failed: %v",
	ErrRequired:      "required",
	ErrStringGT:      "length is not greater than %v",
	ErrStringGTE:     "length is not greater or equal than %v",
	ErrStringLT:      "length is not smaller than %v",
	ErrStringLTE:     "length is not smaller or equal than %v",
	ErrStringLength:  "out of length(min:%v max:%v)",
	ErrStringLen:     "out of len(%v)",
	ErrStringMatch:   "does not match",
	ErrStringOneOf:   "value is not one of %v",
	ErrStringIsEmail: "value is not a valid email",
	ErrNumberRange:   "out of range(min:%v max:%v)",
	ErrNumberGT:      "value is not greater than %v",
	ErrNumberGTE:     "value is not greater or equal than %v",
	ErrNumberLT:      "value is not smaller than %v",
	ErrNumberLTE:     "value is not smaller or equal than %v",
}

type FormatMessageFunc func(errorID string, args Args) string

var FormatMessage FormatMessageFunc = func(errorID string, args Args) string {
	if format, ok := defaultErrMessage[errorID]; ok {
		return fmt.Sprintf(format, args...)
	}
	return fmt.Sprint(errorID, args)
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safehttp

import (
	"net/http"
	"net/textproto"
)

var disallowedHeaders = map[string]bool{"Set-Cookie": true}

// Header represents the key-value pairs in an HTTP header.
// The keys will be in canonical form, as returned by
// textproto.CanonicalMIMEHeaderKey.
type Header struct {
	wrappedHeader http.Header
	immutable     map[string]bool
}

func newHeader(h http.Header) Header {
	return Header{wrappedHeader: h, immutable: map[string]bool{}}
}

// MarkImmutable marks the header with the name `name` as immutable.
// This header is now read-only. `name` is canonicalized using
// textproto.CanonicalMIMEHeaderKey first.
func (h Header) MarkImmutable(name string) {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return
	}
	h.immutable[name] = true
}

// Set sets the header with the name `name` to the value of `value`.
// `name` is canonicalized using textproto.CanonicalMIMEHeaderKey first.
// If this headers is not immutable, this function removes all other
// values currently associated with this header before setting the new
// value. Returns an error when applied on immutable headers.
func (h Header) Set(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Set(name, value)
	return nil
}

// Add adds a new header with the name `name` and the value `value` to
// the collection of headers. `name` is canonicalized using
// textproto.CanonicalMIMEHeaderKey first. Returns an error when applied
// on immutable headers.
func (h Header) Add(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Add(name, value)
	return nil
}

// Del deletes all headers with name `name`. `name` is canonicalized using
// textproto.CanonicalMIMEHeaderKey first. Returns an error when applied
// on immutable headers.
func (h Header) Del(name string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Del(name)
	return nil
}

// Get returns the value of the first header with the name `name`.
// `name` is canonicalized using textproto.CanonicalMIMEHeaderKey first.
// If no header exists with the name `name` then "" is returned.
func (h Header) Get(name string) string {
	return h.wrappedHeader.Get(name)
}

// Values returns all the values of all the headers with the name `name`.
// `name` is canonicalized using textproto.CanonicalMIMEHeaderKey first.
// If no header exists with the name `name` then nil is returned.
func (h Header) Values(name string) []string {
	return h.wrappedHeader.Values(name)
}

// SetCookie adds the cookie provided as a Set-Cookie header in the header
// collection.
// TODO: Replace http.Cookie with safehttp.Cookie.
func (h Header) SetCookie(cookie *http.Cookie) {
	if v := cookie.String(); v != "" {
		h.wrappedHeader.Add("Set-Cookie", v)
	}
}

// TODO: Add Write, WriteSubset and Clone when needed.

type headerIsImmutableError struct {
	name string
}

func (err headerIsImmutableError) Error() string {
	return "The header with name \"" + err.name + "\" is immutable."
}

type headerIsDisallowedError struct {
	name string
}

func (err headerIsDisallowedError) Error() string {
	return "The header with name \"" + err.name + "\" is disallowed."
}
<commit_msg>Better wording in comments<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safehttp

import (
	"net/http"
	"net/textproto"
)

var disallowedHeaders = map[string]bool{"Set-Cookie": true}

// Header represents the key-value pairs in an HTTP header.
// The keys will be in canonical form, as returned by
// textproto.CanonicalMIMEHeaderKey.
type Header struct {
	wrappedHeader http.Header
	immutable     map[string]bool
}

func newHeader(h http.Header) Header {
	return Header{wrappedHeader: h, immutable: map[string]bool{}}
}

// MarkImmutable marks the header with the given name as immutable.
// This header is now read-only. The name is first canonicalized
// using textproto.CanonicalMIMEHeaderKey.
func (h Header) MarkImmutable(name string) {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return
	}
	h.immutable[name] = true
}

// Set sets the header with the given name to the given value.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If this headers is not immutable, this function removes all other
// values currently associated with this header before setting the new
// value. Returns an error when applied on immutable headers.
func (h Header) Set(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Set(name, value)
	return nil
}

// Add adds a new header with the given name and the given value to
// the collection of headers. The name is first canonicalized using
// textproto.CanonicalMIMEHeaderKey. Returns an error when applied
// on immutable headers.
func (h Header) Add(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Add(name, value)
	return nil
}

// Del deletes all headers with the given name. The name is first
// canonicalized using textproto.CanonicalMIMEHeaderKey. Returns an
// error when applied on immutable headers.
func (h Header) Del(name string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return headerIsDisallowedError{name: name}
	}
	if h.immutable[name] {
		return headerIsImmutableError{name: name}
	}
	h.wrappedHeader.Del(name)
	return nil
}

// Get returns the value of the first header with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the given name then "" is returned.
func (h Header) Get(name string) string {
	return h.wrappedHeader.Get(name)
}

// Values returns all the values of all the headers with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the name `name` then nil is returned.
func (h Header) Values(name string) []string {
	return h.wrappedHeader.Values(name)
}

// SetCookie adds the cookie provided as a Set-Cookie header in the header
// collection.
// TODO: Replace http.Cookie with safehttp.Cookie.
func (h Header) SetCookie(cookie *http.Cookie) {
	if v := cookie.String(); v != "" {
		h.wrappedHeader.Add("Set-Cookie", v)
	}
}

// TODO: Add Write, WriteSubset and Clone when needed.

type headerIsImmutableError struct {
	name string
}

func (err headerIsImmutableError) Error() string {
	return "The header with name \"" + err.name + "\" is immutable."
}

type headerIsDisallowedError struct {
	name string
}

func (err headerIsDisallowedError) Error() string {
	return "The header with name \"" + err.name + "\" is disallowed."
}
<|endoftext|>


<commit_before>// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Binary runsc is an implementation of the Open Container Initiative Runtime
// that runs applications inside a sandbox.
package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"

	"flag"

	"github.com/google/subcommands"
	"gvisor.dev/gvisor/pkg/log"
	"gvisor.dev/gvisor/pkg/sentry/platform"
	"gvisor.dev/gvisor/runsc/boot"
	"gvisor.dev/gvisor/runsc/cmd"
	"gvisor.dev/gvisor/runsc/specutils"
)

var (
	// Although these flags are not part of the OCI spec, they are used by
	// Docker, and thus should not be changed.
	rootDir     = flag.String("root", "", "root directory for storage of container state")
	logFilename = flag.String("log", "", "file path where internal debug information is written, default is stdout")
	logFormat   = flag.String("log-format", "text", "log format: text (default), json, or json-k8s")
	debug       = flag.Bool("debug", false, "enable debug logging")
	showVersion = flag.Bool("version", false, "show version and exit")

	// These flags are unique to runsc, and are used to configure parts of the
	// system that are not covered by the runtime spec.

	// Debugging flags.
	debugLog        = flag.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.")
	logPackets      = flag.Bool("log-packets", false, "enable network packet logging")
	logFD           = flag.Int("log-fd", -1, "file descriptor to log to.  If set, the 'log' flag is ignored.")
	debugLogFD      = flag.Int("debug-log-fd", -1, "file descriptor to write debug logs to.  If set, the 'debug-log-dir' flag is ignored.")
	debugLogFormat  = flag.String("debug-log-format", "text", "log format: text (default), json, or json-k8s")
	alsoLogToStderr = flag.Bool("alsologtostderr", false, "send log messages to stderr")

	// Debugging flags: strace related
	strace         = flag.Bool("strace", false, "enable strace")
	straceSyscalls = flag.String("strace-syscalls", "", "comma-separated list of syscalls to trace. If --strace is true and this list is empty, then all syscalls will be traced.")
	straceLogSize  = flag.Uint("strace-log-size", 1024, "default size (in bytes) to log data argument blobs")

	// Flags that control sandbox runtime behavior.
	platformName       = flag.String("platform", "ptrace", "specifies which platform to use: ptrace (default), kvm")
	network            = flag.String("network", "sandbox", "specifies which network to use: sandbox (default), host, none. Using network inside the sandbox is more secure because it's isolated from the host network.")
	gso                = flag.Bool("gso", true, "enable generic segmenation offload")
	fileAccess         = flag.String("file-access", "exclusive", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.")
	overlay            = flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.")
	watchdogAction     = flag.String("watchdog-action", "log", "sets what action the watchdog takes when triggered: log (default), panic.")
	panicSignal        = flag.Int("panic-signal", -1, "register signal handling that panics. Usually set to SIGUSR2(12) to troubleshoot hangs. -1 disables it.")
	profile            = flag.Bool("profile", false, "prepares the sandbox to use Golang profiler. Note that enabling profiler loosens the seccomp protection added to the sandbox (DO NOT USE IN PRODUCTION).")
	netRaw             = flag.Bool("net-raw", false, "enable raw sockets. When false, raw sockets are disabled by removing CAP_NET_RAW from containers (`runsc exec` will still be able to utilize raw sockets). Raw sockets allow malicious containers to craft packets and potentially attack the network.")
	numNetworkChannels = flag.Int("num-network-channels", 1, "number of underlying channels(FDs) to use for network link endpoints.")
	rootless           = flag.Bool("rootless", false, "it allows the sandbox to be started with a user that is not root. Sandbox and Gofer processes may run with same privileges as current user.")

	// Test flags, not to be used outside tests, ever.
	testOnlyAllowRunAsCurrentUserWithoutChroot = flag.Bool("TESTONLY-unsafe-nonroot", false, "TEST ONLY; do not ever use! This skips many security measures that isolate the host from the sandbox.")
)

func main() {
	// Help and flags commands are generated automatically.
	help := cmd.NewHelp(subcommands.DefaultCommander)
	help.Register(new(cmd.Syscalls))
	subcommands.Register(help, "")
	subcommands.Register(subcommands.FlagsCommand(), "")

	// Register user-facing runsc commands.
	subcommands.Register(new(cmd.Checkpoint), "")
	subcommands.Register(new(cmd.Create), "")
	subcommands.Register(new(cmd.Delete), "")
	subcommands.Register(new(cmd.Do), "")
	subcommands.Register(new(cmd.Events), "")
	subcommands.Register(new(cmd.Exec), "")
	subcommands.Register(new(cmd.Gofer), "")
	subcommands.Register(new(cmd.Kill), "")
	subcommands.Register(new(cmd.List), "")
	subcommands.Register(new(cmd.Pause), "")
	subcommands.Register(new(cmd.PS), "")
	subcommands.Register(new(cmd.Restore), "")
	subcommands.Register(new(cmd.Resume), "")
	subcommands.Register(new(cmd.Run), "")
	subcommands.Register(new(cmd.Spec), "")
	subcommands.Register(new(cmd.Start), "")
	subcommands.Register(new(cmd.State), "")
	subcommands.Register(new(cmd.Wait), "")

	// Register internal commands with the internal group name. This causes
	// them to be sorted below the user-facing commands with empty group.
	// The string below will be printed above the commands.
	const internalGroup = "internal use only"
	subcommands.Register(new(cmd.Boot), internalGroup)
	subcommands.Register(new(cmd.Debug), internalGroup)
	subcommands.Register(new(cmd.Gofer), internalGroup)

	// All subcommands must be registered before flag parsing.
	flag.Parse()

	if *testOnlyAllowRunAsCurrentUserWithoutChroot {
		// SIGTERM is sent to all processes if a test exceeds its
		// timeout and this case is handled by syscall_test_runner.
		log.Warningf("Block the TERM signal. This is only safe in tests!")
		signal.Ignore(syscall.SIGTERM)
	}

	// Are we showing the version?
	if *showVersion {
		// The format here is the same as runc.
		fmt.Fprintf(os.Stdout, "runsc version %s\n", version)
		fmt.Fprintf(os.Stdout, "spec: %s\n", specutils.Version)
		os.Exit(0)
	}

	var errorLogger io.Writer
	if *logFD > -1 {
		errorLogger = os.NewFile(uintptr(*logFD), "error log file")

	} else if *logFilename != "" {
		// We must set O_APPEND and not O_TRUNC because Docker passes
		// the same log file for all commands (and also parses these
		// log files), so we can't destroy them on each command.
		var err error
		errorLogger, err = os.OpenFile(*logFilename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			cmd.Fatalf("error opening log file %q: %v", *logFilename, err)
		}
	}
	cmd.ErrorLogger = errorLogger

	platformType := *platformName
	if _, err := platform.Lookup(platformType); err != nil {
		cmd.Fatalf("%v", err)
	}

	fsAccess, err := boot.MakeFileAccessType(*fileAccess)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	if fsAccess == boot.FileAccessShared && *overlay {
		cmd.Fatalf("overlay flag is incompatible with shared file access")
	}

	netType, err := boot.MakeNetworkType(*network)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	wa, err := boot.MakeWatchdogAction(*watchdogAction)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	if *numNetworkChannels <= 0 {
		cmd.Fatalf("num_network_channels must be > 0, got: %d", *numNetworkChannels)
	}

	// Create a new Config from the flags.
	conf := &boot.Config{
		RootDir:            *rootDir,
		Debug:              *debug,
		LogFilename:        *logFilename,
		LogFormat:          *logFormat,
		DebugLog:           *debugLog,
		DebugLogFormat:     *debugLogFormat,
		FileAccess:         fsAccess,
		Overlay:            *overlay,
		Network:            netType,
		GSO:                *gso,
		LogPackets:         *logPackets,
		Platform:           platformType,
		Strace:             *strace,
		StraceLogSize:      *straceLogSize,
		WatchdogAction:     wa,
		PanicSignal:        *panicSignal,
		ProfileEnable:      *profile,
		EnableRaw:          *netRaw,
		NumNetworkChannels: *numNetworkChannels,
		Rootless:           *rootless,
		AlsoLogToStderr:    *alsoLogToStderr,

		TestOnlyAllowRunAsCurrentUserWithoutChroot: *testOnlyAllowRunAsCurrentUserWithoutChroot,
	}
	if len(*straceSyscalls) != 0 {
		conf.StraceSyscalls = strings.Split(*straceSyscalls, ",")
	}

	// Set up logging.
	if *debug {
		log.SetLevel(log.Debug)
	}

	subcommand := flag.CommandLine.Arg(0)

	var e log.Emitter
	if *debugLogFD > -1 {
		f := os.NewFile(uintptr(*debugLogFD), "debug log file")

		// Quick sanity check to make sure no other commands get passed
		// a log fd (they should use log dir instead).
		if subcommand != "boot" && subcommand != "gofer" {
			cmd.Fatalf("flag --debug-log-fd should only be passed to 'boot' and 'gofer' command, but was passed to %q", subcommand)
		}

		// If we are the boot process, then we own our stdio FDs and can do what we
		// want with them. Since Docker and Containerd both eat boot's stderr, we
		// dup our stderr to the provided log FD so that panics will appear in the
		// logs, rather than just disappear.
		if err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd())); err != nil {
			cmd.Fatalf("error dup'ing fd %d to stderr: %v", f.Fd(), err)
		}

		e = newEmitter(*debugLogFormat, f)

	} else if *debugLog != "" {
		f, err := specutils.DebugLogFile(*debugLog, subcommand)
		if err != nil {
			cmd.Fatalf("error opening debug log file in %q: %v", *debugLog, err)
		}
		e = newEmitter(*debugLogFormat, f)

	} else {
		// Stderr is reserved for the application, just discard the logs if no debug
		// log is specified.
		e = newEmitter("text", ioutil.Discard)
	}

	if *alsoLogToStderr {
		e = log.MultiEmitter{e, newEmitter(*debugLogFormat, os.Stderr)}
	}

	log.SetTarget(e)

	log.Infof("***************************")
	log.Infof("Args: %s", os.Args)
	log.Infof("Version %s", version)
	log.Infof("PID: %d", os.Getpid())
	log.Infof("UID: %d, GID: %d", os.Getuid(), os.Getgid())
	log.Infof("Configuration:")
	log.Infof("\t\tRootDir: %s", conf.RootDir)
	log.Infof("\t\tPlatform: %v", conf.Platform)
	log.Infof("\t\tFileAccess: %v, overlay: %t", conf.FileAccess, conf.Overlay)
	log.Infof("\t\tNetwork: %v, logging: %t", conf.Network, conf.LogPackets)
	log.Infof("\t\tStrace: %t, max size: %d, syscalls: %s", conf.Strace, conf.StraceLogSize, conf.StraceSyscalls)
	log.Infof("***************************")

	// Call the subcommand and pass in the configuration.
	var ws syscall.WaitStatus
	subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
	if subcmdCode == subcommands.ExitSuccess {
		log.Infof("Exiting with status: %v", ws)
		if ws.Signaled() {
			// No good way to return it, emulate what the shell does. Maybe raise
			// signall to self?
			os.Exit(128 + int(ws.Signal()))
		}
		os.Exit(ws.ExitStatus())
	}
	// Return an error that is unlikely to be used by the application.
	log.Warningf("Failure to execute command, err: %v", subcmdCode)
	os.Exit(128)
}

func newEmitter(format string, logFile io.Writer) log.Emitter {
	switch format {
	case "text":
		return &log.GoogleEmitter{&log.Writer{Next: logFile}}
	case "json":
		return &log.JSONEmitter{log.Writer{Next: logFile}}
	case "json-k8s":
		return &log.K8sJSONEmitter{log.Writer{Next: logFile}}
	}
	cmd.Fatalf("invalid log format %q, must be 'text', 'json', or 'json-k8s'", format)
	panic("unreachable")
}

func init() {
	// Set default root dir to something (hopefully) user-writeable.
	*rootDir = "/var/run/runsc"
	if runtimeDir := os.Getenv("XDG_RUNTIME_DIR"); runtimeDir != "" {
		*rootDir = filepath.Join(runtimeDir, "runsc")
	}
}
<commit_msg>Log message sent before logging is setup<commit_after>// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Binary runsc is an implementation of the Open Container Initiative Runtime
// that runs applications inside a sandbox.
package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"

	"flag"

	"github.com/google/subcommands"
	"gvisor.dev/gvisor/pkg/log"
	"gvisor.dev/gvisor/pkg/sentry/platform"
	"gvisor.dev/gvisor/runsc/boot"
	"gvisor.dev/gvisor/runsc/cmd"
	"gvisor.dev/gvisor/runsc/specutils"
)

var (
	// Although these flags are not part of the OCI spec, they are used by
	// Docker, and thus should not be changed.
	rootDir     = flag.String("root", "", "root directory for storage of container state")
	logFilename = flag.String("log", "", "file path where internal debug information is written, default is stdout")
	logFormat   = flag.String("log-format", "text", "log format: text (default), json, or json-k8s")
	debug       = flag.Bool("debug", false, "enable debug logging")
	showVersion = flag.Bool("version", false, "show version and exit")

	// These flags are unique to runsc, and are used to configure parts of the
	// system that are not covered by the runtime spec.

	// Debugging flags.
	debugLog        = flag.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.")
	logPackets      = flag.Bool("log-packets", false, "enable network packet logging")
	logFD           = flag.Int("log-fd", -1, "file descriptor to log to.  If set, the 'log' flag is ignored.")
	debugLogFD      = flag.Int("debug-log-fd", -1, "file descriptor to write debug logs to.  If set, the 'debug-log-dir' flag is ignored.")
	debugLogFormat  = flag.String("debug-log-format", "text", "log format: text (default), json, or json-k8s")
	alsoLogToStderr = flag.Bool("alsologtostderr", false, "send log messages to stderr")

	// Debugging flags: strace related
	strace         = flag.Bool("strace", false, "enable strace")
	straceSyscalls = flag.String("strace-syscalls", "", "comma-separated list of syscalls to trace. If --strace is true and this list is empty, then all syscalls will be traced.")
	straceLogSize  = flag.Uint("strace-log-size", 1024, "default size (in bytes) to log data argument blobs")

	// Flags that control sandbox runtime behavior.
	platformName       = flag.String("platform", "ptrace", "specifies which platform to use: ptrace (default), kvm")
	network            = flag.String("network", "sandbox", "specifies which network to use: sandbox (default), host, none. Using network inside the sandbox is more secure because it's isolated from the host network.")
	gso                = flag.Bool("gso", true, "enable generic segmenation offload")
	fileAccess         = flag.String("file-access", "exclusive", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.")
	overlay            = flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.")
	watchdogAction     = flag.String("watchdog-action", "log", "sets what action the watchdog takes when triggered: log (default), panic.")
	panicSignal        = flag.Int("panic-signal", -1, "register signal handling that panics. Usually set to SIGUSR2(12) to troubleshoot hangs. -1 disables it.")
	profile            = flag.Bool("profile", false, "prepares the sandbox to use Golang profiler. Note that enabling profiler loosens the seccomp protection added to the sandbox (DO NOT USE IN PRODUCTION).")
	netRaw             = flag.Bool("net-raw", false, "enable raw sockets. When false, raw sockets are disabled by removing CAP_NET_RAW from containers (`runsc exec` will still be able to utilize raw sockets). Raw sockets allow malicious containers to craft packets and potentially attack the network.")
	numNetworkChannels = flag.Int("num-network-channels", 1, "number of underlying channels(FDs) to use for network link endpoints.")
	rootless           = flag.Bool("rootless", false, "it allows the sandbox to be started with a user that is not root. Sandbox and Gofer processes may run with same privileges as current user.")

	// Test flags, not to be used outside tests, ever.
	testOnlyAllowRunAsCurrentUserWithoutChroot = flag.Bool("TESTONLY-unsafe-nonroot", false, "TEST ONLY; do not ever use! This skips many security measures that isolate the host from the sandbox.")
)

func main() {
	// Help and flags commands are generated automatically.
	help := cmd.NewHelp(subcommands.DefaultCommander)
	help.Register(new(cmd.Syscalls))
	subcommands.Register(help, "")
	subcommands.Register(subcommands.FlagsCommand(), "")

	// Register user-facing runsc commands.
	subcommands.Register(new(cmd.Checkpoint), "")
	subcommands.Register(new(cmd.Create), "")
	subcommands.Register(new(cmd.Delete), "")
	subcommands.Register(new(cmd.Do), "")
	subcommands.Register(new(cmd.Events), "")
	subcommands.Register(new(cmd.Exec), "")
	subcommands.Register(new(cmd.Gofer), "")
	subcommands.Register(new(cmd.Kill), "")
	subcommands.Register(new(cmd.List), "")
	subcommands.Register(new(cmd.Pause), "")
	subcommands.Register(new(cmd.PS), "")
	subcommands.Register(new(cmd.Restore), "")
	subcommands.Register(new(cmd.Resume), "")
	subcommands.Register(new(cmd.Run), "")
	subcommands.Register(new(cmd.Spec), "")
	subcommands.Register(new(cmd.Start), "")
	subcommands.Register(new(cmd.State), "")
	subcommands.Register(new(cmd.Wait), "")

	// Register internal commands with the internal group name. This causes
	// them to be sorted below the user-facing commands with empty group.
	// The string below will be printed above the commands.
	const internalGroup = "internal use only"
	subcommands.Register(new(cmd.Boot), internalGroup)
	subcommands.Register(new(cmd.Debug), internalGroup)
	subcommands.Register(new(cmd.Gofer), internalGroup)

	// All subcommands must be registered before flag parsing.
	flag.Parse()

	// Are we showing the version?
	if *showVersion {
		// The format here is the same as runc.
		fmt.Fprintf(os.Stdout, "runsc version %s\n", version)
		fmt.Fprintf(os.Stdout, "spec: %s\n", specutils.Version)
		os.Exit(0)
	}

	var errorLogger io.Writer
	if *logFD > -1 {
		errorLogger = os.NewFile(uintptr(*logFD), "error log file")

	} else if *logFilename != "" {
		// We must set O_APPEND and not O_TRUNC because Docker passes
		// the same log file for all commands (and also parses these
		// log files), so we can't destroy them on each command.
		var err error
		errorLogger, err = os.OpenFile(*logFilename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			cmd.Fatalf("error opening log file %q: %v", *logFilename, err)
		}
	}
	cmd.ErrorLogger = errorLogger

	platformType := *platformName
	if _, err := platform.Lookup(platformType); err != nil {
		cmd.Fatalf("%v", err)
	}

	fsAccess, err := boot.MakeFileAccessType(*fileAccess)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	if fsAccess == boot.FileAccessShared && *overlay {
		cmd.Fatalf("overlay flag is incompatible with shared file access")
	}

	netType, err := boot.MakeNetworkType(*network)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	wa, err := boot.MakeWatchdogAction(*watchdogAction)
	if err != nil {
		cmd.Fatalf("%v", err)
	}

	if *numNetworkChannels <= 0 {
		cmd.Fatalf("num_network_channels must be > 0, got: %d", *numNetworkChannels)
	}

	// Create a new Config from the flags.
	conf := &boot.Config{
		RootDir:            *rootDir,
		Debug:              *debug,
		LogFilename:        *logFilename,
		LogFormat:          *logFormat,
		DebugLog:           *debugLog,
		DebugLogFormat:     *debugLogFormat,
		FileAccess:         fsAccess,
		Overlay:            *overlay,
		Network:            netType,
		GSO:                *gso,
		LogPackets:         *logPackets,
		Platform:           platformType,
		Strace:             *strace,
		StraceLogSize:      *straceLogSize,
		WatchdogAction:     wa,
		PanicSignal:        *panicSignal,
		ProfileEnable:      *profile,
		EnableRaw:          *netRaw,
		NumNetworkChannels: *numNetworkChannels,
		Rootless:           *rootless,
		AlsoLogToStderr:    *alsoLogToStderr,

		TestOnlyAllowRunAsCurrentUserWithoutChroot: *testOnlyAllowRunAsCurrentUserWithoutChroot,
	}
	if len(*straceSyscalls) != 0 {
		conf.StraceSyscalls = strings.Split(*straceSyscalls, ",")
	}

	// Set up logging.
	if *debug {
		log.SetLevel(log.Debug)
	}

	subcommand := flag.CommandLine.Arg(0)

	var e log.Emitter
	if *debugLogFD > -1 {
		f := os.NewFile(uintptr(*debugLogFD), "debug log file")

		// Quick sanity check to make sure no other commands get passed
		// a log fd (they should use log dir instead).
		if subcommand != "boot" && subcommand != "gofer" {
			cmd.Fatalf("flag --debug-log-fd should only be passed to 'boot' and 'gofer' command, but was passed to %q", subcommand)
		}

		// If we are the boot process, then we own our stdio FDs and can do what we
		// want with them. Since Docker and Containerd both eat boot's stderr, we
		// dup our stderr to the provided log FD so that panics will appear in the
		// logs, rather than just disappear.
		if err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd())); err != nil {
			cmd.Fatalf("error dup'ing fd %d to stderr: %v", f.Fd(), err)
		}

		e = newEmitter(*debugLogFormat, f)

	} else if *debugLog != "" {
		f, err := specutils.DebugLogFile(*debugLog, subcommand)
		if err != nil {
			cmd.Fatalf("error opening debug log file in %q: %v", *debugLog, err)
		}
		e = newEmitter(*debugLogFormat, f)

	} else {
		// Stderr is reserved for the application, just discard the logs if no debug
		// log is specified.
		e = newEmitter("text", ioutil.Discard)
	}

	if *alsoLogToStderr {
		e = log.MultiEmitter{e, newEmitter(*debugLogFormat, os.Stderr)}
	}

	log.SetTarget(e)

	log.Infof("***************************")
	log.Infof("Args: %s", os.Args)
	log.Infof("Version %s", version)
	log.Infof("PID: %d", os.Getpid())
	log.Infof("UID: %d, GID: %d", os.Getuid(), os.Getgid())
	log.Infof("Configuration:")
	log.Infof("\t\tRootDir: %s", conf.RootDir)
	log.Infof("\t\tPlatform: %v", conf.Platform)
	log.Infof("\t\tFileAccess: %v, overlay: %t", conf.FileAccess, conf.Overlay)
	log.Infof("\t\tNetwork: %v, logging: %t", conf.Network, conf.LogPackets)
	log.Infof("\t\tStrace: %t, max size: %d, syscalls: %s", conf.Strace, conf.StraceLogSize, conf.StraceSyscalls)
	log.Infof("***************************")

	if *testOnlyAllowRunAsCurrentUserWithoutChroot {
		// SIGTERM is sent to all processes if a test exceeds its
		// timeout and this case is handled by syscall_test_runner.
		log.Warningf("Block the TERM signal. This is only safe in tests!")
		signal.Ignore(syscall.SIGTERM)
	}

	// Call the subcommand and pass in the configuration.
	var ws syscall.WaitStatus
	subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
	if subcmdCode == subcommands.ExitSuccess {
		log.Infof("Exiting with status: %v", ws)
		if ws.Signaled() {
			// No good way to return it, emulate what the shell does. Maybe raise
			// signall to self?
			os.Exit(128 + int(ws.Signal()))
		}
		os.Exit(ws.ExitStatus())
	}
	// Return an error that is unlikely to be used by the application.
	log.Warningf("Failure to execute command, err: %v", subcmdCode)
	os.Exit(128)
}

func newEmitter(format string, logFile io.Writer) log.Emitter {
	switch format {
	case "text":
		return &log.GoogleEmitter{&log.Writer{Next: logFile}}
	case "json":
		return &log.JSONEmitter{log.Writer{Next: logFile}}
	case "json-k8s":
		return &log.K8sJSONEmitter{log.Writer{Next: logFile}}
	}
	cmd.Fatalf("invalid log format %q, must be 'text', 'json', or 'json-k8s'", format)
	panic("unreachable")
}

func init() {
	// Set default root dir to something (hopefully) user-writeable.
	*rootDir = "/var/run/runsc"
	if runtimeDir := os.Getenv("XDG_RUNTIME_DIR"); runtimeDir != "" {
		*rootDir = filepath.Join(runtimeDir, "runsc")
	}
}
<|endoftext|>


<commit_before>// Package evaler implements a simple fp arithmetic expression evaluator.
//
// Evaler uses Dijkstra's Shunting Yard algorithm [1] to convert an infix
// expression to postfix/RPN format [2], then evaluates the RPN expression.
//
// The operators supported are: + - * / and parentheses ().
//
// [1] http://en.wikipedia.org/wiki/Shunting-yard_algorithm
// [2] http://en.wikipedia.org/wiki/Reverse_Polish_notation

package evaler

import (
	"fmt"
	"github.com/soniah/evaler/stack"
	"math"
	"regexp"
	"strconv"
	"strings"
)

var whitespace_rx = regexp.MustCompile(`\s+`)
var fp_rx = regexp.MustCompile(`(\d+(?:\.\d)?)`) // simple fp number
var operators = "-+**/"

// prec returns the operator's precedence
func prec(op string) int {
	result := 0
	if op == "-" || op == "+" {
		result = 1
	} else if op == "*" || op == "/" {
		result = 2
	} else if op == "**" {
		result = 3
	}
	return result
}

// opGTE returns true if op1's precedence is >= op2
func opGTE(op1, op2 string) bool {
	return prec(op1) >= prec(op2)
}

// isOperator returns true if token is an operator
func isOperator(token string) bool {
	return strings.Contains(operators, token)
}

// isOperand returns true if token is an operand
func isOperand(token string) bool {
	return fp_rx.MatchString(token)
}

// convert2postfix converts an infix expression to postfix
func convert2postfix(tokens []string) []string {
	var stack stack.Stack
	var result []string
	for _, token := range tokens {

		if isOperator(token) {

		OPERATOR:
			for {
				top, err := stack.Top()
				if err == nil && top != "(" {
					if opGTE(top.(string), token) {
						pop, _ := stack.Pop()
						result = append(result, pop.(string))
					} else {
						break OPERATOR
					}
				}
				break OPERATOR
			}
			stack.Push(token)

		} else if token == "(" {
			stack.Push(token)

		} else if token == ")" {
		PAREN:
			for {
				top, err := stack.Top()
				if err == nil && top != "(" {
					pop, _ := stack.Pop()
					result = append(result, pop.(string))
				} else {
					stack.Pop() // pop off "("
					break PAREN
				}
			}

		} else if isOperand(token) {
			result = append(result, token)
		}

	}

	for !stack.IsEmpty() {
		pop, _ := stack.Pop()
		result = append(result, pop.(string))
	}

	return result
}

// evaluatePostfix takes a postfix expression and evaluates it
func evaluatePostfix(postfix []string) float64 {
	var stack stack.Stack
	var result float64
	var fp float64
	for _, token := range postfix {
		if isOperand(token) {
			fp, _ = strconv.ParseFloat(token, 64)
			stack.Push(fp)
		} else if isOperator(token) {
			op2, _ := stack.Pop()
			op1, _ := stack.Pop()
			switch token {
			case "**":
				result = math.Pow(op1.(float64), op2.(float64))
				stack.Push(result)
			case "*":
				result = op1.(float64) * op2.(float64)
				stack.Push(result)
			case "/":
				result = op1.(float64) / op2.(float64)
				stack.Push(result)
			case "+":
				result = op1.(float64) + op2.(float64)
				stack.Push(result)
			case "-":
				result = op1.(float64) - op2.(float64)
				stack.Push(result)
			}
		} else {
			panic("Error")
		}
	}
	retval, _ := stack.Pop()
	return retval.(float64)
}

// tokenise takes an expr string and converts it to a slice of tokens
//
// tokenise puts spaces around all non-numbers, removes leading and
// trailing spaces, then splits on spaces
//
func tokenise(expr string) []string {
	spaced := fp_rx.ReplaceAllString(expr, " ${1} ")
	symbols := []string{"(", ")"}
	for _, symbol := range symbols {
		spaced = strings.Replace(spaced, symbol, fmt.Sprintf(" %s ", symbol), -1)
	}
	stripped := whitespace_rx.ReplaceAllString(strings.TrimSpace(spaced), "|")
	return strings.Split(stripped, "|")
}

// Eval takes an infix string arithmetic expression, and evaluates it
//
// Usage:
//   result, err := evaler.Eval("1+2")
// Returns: the result of the evaluation, and any errors
//
func Eval(expr string) (result float64, err error) {
	defer func() {
		if e := recover(); e != nil {
			result = float64(0.0)
			err = fmt.Errorf("Invalid Expression: %s", expr)
		}
	}()

	tokens := tokenise(expr)
	postfix := convert2postfix(tokens)
	result = evaluatePostfix(postfix)
	if math.IsInf(result, 0) {
		return result, fmt.Errorf("Divide by Zero: %s", expr)
	}
	return result, nil
}

// vim: tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab tw=74
<commit_msg>update doco - supports ** exponent<commit_after>// Package evaler implements a simple fp arithmetic expression evaluator.
//
// Evaler uses Dijkstra's Shunting Yard algorithm [1] to convert an infix
// expression to postfix/RPN format [2], then evaluates the RPN expression.
//
// The operators supported are: + - * / ** and parentheses ().
//
// [1] http://en.wikipedia.org/wiki/Shunting-yard_algorithm
// [2] http://en.wikipedia.org/wiki/Reverse_Polish_notation

package evaler

import (
	"fmt"
	"github.com/soniah/evaler/stack"
	"math"
	"regexp"
	"strconv"
	"strings"
)

var whitespace_rx = regexp.MustCompile(`\s+`)
var fp_rx = regexp.MustCompile(`(\d+(?:\.\d)?)`) // simple fp number
var operators = "-+**/"

// prec returns the operator's precedence
func prec(op string) int {
	result := 0
	if op == "-" || op == "+" {
		result = 1
	} else if op == "*" || op == "/" {
		result = 2
	} else if op == "**" {
		result = 3
	}
	return result
}

// opGTE returns true if op1's precedence is >= op2
func opGTE(op1, op2 string) bool {
	return prec(op1) >= prec(op2)
}

// isOperator returns true if token is an operator
func isOperator(token string) bool {
	return strings.Contains(operators, token)
}

// isOperand returns true if token is an operand
func isOperand(token string) bool {
	return fp_rx.MatchString(token)
}

// convert2postfix converts an infix expression to postfix
func convert2postfix(tokens []string) []string {
	var stack stack.Stack
	var result []string
	for _, token := range tokens {

		if isOperator(token) {

		OPERATOR:
			for {
				top, err := stack.Top()
				if err == nil && top != "(" {
					if opGTE(top.(string), token) {
						pop, _ := stack.Pop()
						result = append(result, pop.(string))
					} else {
						break OPERATOR
					}
				}
				break OPERATOR
			}
			stack.Push(token)

		} else if token == "(" {
			stack.Push(token)

		} else if token == ")" {
		PAREN:
			for {
				top, err := stack.Top()
				if err == nil && top != "(" {
					pop, _ := stack.Pop()
					result = append(result, pop.(string))
				} else {
					stack.Pop() // pop off "("
					break PAREN
				}
			}

		} else if isOperand(token) {
			result = append(result, token)
		}

	}

	for !stack.IsEmpty() {
		pop, _ := stack.Pop()
		result = append(result, pop.(string))
	}

	return result
}

// evaluatePostfix takes a postfix expression and evaluates it
func evaluatePostfix(postfix []string) float64 {
	var stack stack.Stack
	var result float64
	var fp float64
	for _, token := range postfix {
		if isOperand(token) {
			fp, _ = strconv.ParseFloat(token, 64)
			stack.Push(fp)
		} else if isOperator(token) {
			op2, _ := stack.Pop()
			op1, _ := stack.Pop()
			switch token {
			case "**":
				result = math.Pow(op1.(float64), op2.(float64))
				stack.Push(result)
			case "*":
				result = op1.(float64) * op2.(float64)
				stack.Push(result)
			case "/":
				result = op1.(float64) / op2.(float64)
				stack.Push(result)
			case "+":
				result = op1.(float64) + op2.(float64)
				stack.Push(result)
			case "-":
				result = op1.(float64) - op2.(float64)
				stack.Push(result)
			}
		} else {
			panic("Error")
		}
	}
	retval, _ := stack.Pop()
	return retval.(float64)
}

// tokenise takes an expr string and converts it to a slice of tokens
//
// tokenise puts spaces around all non-numbers, removes leading and
// trailing spaces, then splits on spaces
//
func tokenise(expr string) []string {
	spaced := fp_rx.ReplaceAllString(expr, " ${1} ")
	symbols := []string{"(", ")"}
	for _, symbol := range symbols {
		spaced = strings.Replace(spaced, symbol, fmt.Sprintf(" %s ", symbol), -1)
	}
	stripped := whitespace_rx.ReplaceAllString(strings.TrimSpace(spaced), "|")
	return strings.Split(stripped, "|")
}

// Eval takes an infix string arithmetic expression, and evaluates it
//
// Usage:
//   result, err := evaler.Eval("1+2")
// Returns: the result of the evaluation, and any errors
//
func Eval(expr string) (result float64, err error) {
	defer func() {
		if e := recover(); e != nil {
			result = float64(0.0)
			err = fmt.Errorf("Invalid Expression: %s", expr)
		}
	}()

	tokens := tokenise(expr)
	postfix := convert2postfix(tokens)
	result = evaluatePostfix(postfix)
	if math.IsInf(result, 0) {
		return result, fmt.Errorf("Divide by Zero: %s", expr)
	}
	return result, nil
}

// vim: tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab tw=74
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"cmd/go/internal/robustio"
)

func TestAbsolutePath(t *testing.T) {
	t.Parallel()

	tmp, err := ioutil.TempDir("", "TestAbsolutePath")
	if err != nil {
		t.Fatal(err)
	}
	defer robustio.RemoveAll(tmp)

	file := filepath.Join(tmp, "a.go")
	err = ioutil.WriteFile(file, []byte{}, 0644)
	if err != nil {
		t.Fatal(err)
	}
	dir := filepath.Join(tmp, "dir")
	err = os.Mkdir(dir, 0777)
	if err != nil {
		t.Fatal(err)
	}

	noVolume := file[len(filepath.VolumeName(file)):]
	wrongPath := filepath.Join(dir, noVolume)
	cmd := exec.Command(testenv.GoToolPath(t), "build", noVolume)
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err == nil {
		t.Fatal("build should fail")
	}
	if strings.Contains(string(output), wrongPath) {
		t.Fatalf("wrong output found: %v %v", err, string(output))
	}
}
<commit_msg>cmd/go: update go_windows_test to use test go binary<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"cmd/go/internal/robustio"
)

func TestAbsolutePath(t *testing.T) {
	tg := testgo(t)
	defer tg.cleanup()
	tg.parallel()

	tmp, err := ioutil.TempDir("", "TestAbsolutePath")
	if err != nil {
		t.Fatal(err)
	}
	defer robustio.RemoveAll(tmp)

	file := filepath.Join(tmp, "a.go")
	err = ioutil.WriteFile(file, []byte{}, 0644)
	if err != nil {
		t.Fatal(err)
	}
	dir := filepath.Join(tmp, "dir")
	err = os.Mkdir(dir, 0777)
	if err != nil {
		t.Fatal(err)
	}

	noVolume := file[len(filepath.VolumeName(file)):]
	wrongPath := filepath.Join(dir, noVolume)
	cmd := exec.Command(tg.goTool(), "build", noVolume)
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err == nil {
		t.Fatal("build should fail")
	}
	if strings.Contains(string(output), wrongPath) {
		t.Fatalf("wrong output found: %v %v", err, string(output))
	}
}
<|endoftext|>


<commit_before>// Package httpexpect helps to write nice tests for your HTTP API.
//
// Usage examples
//
// See example directory:
//  - https://godoc.org/github.com/gavv/httpexpect/example
//  - https://github.com/gavv/httpexpect/tree/master/example
//
// Communication mode
//
// There are two common ways to test API with httpexpect:
//  - start HTTP server and instruct httpexpect to use HTTP client for communication
//  - don't start server and instruct httpexpect to invoke http handler directly
//
// The second approach works only if the server is a Go module and its handler can
// be imported in tests.
//
// Concrete behaviour is determined by Client implementation passed to Config struct.
// The following implementations are available out of the box:
//  1. http.Client - use regular HTTP client from net/http (you should start server)
//  2. httpexpect.Binder - invoke given http.Handler directly
//  3. fasthttpexpect.ClientAdapter - use client from fasthttp (you should start server)
//  4. fasthttpexpect.Binder - invoke given fasthttp.RequestHandler directly
//
// Note that http handler can be usually obtained from http framework you're using.
// E.g., echo framework provides either http.Handler or fasthttp.RequestHandler.
//
// You can also provide your own Client implementation and do whatever you want to
// convert http.Request to http.Response.
//
// If you're starting server from tests, it's very handy to use net/http/httptest
// for that.
//
// Value equality
//
// Whenever values are checked for equality in httpexpect, they are converted
// to "canonical form":
//  - type aliases are removed
//  - numeric types are converted to float64
//  - non-nil interfaces pointing to nil slices and maps are replaced with nil interfaces
//  - structs are converted to map[string]interface{}
//
// This is equivalent to subsequently json.Marshal() and json.Unmarshal() the value
// and currently is implemented so.
//
// Failure handling
//
// When some check fails, failure is reported. If non-fatal failures are used
// (see Reporter interface), execution is continued and instance that was checked
// is marked as failed.
//
// If specific instance is marked as failed, all subsequent checks are ignored
// for this instance and for any child instances retrieved after failure.
//
// Example:
//  array := NewArray(NewAssertReporter(t), []interface{}{"foo", 123})
//
//  e0 := array.Element(0)  // success
//  e1 := array.Element(1)  // success
//
//  s0 := e0.String()       // success
//  s1 := e1.String()       // failure; e1 and s1 are marked as failed, e0 and s0 are not
//
//  s0.Equal("foo")         // success
//  s1.Equal("bar")         // this check is ignored because s1 is marked as failed
package httpexpect

import (
	"net/http"
	"testing"
)

// Expect is a toplevel object that contains user Config and allows
// to construct Request objects.
type Expect struct {
	config Config
}

// Config contains various settings.
type Config struct {
	// BaseURL is a URL to prepended to all request. My be empty. If
	// non-empty, trailing slash is allowed but not required and is
	// appended automatically.
	BaseURL string

	// Client is used to send http.Request and receive http.Response.
	// Should not be nil.
	//
	// You can use http.DefaultClient or http.Client, or provide
	// custom implementation.
	Client Client

	// Reporter is used to report failures.
	// Should not be nil.
	//
	// You can use AssertReporter, RequireReporter (they use testify),
	// or testing.T, or provide custom implementation.
	Reporter Reporter

	// Printers are used to print requests and responses.
	// May be nil.
	//
	// You can use CompactPrinter or DebugPrinter, or provide custom
	// implementation.
	//
	// You can also use CompactPrinter or DebugPrinter with alternative
	// Logger if you're happy with their format, but want to send logs
	// somewhere else instead of testing.T.
	Printers []Printer
}

// Client is used to send http.Request and receive http.Response.
// http.Client, Binder, fasthttpexpect.ClientAdapter, fasthttpexpect.Binder
// implement this interface.
type Client interface {
	// Do sends request and returns response.
	Do(*http.Request) (*http.Response, error)
}

// Printer is used to print requests and responses.
// CompactPrinter and DebugPrinter implement this interface.
type Printer interface {
	// Request is called before request is sent.
	Request(*http.Request)

	// Response is called after response is received.
	Response(*http.Response)
}

// Logger is used as output backend for Printer.
// testing.T implements this interface.
type Logger interface {
	// Logf writes message to log.
	Logf(fmt string, args ...interface{})
}

// Reporter is used to report failures.
// testing.T implements this interface. AssertReporter and RequireReporter,
// also implement this interface using testify.
type Reporter interface {
	// Errorf reports failure.
	// Allowed to return normally or terminate test using t.FailNow().
	Errorf(message string, args ...interface{})
}

// New returns a new Expect object.
//
// baseURL specifies URL to prepended to all request. My be empty. If non-empty,
// trailing slash is allowed but not required and is appended automatically.
//
// New is a shorthand for WithConfig. It uses:
//  - http.DefaultClient as Client
//  - CompactPrinter as Printer with testing.T as Logger
//  - AssertReporter as Reporter
//
// Example:
//  func TestAPI(t *testing.T) {
//      e := httpexpect.New(t, "http://example.org/")
//      e.GET("/path").Expect().Status(http.StatusOK)
//  }
func New(t *testing.T, baseURL string) *Expect {
	return WithConfig(Config{
		BaseURL:  baseURL,
		Reporter: NewAssertReporter(t),
		Printers: []Printer{
			NewCompactPrinter(t),
		},
	})
}

// WithConfig returns a new Expect object with given config.
//
// If Config.Client is nil, http.DefaultClient is used.
//
// Example:
//  func TestAPI(t *testing.T) {
//      e := httpexpect.WithConfig(httpexpect.Config{
//          BaseURL:  "http://example.org/",
//          Client:   http.DefaultClient,
//          Reporter: httpexpect.NewAssertReporter(t),
//          Printers: []httpexpect.Printer{
//              httpexpect.NewCurlPrinter(t),
//              httpexpect.NewDebugPrinter(t, true)
//          },
//      })
//      e.GET("/path").Expect().Status(http.StatusOK)
//  }
func WithConfig(config Config) *Expect {
	if config.Client == nil {
		config.Client = http.DefaultClient
	}
	if config.Reporter == nil {
		panic("config.Reporter is nil")
	}
	return &Expect{config}
}

// Request is a shorthand for NewRequest(config, method, url, args...).
func (e *Expect) Request(method, url string, args ...interface{}) *Request {
	return NewRequest(e.config, method, url, args...)
}

// OPTIONS is a shorthand for NewRequest(config, "OPTIONS", url, args...).
func (e *Expect) OPTIONS(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "OPTIONS", url, args...)
}

// HEAD is a shorthand for NewRequest(config, "HEAD", url, args...).
func (e *Expect) HEAD(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "HEAD", url, args...)
}

// GET is a shorthand for NewRequest(config, "GET", url, args...).
func (e *Expect) GET(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "GET", url, args...)
}

// POST is a shorthand for NewRequest(config, "POST", url, args...).
func (e *Expect) POST(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "POST", url, args...)
}

// PUT is a shorthand for NewRequest(config, "PUT", url, args...).
func (e *Expect) PUT(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "PUT", url, args...)
}

// PATCH is a shorthand for NewRequest(config, "PATCH", url, args...).
func (e *Expect) PATCH(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "PATCH", url, args...)
}

// DELETE is a shorthand for NewRequest(config, "DELETE", url, args...).
func (e *Expect) DELETE(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "DELETE", url, args...)
}

// Value is a shorthand for NewValue(Config.Reporter, value).
func (e *Expect) Value(value interface{}) *Value {
	return NewValue(e.config.Reporter, value)
}

// Object is a shorthand for NewObject(Config.Reporter, value).
func (e *Expect) Object(value map[string]interface{}) *Object {
	return NewObject(e.config.Reporter, value)
}

// Array is a shorthand for NewArray(Config.Reporter, value).
func (e *Expect) Array(value []interface{}) *Array {
	return NewArray(e.config.Reporter, value)
}

// String is a shorthand for NewString(Config.Reporter, value).
func (e *Expect) String(value string) *String {
	return NewString(e.config.Reporter, value)
}

// Number is a shorthand for NewNumber(Config.Reporter, value).
func (e *Expect) Number(value float64) *Number {
	return NewNumber(e.config.Reporter, value)
}

// Boolean is a shorthand for NewBoolean(Config.Reporter, value).
func (e *Expect) Boolean(value bool) *Boolean {
	return NewBoolean(e.config.Reporter, value)
}
<commit_msg>Update docs<commit_after>// Package httpexpect helps to write nice tests for your HTTP API.
//
// Usage examples
//
// See example directory:
//  - https://godoc.org/github.com/gavv/httpexpect/example
//  - https://github.com/gavv/httpexpect/tree/master/example
//
// Communication mode
//
// There are two common ways to test API with httpexpect:
//  - start HTTP server and instruct httpexpect to use HTTP client for communication
//  - don't start server and instruct httpexpect to invoke http handler directly
//
// The second approach works only if the server is a Go module and its handler can
// be imported in tests.
//
// Concrete behaviour is determined by Client implementation passed to Config struct.
// The following implementations are available out of the box:
//  1. http.Client - use regular HTTP client from net/http (you should start server)
//  2. httpexpect.Binder - invoke given http.Handler directly
//  3. fasthttpexpect.ClientAdapter - use client from fasthttp (you should start server)
//  4. fasthttpexpect.Binder - invoke given fasthttp.RequestHandler directly
//
// Note that http handler can be usually obtained from http framework you're using.
// E.g., echo framework provides either http.Handler or fasthttp.RequestHandler.
//
// You can also provide your own Client implementation and do whatever you want to
// convert http.Request to http.Response.
//
// If you're starting server from tests, it's very handy to use net/http/httptest
// for that.
//
// Value equality
//
// Whenever values are checked for equality in httpexpect, they are converted
// to "canonical form":
//  - type aliases are removed
//  - numeric types are converted to float64
//  - non-nil interfaces pointing to nil slices and maps are replaced with nil interfaces
//  - structs are converted to map[string]interface{}
//
// This is equivalent to subsequently json.Marshal() and json.Unmarshal() the value
// and currently is implemented so.
//
// Failure handling
//
// When some check fails, failure is reported. If non-fatal failures are used
// (see Reporter interface), execution is continued and instance that was checked
// is marked as failed.
//
// If specific instance is marked as failed, all subsequent checks are ignored
// for this instance and for any child instances retrieved after failure.
//
// Example:
//  array := NewArray(NewAssertReporter(t), []interface{}{"foo", 123})
//
//  e0 := array.Element(0)  // success
//  e1 := array.Element(1)  // success
//
//  s0 := e0.String()       // success
//  s1 := e1.String()       // failure; e1 and s1 are marked as failed, e0 and s0 are not
//
//  s0.Equal("foo")         // success
//  s1.Equal("bar")         // this check is ignored because s1 is marked as failed
package httpexpect

import (
	"net/http"
	"testing"
)

// Expect is a toplevel object that contains user Config and allows
// to construct Request objects.
type Expect struct {
	config Config
}

// Config contains various settings.
type Config struct {
	// BaseURL is a URL to prepended to all request. My be empty. If
	// non-empty, trailing slash is allowed but not required and is
	// appended automatically.
	BaseURL string

	// Client is used to send http.Request and receive http.Response.
	// Should not be nil.
	//
	// You can use http.DefaultClient or http.Client, or provide
	// custom implementation.
	Client Client

	// Reporter is used to report failures.
	// Should not be nil.
	//
	// You can use AssertReporter, RequireReporter (they use testify),
	// or testing.T, or provide custom implementation.
	Reporter Reporter

	// Printers are used to print requests and responses.
	// May be nil.
	//
	// You can use CompactPrinter, DebugPrinter, CurlPrinter, or provide
	// custom implementation.
	//
	// You can also use builtin printers with alternative Logger if
	// you're happy with their format, but want to send logs somewhere
	// else instead of testing.T.
	Printers []Printer
}

// Client is used to send http.Request and receive http.Response.
// http.Client, Binder, fasthttpexpect.ClientAdapter, fasthttpexpect.Binder
// implement this interface.
type Client interface {
	// Do sends request and returns response.
	Do(*http.Request) (*http.Response, error)
}

// Printer is used to print requests and responses.
// CompactPrinter, DebugPrinter, and CurlPrinter implement this interface.
type Printer interface {
	// Request is called before request is sent.
	Request(*http.Request)

	// Response is called after response is received.
	Response(*http.Response)
}

// Logger is used as output backend for Printer.
// testing.T implements this interface.
type Logger interface {
	// Logf writes message to log.
	Logf(fmt string, args ...interface{})
}

// Reporter is used to report failures.
// testing.T implements this interface. AssertReporter and RequireReporter,
// also implement this interface using testify.
type Reporter interface {
	// Errorf reports failure.
	// Allowed to return normally or terminate test using t.FailNow().
	Errorf(message string, args ...interface{})
}

// New returns a new Expect object.
//
// baseURL specifies URL to prepended to all request. My be empty. If non-empty,
// trailing slash is allowed but not required and is appended automatically.
//
// New is a shorthand for WithConfig. It uses:
//  - http.DefaultClient as Client
//  - CompactPrinter as Printer with testing.T as Logger
//  - AssertReporter as Reporter
//
// Example:
//  func TestAPI(t *testing.T) {
//      e := httpexpect.New(t, "http://example.org/")
//      e.GET("/path").Expect().Status(http.StatusOK)
//  }
func New(t *testing.T, baseURL string) *Expect {
	return WithConfig(Config{
		BaseURL:  baseURL,
		Reporter: NewAssertReporter(t),
		Printers: []Printer{
			NewCompactPrinter(t),
		},
	})
}

// WithConfig returns a new Expect object with given config.
//
// If Config.Client is nil, http.DefaultClient is used.
//
// Example:
//  func TestAPI(t *testing.T) {
//      e := httpexpect.WithConfig(httpexpect.Config{
//          BaseURL:  "http://example.org/",
//          Client:   http.DefaultClient,
//          Reporter: httpexpect.NewAssertReporter(t),
//          Printers: []httpexpect.Printer{
//              httpexpect.NewCurlPrinter(t),
//              httpexpect.NewDebugPrinter(t, true)
//          },
//      })
//      e.GET("/path").Expect().Status(http.StatusOK)
//  }
func WithConfig(config Config) *Expect {
	if config.Client == nil {
		config.Client = http.DefaultClient
	}
	if config.Reporter == nil {
		panic("config.Reporter is nil")
	}
	return &Expect{config}
}

// Request is a shorthand for NewRequest(config, method, url, args...).
func (e *Expect) Request(method, url string, args ...interface{}) *Request {
	return NewRequest(e.config, method, url, args...)
}

// OPTIONS is a shorthand for NewRequest(config, "OPTIONS", url, args...).
func (e *Expect) OPTIONS(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "OPTIONS", url, args...)
}

// HEAD is a shorthand for NewRequest(config, "HEAD", url, args...).
func (e *Expect) HEAD(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "HEAD", url, args...)
}

// GET is a shorthand for NewRequest(config, "GET", url, args...).
func (e *Expect) GET(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "GET", url, args...)
}

// POST is a shorthand for NewRequest(config, "POST", url, args...).
func (e *Expect) POST(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "POST", url, args...)
}

// PUT is a shorthand for NewRequest(config, "PUT", url, args...).
func (e *Expect) PUT(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "PUT", url, args...)
}

// PATCH is a shorthand for NewRequest(config, "PATCH", url, args...).
func (e *Expect) PATCH(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "PATCH", url, args...)
}

// DELETE is a shorthand for NewRequest(config, "DELETE", url, args...).
func (e *Expect) DELETE(url string, args ...interface{}) *Request {
	return NewRequest(e.config, "DELETE", url, args...)
}

// Value is a shorthand for NewValue(Config.Reporter, value).
func (e *Expect) Value(value interface{}) *Value {
	return NewValue(e.config.Reporter, value)
}

// Object is a shorthand for NewObject(Config.Reporter, value).
func (e *Expect) Object(value map[string]interface{}) *Object {
	return NewObject(e.config.Reporter, value)
}

// Array is a shorthand for NewArray(Config.Reporter, value).
func (e *Expect) Array(value []interface{}) *Array {
	return NewArray(e.config.Reporter, value)
}

// String is a shorthand for NewString(Config.Reporter, value).
func (e *Expect) String(value string) *String {
	return NewString(e.config.Reporter, value)
}

// Number is a shorthand for NewNumber(Config.Reporter, value).
func (e *Expect) Number(value float64) *Number {
	return NewNumber(e.config.Reporter, value)
}

// Boolean is a shorthand for NewBoolean(Config.Reporter, value).
func (e *Expect) Boolean(value bool) *Boolean {
	return NewBoolean(e.config.Reporter, value)
}
<|endoftext|>


<commit_before>// Copyright 2018 Google 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 terminalapi defines the API of all terminal implementations.
package terminalapi

import (
	"context"
	"image"

	"github.com/mum4k/termdash/cell"
)

// Terminal abstracts an implementation of a 2-D terminal.
// A terminal consists of a number of cells.
type Terminal interface {
	// Size returns the terminal width and height in cells.
	Size() image.Point

	// Clear clears the content of the internal back buffer, resetting all
	// cells to their default content and attributes. Sets the provided options
	// on all the cell.
	Clear(opts ...cell.Option) error
	// Flush flushes the internal back buffer to the terminal.
	Flush() error

	// SetCursor sets the position of the cursor.
	SetCursor(p image.Point)
	// HideCursos hides the cursor.
	HideCursor()

	// SetCell sets the value of the specified cell to the provided rune.
	// Use the options to specify which attributes to modify, if an attribute
	// option isn't specified, the attribute retains its previous value.
	SetCell(p image.Point, r rune, opts ...cell.Option) error

	// Event waits for the next event and returns it.
	// This call blocks until the next event or cancellation of the context.
	// Returns nil when the context gets canceled.
	Event(ctx context.Context) Event
}
<commit_msg>Add missing Close() function to terminalapi.Terminal interface<commit_after>// Copyright 2018 Google 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 terminalapi defines the API of all terminal implementations.
package terminalapi

import (
	"context"
	"image"

	"github.com/mum4k/termdash/cell"
)

// Terminal abstracts an implementation of a 2-D terminal.
// A terminal consists of a number of cells.
type Terminal interface {
	// Size returns the terminal width and height in cells.
	Size() image.Point

	// Clear clears the content of the internal back buffer, resetting all
	// cells to their default content and attributes. Sets the provided options
	// on all the cell.
	Clear(opts ...cell.Option) error
	// Flush flushes the internal back buffer to the terminal.
	Flush() error

	// SetCursor sets the position of the cursor.
	SetCursor(p image.Point)
	// HideCursos hides the cursor.
	HideCursor()

	// SetCell sets the value of the specified cell to the provided rune.
	// Use the options to specify which attributes to modify, if an attribute
	// option isn't specified, the attribute retains its previous value.
	SetCell(p image.Point, r rune, opts ...cell.Option) error

	// Event waits for the next event and returns it.
	// This call blocks until the next event or cancellation of the context.
	// Returns nil when the context gets canceled.
	Event(ctx context.Context) Event

	// Close closes the underlying terminal implementation and should be called when
	// the terminal isn't required anymore to return the screen to a sane state.
	Close()
}
<|endoftext|>


<commit_before>package terraform

import (
	"log"

	"github.com/hashicorp/terraform/dag"
)

// GraphNodeAttachResourceState is an interface that can be implemented
// to request that a ResourceState is attached to the node.
type GraphNodeAttachResourceState interface {
	// The address to the resource for the state
	ResourceAddr() *ResourceAddress

	// Sets the state
	AttachResourceState(*ResourceState)
}

// AttachStateTransformer goes through the graph and attaches
// state to nodes that implement the interfaces above.
type AttachStateTransformer struct {
	State *State // State is the root state
}

func (t *AttachStateTransformer) Transform(g *Graph) error {
	// If no state, then nothing to do
	if t.State == nil {
		log.Printf("[DEBUG] Not attaching any state: state is nil")
		return nil
	}

	filter := &StateFilter{State: t.State}
	for _, v := range g.Vertices() {
		// Only care about nodes requesting we're adding state
		an, ok := v.(GraphNodeAttachResourceState)
		if !ok {
			continue
		}
		addr := an.ResourceAddr()

		// Get the module state
		results, err := filter.Filter(addr.String())
		if err != nil {
			return err
		}

		// Attach the first resource state we get
		found := false
		for _, result := range results {
			if rs, ok := result.Value.(*ResourceState); ok {
				log.Printf(
					"[DEBUG] Attaching resource state to %q: %s",
					dag.VertexName(v), rs)
				an.AttachResourceState(rs)
				found = true
				break
			}
		}

		if !found {
			log.Printf(
				"[DEBUG] Resource state not foudn for %q: %s",
				dag.VertexName(v), addr)
		}
	}

	return nil
}
<commit_msg>fix typo<commit_after>package terraform

import (
	"log"

	"github.com/hashicorp/terraform/dag"
)

// GraphNodeAttachResourceState is an interface that can be implemented
// to request that a ResourceState is attached to the node.
type GraphNodeAttachResourceState interface {
	// The address to the resource for the state
	ResourceAddr() *ResourceAddress

	// Sets the state
	AttachResourceState(*ResourceState)
}

// AttachStateTransformer goes through the graph and attaches
// state to nodes that implement the interfaces above.
type AttachStateTransformer struct {
	State *State // State is the root state
}

func (t *AttachStateTransformer) Transform(g *Graph) error {
	// If no state, then nothing to do
	if t.State == nil {
		log.Printf("[DEBUG] Not attaching any state: state is nil")
		return nil
	}

	filter := &StateFilter{State: t.State}
	for _, v := range g.Vertices() {
		// Only care about nodes requesting we're adding state
		an, ok := v.(GraphNodeAttachResourceState)
		if !ok {
			continue
		}
		addr := an.ResourceAddr()

		// Get the module state
		results, err := filter.Filter(addr.String())
		if err != nil {
			return err
		}

		// Attach the first resource state we get
		found := false
		for _, result := range results {
			if rs, ok := result.Value.(*ResourceState); ok {
				log.Printf(
					"[DEBUG] Attaching resource state to %q: %s",
					dag.VertexName(v), rs)
				an.AttachResourceState(rs)
				found = true
				break
			}
		}

		if !found {
			log.Printf(
				"[DEBUG] Resource state not found for %q: %s",
				dag.VertexName(v), addr)
		}
	}

	return nil
}
<|endoftext|>