<commit_before>// Package integration performs initialization and validation for integration
// tests.
package integration

import (
	"bytes"
	"context"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

const (
	TmpTestFilePathDefault  = "/tmp/gollum_test.log"
	TmpTestFilePathFoo    	= "/tmp/gollum_test_foo.log"
	TmpTestFilePathBar    	= "/tmp/gollum_test_bar.log"
)

// ExecuteGollum execute gollum binary for integration testing
func ExecuteGollum(config string, inputs []string, arg ...string) (out bytes.Buffer, err error) {
	if config != "" {
		arg = append(arg, "-c="+getTestConfigPath(config))
	}

	var stdin io.WriteCloser
	timeout := 2 * time.Second
	hasInputValues := len(inputs) > 0

	cmd := GetGollumCmd(timeout, arg...)
	cmd.Stdout = &out

	if hasInputValues {
		stdin, err = cmd.StdinPipe()
		if err != nil {
			return
		}
	}

	err = cmd.Start()
	if err != nil {
		return
	}

	if hasInputValues {
		for _, input := range inputs {
			io.WriteString(stdin, input+"\n")
		}
	}

	// no error handling here because we will get a "signal killed" error
	cmd.Wait()

	return
}

// GetGollumCmd returns gollum Command
func GetGollumCmd(timeout time.Duration, arg ...string) *exec.Cmd {
	var cmd *exec.Cmd

	if timeout > 0 {
		ctx, _ := context.WithTimeout(context.Background(), timeout)
		//defer cancel()

		cmd = exec.CommandContext(ctx, "./gollum", arg...)
	} else {
		cmd = exec.Command("./gollum", arg...)
	}

	cmd.Dir = getGollumPath()

	return cmd
}

type ResultFile struct {
	content string
	lines int
}

// GetResultFile returns file content as a string
func GetResultFile(filepath string) (ResultFile, error) {
	result := ResultFile{}

	// open file
	file, err := os.Open(filepath)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// read file
	b, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}

	file.Seek(0, os.SEEK_SET)
	lineCount, err := lineCounter(file)
	if err != nil {
		panic(err)
	}

	// create result
	result.content = string(b)
	result.lines = lineCount

	return result, nil
}

func lineCounter(r io.Reader) (int, error) {
	buf := make([]byte, 32*1024)
	count := 0
	lineSep := []byte{'\n'}
	hasChars := false

	for {
		c, err := r.Read(buf)

		if len(buf[:c]) > 0 {
			hasChars = true
		}

		count += bytes.Count(buf[:c], lineSep)

		switch {
		case err == io.EOF:
			if count == 0 && hasChars == true {
				count += 1 // one line without "\n"
			}
			return count, nil

		case err != nil:
			return count, err
		}
	}
}

func getGollumPath() (pwd string) {
	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	dir, err := filepath.Abs(pwd + "/../../")
	if err != nil {
		panic(err)
	}

	return dir
}

func getTestConfigPath(configFile string) string {
	baseDir := getGollumPath()

	dir, err := filepath.Abs(baseDir + "/testing/configs/")
	if err != nil {
		panic(err)
	}

	return dir + "/" + configFile
}
<commit_msg>Added sleep for one second for slow disk io during testing<commit_after>// Package integration performs initialization and validation for integration
// tests.
package integration

import (
	"bytes"
	"context"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

const (
	TmpTestFilePathDefault  = "/tmp/gollum_test.log"
	TmpTestFilePathFoo    	= "/tmp/gollum_test_foo.log"
	TmpTestFilePathBar    	= "/tmp/gollum_test_bar.log"
)

// ExecuteGollum execute gollum binary for integration testing
func ExecuteGollum(config string, inputs []string, arg ...string) (out bytes.Buffer, err error) {
	if config != "" {
		arg = append(arg, "-c="+getTestConfigPath(config))
	}

	var stdin io.WriteCloser
	timeout := 2 * time.Second
	hasInputValues := len(inputs) > 0

	cmd := GetGollumCmd(timeout, arg...)
	cmd.Stdout = &out

	if hasInputValues {
		stdin, err = cmd.StdinPipe()
		if err != nil {
			return
		}
	}

	err = cmd.Start()
	if err != nil {
		return
	}

	if hasInputValues {
		for _, input := range inputs {
			io.WriteString(stdin, input+"\n")
		}
	}

	// no error handling here because we will get a "signal killed" error
	cmd.Wait()

	// sleep for one second for slow disk io during testing
	time.Sleep(1 * time.Second)

	return
}

// GetGollumCmd returns gollum Command
func GetGollumCmd(timeout time.Duration, arg ...string) *exec.Cmd {
	var cmd *exec.Cmd

	if timeout > 0 {
		ctx, _ := context.WithTimeout(context.Background(), timeout)
		//defer cancel()

		cmd = exec.CommandContext(ctx, "./gollum", arg...)
	} else {
		cmd = exec.Command("./gollum", arg...)
	}

	cmd.Dir = getGollumPath()

	return cmd
}

type ResultFile struct {
	content string
	lines int
}

// GetResultFile returns file content as a string
func GetResultFile(filepath string) (ResultFile, error) {
	result := ResultFile{}

	// open file
	file, err := os.Open(filepath)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// read file
	b, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}

	file.Seek(0, os.SEEK_SET)
	lineCount, err := lineCounter(file)
	if err != nil {
		panic(err)
	}

	// create result
	result.content = string(b)
	result.lines = lineCount

	return result, nil
}

func lineCounter(r io.Reader) (int, error) {
	buf := make([]byte, 32*1024)
	count := 0
	lineSep := []byte{'\n'}
	hasChars := false

	for {
		c, err := r.Read(buf)

		if len(buf[:c]) > 0 {
			hasChars = true
		}

		count += bytes.Count(buf[:c], lineSep)

		switch {
		case err == io.EOF:
			if count == 0 && hasChars == true {
				count += 1 // one line without "\n"
			}
			return count, nil

		case err != nil:
			return count, err
		}
	}
}

func getGollumPath() (pwd string) {
	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	dir, err := filepath.Abs(pwd + "/../../")
	if err != nil {
		panic(err)
	}

	return dir
}

func getTestConfigPath(configFile string) string {
	baseDir := getGollumPath()

	dir, err := filepath.Abs(baseDir + "/testing/configs/")
	if err != nil {
		panic(err)
	}

	return dir + "/" + configFile
}
<|endoftext|>


<commit_before>package fuse

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"strings"
	"sync/atomic"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"github.com/pachyderm/pachyderm/src/pfs"
	"github.com/pachyderm/pachyderm/src/pfs/pfsutil"
	"golang.org/x/net/context"
)

type filesystem struct {
	apiClient      pfs.ApiClient
	repositoryName string
	commitID       string
	shard          uint64
	modulus        uint64
}

func newFilesystem(
	apiClient pfs.ApiClient,
	repositoryName string,
	commitID string,
	shard uint64,
	modulus uint64,
) *filesystem {
	return &filesystem{
		apiClient,
		repositoryName,
		commitID,
		shard,
		modulus,
	}
}

func (f *filesystem) Root() (fs.Node, error) {
	return &directory{f, f.commitID, true, ""}, nil
}

type directory struct {
	fs       *filesystem
	commitID string
	write    bool
	path     string
}

func (d *directory) Attr(ctx context.Context, a *fuse.Attr) error {
	if d.write {
		a.Mode = os.ModeDir | 0775
	} else {
		a.Mode = os.ModeDir | 0555
	}
	return nil
}

func (d *directory) nodeFromFileInfo(fileInfo *pfs.FileInfo) (fs.Node, error) {
	if fileInfo == nil {
		return nil, fuse.ENOENT
	}
	switch fileInfo.FileType {
	case pfs.FileType_FILE_TYPE_NONE:
		return nil, fuse.ENOENT
	case pfs.FileType_FILE_TYPE_OTHER:
		return nil, fuse.ENOENT
	case pfs.FileType_FILE_TYPE_REGULAR:
		return &file{d.fs, d.commitID, path.Join(d.path, fileInfo.Path.Path), 0,
			int64(fileInfo.SizeBytes)}, nil
	case pfs.FileType_FILE_TYPE_DIR:
		return &directory{d.fs, d.commitID, d.write, fileInfo.Path.Path}, nil
	default:
		return nil, fmt.Errorf("Unrecognized FileType.")
	}
}

func (d *directory) Lookup(ctx context.Context, name string) (fs.Node, error) {
	if d.commitID == "" {
		commitInfo, err := pfsutil.GetCommitInfo(
			d.fs.apiClient,
			d.fs.repositoryName,
			name,
		)
		if err != nil {
			return nil, err
		}
		if commitInfo == nil {
			return nil, fuse.ENOENT
		}
		return &directory{
				d.fs,
				name,
				commitInfo.CommitType == pfs.CommitType_COMMIT_TYPE_WRITE,
				"",
			},
			nil
	}
	fileInfo, err := pfsutil.GetFileInfo(
		d.fs.apiClient,
		d.fs.repositoryName,
		d.commitID,
		path.Join(d.path, name),
	)
	if err != nil {
		return nil, err
	}
	return d.nodeFromFileInfo(fileInfo)
}

func (d *directory) readCommits(ctx context.Context) ([]fuse.Dirent, error) {
	commitInfos, err := pfsutil.ListCommits(d.fs.apiClient, d.fs.repositoryName)
	if err != nil {
		return nil, err
	}
	result := make([]fuse.Dirent, 0, len(commitInfos.CommitInfo))
	for _, commitInfo := range commitInfos.CommitInfo {
		result = append(result, fuse.Dirent{Name: commitInfo.Commit.Id, Type: fuse.DT_Dir})
	}
	return result, nil
}

func (d *directory) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
	if d.commitID == "" {
		return d.readCommits(ctx)
	}
	fileInfos, err := pfsutil.ListFiles(d.fs.apiClient, d.fs.repositoryName, d.commitID, d.path, d.fs.shard, d.fs.modulus)
	if err != nil {
		return nil, err
	}
	result := make([]fuse.Dirent, 0, len(fileInfos.FileInfo))
	for _, fileInfo := range fileInfos.FileInfo {
		shortPath := strings.TrimPrefix(fileInfo.Path.Path, d.path)
		switch fileInfo.FileType {
		case pfs.FileType_FILE_TYPE_NONE:
			continue
		case pfs.FileType_FILE_TYPE_OTHER:
			continue
		case pfs.FileType_FILE_TYPE_REGULAR:
			result = append(result, fuse.Dirent{Name: shortPath, Type: fuse.DT_File})
		case pfs.FileType_FILE_TYPE_DIR:
			result = append(result, fuse.Dirent{Name: shortPath, Type: fuse.DT_Dir})
		default:
			continue
		}
	}
	return result, nil
}

func (d *directory) Create(ctx context.Context, request *fuse.CreateRequest, response *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	if d.commitID == "" {
		return nil, 0, fuse.EPERM
	}
	result := &file{d.fs, d.commitID, path.Join(d.path, request.Name), 0, 0}
	handle, err := result.Open(ctx, nil, nil)
	if err != nil {
		return nil, nil, err
	}
	return result, handle, nil
}

func (d *directory) Mkdir(ctx context.Context, request *fuse.MkdirRequest) (fs.Node, error) {
	if d.commitID == "" {
		return nil, fuse.EPERM
	}
	if err := pfsutil.MakeDirectory(d.fs.apiClient, d.fs.repositoryName, d.commitID, path.Join(d.path, request.Name)); err != nil {
		return nil, err
	}
	return &directory{
		d.fs, d.commitID, d.write, path.Join(d.path, request.Name),
	}, nil
}

type file struct {
	fs       *filesystem
	commitID string
	path     string
	handles  int32
	size     int64
}

func (f *file) Attr(ctx context.Context, a *fuse.Attr) error {
	fileInfo, err := pfsutil.GetFileInfo(
		f.fs.apiClient,
		f.fs.repositoryName,
		f.commitID,
		f.path,
	)
	if err != nil {
		return err
	}
	if fileInfo != nil {
		a.Size = fileInfo.SizeBytes
	}
	a.Mode = 0666
	return nil
}

func (f *file) Read(ctx context.Context, request *fuse.ReadRequest, response *fuse.ReadResponse) error {
	buffer := bytes.NewBuffer(make([]byte, 0, request.Size))
	if err := pfsutil.GetFile(f.fs.apiClient, f.fs.repositoryName, f.commitID, f.path, request.Offset, int64(request.Size), buffer); err != nil {
		return err
	}
	response.Data = buffer.Bytes()
	return nil
}

func (f *file) Open(ctx context.Context, request *fuse.OpenRequest, response *fuse.OpenResponse) (fs.Handle, error) {
	atomic.AddInt32(&f.handles, 1)
	return f, nil
}

func (f *file) Write(ctx context.Context, request *fuse.WriteRequest, response *fuse.WriteResponse) error {
	written, err := pfsutil.PutFile(f.fs.apiClient, f.fs.repositoryName, f.commitID, f.path, request.Offset, bytes.NewReader(request.Data))
	if err != nil {
		return err
	}
	response.Size = int(written)
	if f.size < request.Offset+written {
		f.size = request.Offset + written
	}
	return nil
}
<commit_msg>Get fuse compiling again.<commit_after>package fuse

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"strings"
	"sync/atomic"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"github.com/pachyderm/pachyderm/src/pfs"
	"github.com/pachyderm/pachyderm/src/pfs/pfsutil"
	"golang.org/x/net/context"
)

type filesystem struct {
	apiClient      pfs.ApiClient
	repositoryName string
	commitID       string
	shard          uint64
	modulus        uint64
}

func newFilesystem(
	apiClient pfs.ApiClient,
	repositoryName string,
	commitID string,
	shard uint64,
	modulus uint64,
) *filesystem {
	return &filesystem{
		apiClient,
		repositoryName,
		commitID,
		shard,
		modulus,
	}
}

func (f *filesystem) Root() (fs.Node, error) {
	return &directory{f, f.commitID, true, ""}, nil
}

type directory struct {
	fs       *filesystem
	commitID string
	write    bool
	path     string
}

func (d *directory) Attr(ctx context.Context, a *fuse.Attr) error {
	if d.write {
		a.Mode = os.ModeDir | 0775
	} else {
		a.Mode = os.ModeDir | 0555
	}
	return nil
}

func (d *directory) nodeFromFileInfo(fileInfo *pfs.FileInfo) (fs.Node, error) {
	if fileInfo == nil {
		return nil, fuse.ENOENT
	}
	switch fileInfo.FileType {
	case pfs.FileType_FILE_TYPE_REGULAR:
		return &file{d.fs, d.commitID, path.Join(d.path, fileInfo.File.Path), 0,
			int64(fileInfo.SizeBytes)}, nil
	case pfs.FileType_FILE_TYPE_DIR:
		return &directory{d.fs, d.commitID, d.write, fileInfo.File.Path}, nil
	default:
		return nil, fmt.Errorf("Unrecognized FileType.")
	}
}

func (d *directory) Lookup(ctx context.Context, name string) (fs.Node, error) {
	if d.commitID == "" {
		commitInfo, err := pfsutil.CommitInspect(
			d.fs.apiClient,
			d.fs.repositoryName,
			name,
		)
		if err != nil {
			return nil, err
		}
		if commitInfo == nil {
			return nil, fuse.ENOENT
		}
		return &directory{
				d.fs,
				name,
				commitInfo.CommitType == pfs.CommitType_COMMIT_TYPE_WRITE,
				"",
			},
			nil
	}
	fileInfo, err := pfsutil.FileInspect(
		d.fs.apiClient,
		d.fs.repositoryName,
		d.commitID,
		path.Join(d.path, name),
	)
	if err != nil {
		return nil, err
	}
	return d.nodeFromFileInfo(fileInfo)
}

func (d *directory) readCommits(ctx context.Context) ([]fuse.Dirent, error) {
	commitInfos, err := pfsutil.CommitList(d.fs.apiClient, d.fs.repositoryName)
	if err != nil {
		return nil, err
	}
	result := make([]fuse.Dirent, 0, len(commitInfos))
	for _, commitInfo := range commitInfos {
		result = append(result, fuse.Dirent{Name: commitInfo.Commit.Id, Type: fuse.DT_Dir})
	}
	return result, nil
}

func (d *directory) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
	if d.commitID == "" {
		return d.readCommits(ctx)
	}
	fileInfos, err := pfsutil.FileList(d.fs.apiClient, d.fs.repositoryName, d.commitID, d.path, d.fs.shard, d.fs.modulus)
	if err != nil {
		return nil, err
	}
	result := make([]fuse.Dirent, 0, len(fileInfos))
	for _, fileInfo := range fileInfos {
		shortPath := strings.TrimPrefix(fileInfo.File.Path, d.path)
		switch fileInfo.FileType {
		case pfs.FileType_FILE_TYPE_REGULAR:
			result = append(result, fuse.Dirent{Name: shortPath, Type: fuse.DT_File})
		case pfs.FileType_FILE_TYPE_DIR:
			result = append(result, fuse.Dirent{Name: shortPath, Type: fuse.DT_Dir})
		default:
			continue
		}
	}
	return result, nil
}

func (d *directory) Create(ctx context.Context, request *fuse.CreateRequest, response *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	if d.commitID == "" {
		return nil, 0, fuse.EPERM
	}
	result := &file{d.fs, d.commitID, path.Join(d.path, request.Name), 0, 0}
	handle, err := result.Open(ctx, nil, nil)
	if err != nil {
		return nil, nil, err
	}
	return result, handle, nil
}

func (d *directory) Mkdir(ctx context.Context, request *fuse.MkdirRequest) (fs.Node, error) {
	if d.commitID == "" {
		return nil, fuse.EPERM
	}
	if err := pfsutil.MakeDirectory(d.fs.apiClient, d.fs.repositoryName, d.commitID, path.Join(d.path, request.Name)); err != nil {
		return nil, err
	}
	return &directory{
		d.fs, d.commitID, d.write, path.Join(d.path, request.Name),
	}, nil
}

type file struct {
	fs       *filesystem
	commitID string
	path     string
	handles  int32
	size     int64
}

func (f *file) Attr(ctx context.Context, a *fuse.Attr) error {
	fileInfo, err := pfsutil.FileInspect(
		f.fs.apiClient,
		f.fs.repositoryName,
		f.commitID,
		f.path,
	)
	if err != nil {
		return err
	}
	if fileInfo != nil {
		a.Size = fileInfo.SizeBytes
	}
	a.Mode = 0666
	return nil
}

func (f *file) Read(ctx context.Context, request *fuse.ReadRequest, response *fuse.ReadResponse) error {
	buffer := bytes.NewBuffer(make([]byte, 0, request.Size))
	if err := pfsutil.FileGet(f.fs.apiClient, f.fs.repositoryName, f.commitID, f.path, request.Offset, int64(request.Size), buffer); err != nil {
		return err
	}
	response.Data = buffer.Bytes()
	return nil
}

func (f *file) Open(ctx context.Context, request *fuse.OpenRequest, response *fuse.OpenResponse) (fs.Handle, error) {
	atomic.AddInt32(&f.handles, 1)
	return f, nil
}

func (f *file) Write(ctx context.Context, request *fuse.WriteRequest, response *fuse.WriteResponse) error {
	written, err := pfsutil.FilePut(f.fs.apiClient, f.fs.repositoryName, f.commitID, f.path, request.Offset, bytes.NewReader(request.Data))
	if err != nil {
		return err
	}
	response.Size = int(written)
	if f.size < request.Offset+written {
		f.size = request.Offset + written
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 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 syscall contains an interface to the low-level operating system
// primitives.  The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net".  Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These calls return errno == 0 to indicate success; otherwise
// errno is an operating system error number describing the failure.
package syscall

// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
	a := make([]byte, len(s)+1)
	copy(a, s)
	return a
}

// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }

// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.sh.
var _zero uintptr
<commit_msg>syscall: correct name of mksyscall script in comment<commit_after>// Copyright 2009 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 syscall contains an interface to the low-level operating system
// primitives.  The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net".  Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These calls return errno == 0 to indicate success; otherwise
// errno is an operating system error number describing the failure.
package syscall

// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
	a := make([]byte, len(s)+1)
	copy(a, s)
	return a
}

// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }

// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
<|endoftext|>


<commit_before>// Copyright 2013 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.

// +build !windows,!plan9

package interp_test

import (
	"bytes"
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"code.google.com/p/go.tools/importer"
	"code.google.com/p/go.tools/ssa"
	"code.google.com/p/go.tools/ssa/interp"
)

// Each line contains a space-separated list of $GOROOT/test/
// filenames comprising the main package of a program.
// They are ordered quickest-first, roughly.
//
// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
// golden file checking, etc.
var gorootTestTests = []string{
	"235.go",
	"alias1.go",
	"chancap.go",
	"func5.go",
	"func6.go",
	"func7.go",
	"func8.go",
	"helloworld.go",
	"varinit.go",
	"escape3.go",
	"initcomma.go",
	"cmp.go",
	"compos.go",
	"turing.go",
	"indirect.go",
	"complit.go",
	"for.go",
	"struct0.go",
	"intcvt.go",
	"printbig.go",
	"deferprint.go",
	"escape.go",
	"range.go",
	"const4.go",
	"float_lit.go",
	"bigalg.go",
	"decl.go",
	"if.go",
	"named.go",
	"bigmap.go",
	"func.go",
	"reorder2.go",
	"closure.go",
	"gc.go",
	"simassign.go",
	"iota.go",
	"nilptr2.go",
	"goprint.go", // doesn't actually assert anything (cmpout)
	"utf.go",
	"method.go",
	"char_lit.go",
	"env.go",
	"int_lit.go",
	"string_lit.go",
	"defer.go",
	"typeswitch.go",
	"stringrange.go",
	"reorder.go",
	"method3.go",
	"literal.go",
	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
	"zerodivide.go",
	"convert.go",
	"convT2X.go",
	"switch.go",
	"initialize.go",
	"ddd.go",
	"blank.go", // partly disabled
	"map.go",
	"closedchan.go",
	"divide.go",
	"rename.go",
	"const3.go",
	"nil.go",
	"recover.go", // reflection parts disabled
	"recover1.go",
	"recover2.go",
	"recover3.go",
	"typeswitch1.go",
	"floatcmp.go",
	"crlf.go", // doesn't actually assert anything (runoutput)
	// Slow tests follow.
	"bom.go", // ~1.7s
	"gc1.go", // ~1.7s
	"cmplxdivide.go cmplxdivide1.go", // ~2.4s

	// Working, but not worth enabling:
	// "append.go",    // works, but slow (15s).
	// "gc2.go",       // works, but slow, and cheats on the memory check.
	// "sigchld.go",   // works, but only on POSIX.
	// "peano.go",     // works only up to n=9, and slow even then.
	// "stack.go",     // works, but too slow (~30s) by default.
	// "solitaire.go", // works, but too slow (~30s).
	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
	// "rotate.go rotate0.go", // emits source for a test
	// "rotate.go rotate1.go", // emits source for a test
	// "rotate.go rotate2.go", // emits source for a test
	// "rotate.go rotate3.go", // emits source for a test
	// "64bit.go",             // emits source for a test
	// "run.go",               // test driver, not a test.

	// Broken.  TODO(adonovan): fix.
	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
	// args.go         // works, but requires specific os.Args from the driver.
	// index.go        // a template, not a real test.
	// mallocfin.go    // SetFinalizer not implemented.

	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
	// bench chan bugs fixedbugs interface ken.
}

// These are files in go.tools/ssa/interp/testdata/.
var testdataTests = []string{
	"boundmeth.go",
	"coverage.go",
	"fieldprom.go",
	"ifaceconv.go",
	"ifaceprom.go",
	"initorder.go",
	"methprom.go",
	"mrvchain.go",
	"recover.go",
}

// These are files in $GOROOT/src/pkg/.
// These tests exercise the "testing" package.
var gorootSrcPkgTests = []string{
	"unicode/script_test.go",
	"unicode/digit_test.go",
	"hash/crc32/crc32.go hash/crc32/crc32_generic.go hash/crc32/crc32_test.go",
	"path/path.go path/path_test.go",
	// TODO(adonovan): figure out the package loading error here:
	// "strings.go strings/search.go strings/search_test.go",
}

type successPredicate func(exitcode int, output string) error

func run(t *testing.T, dir, input string, success successPredicate) bool {
	fmt.Printf("Input: %s\n", input)

	start := time.Now()

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		inputs = append(inputs, dir+i)
	}

	imp := importer.New(&importer.Config{Build: &build.Default})
	// TODO(adonovan): use LoadInitialPackages, then un-export ParseFiles.
	// Then add the following packages' tests, which pass:
	// "flag", "unicode", "unicode/utf8", "testing", "log", "path".
	files, err := importer.ParseFiles(imp.Fset, ".", inputs...)
	if err != nil {
		t.Errorf("ssa.ParseFiles(%s) failed: %s", inputs, err.Error())
		return false
	}

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println("FAIL")
			fmt.Println(hint)
		} else {
			fmt.Println("PASS")
		}

		interp.CapturedOutput = nil
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build code.google.com/p/go.tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input)
	mainInfo := imp.CreatePackage(files[0].Name.Name, files...)

	if _, err := imp.LoadPackage("runtime"); err != nil {
		t.Errorf("LoadPackage(runtime) failed: %s", err)
	}

	prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
	if err := prog.CreatePackages(imp); err != nil {
		t.Errorf("CreatePackages failed: %s", err)
		return false
	}
	prog.BuildAll()

	mainPkg := prog.Package(mainInfo.Pkg)
	if mainPkg.Func("main") == nil {
		testmainPkg := prog.CreateTestMainPackage(mainPkg)
		if testmainPkg == nil {
			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
			return false
		}
		if testmainPkg.Func("main") == nil {
			t.Errorf("synthetic testmain package has no main")
			return false
		}
		mainPkg = testmainPkg
	}

	var out bytes.Buffer
	interp.CapturedOutput = &out

	hint = fmt.Sprintf("To trace execution, run:\n%% go build code.google.com/p/go.tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
	exitCode := interp.Interpret(mainPkg, 0, inputs[0], []string{})

	// The definition of success varies with each file.
	if err := success(exitCode, out.String()); err != nil {
		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
		return false
	}

	hint = "" // call off the hounds

	if false {
		fmt.Println(input, time.Since(start)) // test profiling
	}

	return true
}

const slash = string(os.PathSeparator)

func printFailures(failures []string) {
	if failures != nil {
		fmt.Println("The following tests failed:")
		for _, f := range failures {
			fmt.Printf("\t%s\n", f)
		}
	}
}

// The "normal" success predicate.
func exitsZero(exitcode int, _ string) error {
	if exitcode != 0 {
		return fmt.Errorf("exit code was %d", exitcode)
	}
	return nil
}

// TestTestdataFiles runs the interpreter on testdata/*.go.
func TestTestdataFiles(t *testing.T) {
	var failures []string
	for _, input := range testdataTests {
		if !run(t, "testdata"+slash, input, exitsZero) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
func TestGorootTest(t *testing.T) {
	if testing.Short() {
		return // too slow (~30s)
	}

	var failures []string

	// $GOROOT/tests are also considered a failure if they print "BUG".
	success := func(exitcode int, output string) error {
		if exitcode != 0 {
			return fmt.Errorf("exit code was %d", exitcode)
		}
		if strings.Contains(output, "BUG") {
			return fmt.Errorf("exited zero but output contained 'BUG'")
		}
		return nil
	}
	for _, input := range gorootTestTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	for _, input := range gorootSrcPkgTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "src/pkg")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
func TestTestmainPackage(t *testing.T) {
	success := func(exitcode int, output string) error {
		if exitcode == 0 {
			return fmt.Errorf("unexpected success")
		}
		if !strings.Contains(output, "FAIL: TestFoo") {
			return fmt.Errorf("missing failure log for TestFoo")
		}
		if !strings.Contains(output, "FAIL: TestBar") {
			return fmt.Errorf("missing failure log for TestBar")
		}
		// TODO(adonovan): test benchmarks too
		return nil
	}
	run(t, "testdata"+slash, "a_test.go", success)
}

// CreateTestMainPackage should return nil if there were no tests.
func TestNullTestmainPackage(t *testing.T) {
	imp := importer.New(&importer.Config{Build: build.Default})
	files, err := importer.ParseFiles(imp.Fset, ".", "testdata/b_test.go")
	if err != nil {
		t.Fatalf("ParseFiles failed: %s", err)
	}
	mainInfo := imp.CreatePackage("b", files...)
	prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
	if err := prog.CreatePackages(imp); err != nil {
		t.Fatalf("CreatePackages failed: %s", err)
	}
	mainPkg := prog.Package(mainInfo.Pkg)
	if mainPkg.Func("main") != nil {
		t.Fatalf("unexpected main function")
	}
	if prog.CreateTestMainPackage(mainPkg) != nil {
		t.Fatalf("CreateTestMainPackage returned non-nil")
	}
}
<commit_msg>go.tools/ssa/interp: fix build breakage.<commit_after>// Copyright 2013 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.

// +build !windows,!plan9

package interp_test

import (
	"bytes"
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"code.google.com/p/go.tools/importer"
	"code.google.com/p/go.tools/ssa"
	"code.google.com/p/go.tools/ssa/interp"
)

// Each line contains a space-separated list of $GOROOT/test/
// filenames comprising the main package of a program.
// They are ordered quickest-first, roughly.
//
// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
// golden file checking, etc.
var gorootTestTests = []string{
	"235.go",
	"alias1.go",
	"chancap.go",
	"func5.go",
	"func6.go",
	"func7.go",
	"func8.go",
	"helloworld.go",
	"varinit.go",
	"escape3.go",
	"initcomma.go",
	"cmp.go",
	"compos.go",
	"turing.go",
	"indirect.go",
	"complit.go",
	"for.go",
	"struct0.go",
	"intcvt.go",
	"printbig.go",
	"deferprint.go",
	"escape.go",
	"range.go",
	"const4.go",
	"float_lit.go",
	"bigalg.go",
	"decl.go",
	"if.go",
	"named.go",
	"bigmap.go",
	"func.go",
	"reorder2.go",
	"closure.go",
	"gc.go",
	"simassign.go",
	"iota.go",
	"nilptr2.go",
	"goprint.go", // doesn't actually assert anything (cmpout)
	"utf.go",
	"method.go",
	"char_lit.go",
	"env.go",
	"int_lit.go",
	"string_lit.go",
	"defer.go",
	"typeswitch.go",
	"stringrange.go",
	"reorder.go",
	"method3.go",
	"literal.go",
	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
	"zerodivide.go",
	"convert.go",
	"convT2X.go",
	"switch.go",
	"initialize.go",
	"ddd.go",
	"blank.go", // partly disabled
	"map.go",
	"closedchan.go",
	"divide.go",
	"rename.go",
	"const3.go",
	"nil.go",
	"recover.go", // reflection parts disabled
	"recover1.go",
	"recover2.go",
	"recover3.go",
	"typeswitch1.go",
	"floatcmp.go",
	"crlf.go", // doesn't actually assert anything (runoutput)
	// Slow tests follow.
	"bom.go", // ~1.7s
	"gc1.go", // ~1.7s
	"cmplxdivide.go cmplxdivide1.go", // ~2.4s

	// Working, but not worth enabling:
	// "append.go",    // works, but slow (15s).
	// "gc2.go",       // works, but slow, and cheats on the memory check.
	// "sigchld.go",   // works, but only on POSIX.
	// "peano.go",     // works only up to n=9, and slow even then.
	// "stack.go",     // works, but too slow (~30s) by default.
	// "solitaire.go", // works, but too slow (~30s).
	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
	// "rotate.go rotate0.go", // emits source for a test
	// "rotate.go rotate1.go", // emits source for a test
	// "rotate.go rotate2.go", // emits source for a test
	// "rotate.go rotate3.go", // emits source for a test
	// "64bit.go",             // emits source for a test
	// "run.go",               // test driver, not a test.

	// Broken.  TODO(adonovan): fix.
	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
	// args.go         // works, but requires specific os.Args from the driver.
	// index.go        // a template, not a real test.
	// mallocfin.go    // SetFinalizer not implemented.

	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
	// bench chan bugs fixedbugs interface ken.
}

// These are files in go.tools/ssa/interp/testdata/.
var testdataTests = []string{
	"boundmeth.go",
	"coverage.go",
	"fieldprom.go",
	"ifaceconv.go",
	"ifaceprom.go",
	"initorder.go",
	"methprom.go",
	"mrvchain.go",
	"recover.go",
}

// These are files in $GOROOT/src/pkg/.
// These tests exercise the "testing" package.
var gorootSrcPkgTests = []string{
	"unicode/script_test.go",
	"unicode/digit_test.go",
	"hash/crc32/crc32.go hash/crc32/crc32_generic.go hash/crc32/crc32_test.go",
	"path/path.go path/path_test.go",
	// TODO(adonovan): figure out the package loading error here:
	// "strings.go strings/search.go strings/search_test.go",
}

type successPredicate func(exitcode int, output string) error

func run(t *testing.T, dir, input string, success successPredicate) bool {
	fmt.Printf("Input: %s\n", input)

	start := time.Now()

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		inputs = append(inputs, dir+i)
	}

	imp := importer.New(&importer.Config{Build: &build.Default})
	// TODO(adonovan): use LoadInitialPackages, then un-export ParseFiles.
	// Then add the following packages' tests, which pass:
	// "flag", "unicode", "unicode/utf8", "testing", "log", "path".
	files, err := importer.ParseFiles(imp.Fset, ".", inputs...)
	if err != nil {
		t.Errorf("ssa.ParseFiles(%s) failed: %s", inputs, err.Error())
		return false
	}

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println("FAIL")
			fmt.Println(hint)
		} else {
			fmt.Println("PASS")
		}

		interp.CapturedOutput = nil
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build code.google.com/p/go.tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input)
	mainInfo := imp.CreatePackage(files[0].Name.Name, files...)

	if _, err := imp.LoadPackage("runtime"); err != nil {
		t.Errorf("LoadPackage(runtime) failed: %s", err)
	}

	prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
	if err := prog.CreatePackages(imp); err != nil {
		t.Errorf("CreatePackages failed: %s", err)
		return false
	}
	prog.BuildAll()

	mainPkg := prog.Package(mainInfo.Pkg)
	if mainPkg.Func("main") == nil {
		testmainPkg := prog.CreateTestMainPackage(mainPkg)
		if testmainPkg == nil {
			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
			return false
		}
		if testmainPkg.Func("main") == nil {
			t.Errorf("synthetic testmain package has no main")
			return false
		}
		mainPkg = testmainPkg
	}

	var out bytes.Buffer
	interp.CapturedOutput = &out

	hint = fmt.Sprintf("To trace execution, run:\n%% go build code.google.com/p/go.tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
	exitCode := interp.Interpret(mainPkg, 0, inputs[0], []string{})

	// The definition of success varies with each file.
	if err := success(exitCode, out.String()); err != nil {
		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
		return false
	}

	hint = "" // call off the hounds

	if false {
		fmt.Println(input, time.Since(start)) // test profiling
	}

	return true
}

const slash = string(os.PathSeparator)

func printFailures(failures []string) {
	if failures != nil {
		fmt.Println("The following tests failed:")
		for _, f := range failures {
			fmt.Printf("\t%s\n", f)
		}
	}
}

// The "normal" success predicate.
func exitsZero(exitcode int, _ string) error {
	if exitcode != 0 {
		return fmt.Errorf("exit code was %d", exitcode)
	}
	return nil
}

// TestTestdataFiles runs the interpreter on testdata/*.go.
func TestTestdataFiles(t *testing.T) {
	var failures []string
	for _, input := range testdataTests {
		if !run(t, "testdata"+slash, input, exitsZero) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
func TestGorootTest(t *testing.T) {
	if testing.Short() {
		return // too slow (~30s)
	}

	var failures []string

	// $GOROOT/tests are also considered a failure if they print "BUG".
	success := func(exitcode int, output string) error {
		if exitcode != 0 {
			return fmt.Errorf("exit code was %d", exitcode)
		}
		if strings.Contains(output, "BUG") {
			return fmt.Errorf("exited zero but output contained 'BUG'")
		}
		return nil
	}
	for _, input := range gorootTestTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	for _, input := range gorootSrcPkgTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "src/pkg")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
func TestTestmainPackage(t *testing.T) {
	success := func(exitcode int, output string) error {
		if exitcode == 0 {
			return fmt.Errorf("unexpected success")
		}
		if !strings.Contains(output, "FAIL: TestFoo") {
			return fmt.Errorf("missing failure log for TestFoo")
		}
		if !strings.Contains(output, "FAIL: TestBar") {
			return fmt.Errorf("missing failure log for TestBar")
		}
		// TODO(adonovan): test benchmarks too
		return nil
	}
	run(t, "testdata"+slash, "a_test.go", success)
}

// CreateTestMainPackage should return nil if there were no tests.
func TestNullTestmainPackage(t *testing.T) {
	imp := importer.New(&importer.Config{Build: &build.Default})
	files, err := importer.ParseFiles(imp.Fset, ".", "testdata/b_test.go")
	if err != nil {
		t.Fatalf("ParseFiles failed: %s", err)
	}
	mainInfo := imp.CreatePackage("b", files...)
	prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
	if err := prog.CreatePackages(imp); err != nil {
		t.Fatalf("CreatePackages failed: %s", err)
	}
	mainPkg := prog.Package(mainInfo.Pkg)
	if mainPkg.Func("main") != nil {
		t.Fatalf("unexpected main function")
	}
	if prog.CreateTestMainPackage(mainPkg) != nil {
		t.Fatalf("CreateTestMainPackage returned non-nil")
	}
}
<|endoftext|>


<commit_before>package stats

import (
	"reflect"
	"strings"
)

type FlatMap map[string]interface{}

func isEmptyValue(v reflect.Value) bool {
	return v.Interface() == reflect.Zero(v.Type()).Interface()
}

func keyForField(field reflect.StructField, v reflect.Value) (string, bool) {
	if tag := field.Tag.Get("json"); tag != "" {
		tokens := strings.SplitN(tag, ",", 2)
		name := tokens[0]
		opts := ""

		if len(tokens) > 1 {
			opts = tokens[1]
		}

		if name == "-" || strings.Contains(opts, "omitempty") && isEmptyValue(v) {
			return "", false
		} else if name != "" {
			return name, false
		}
	}

	if field.Anonymous {
		return "", true
	}
	return field.Name, false
}

func extractValue(val, fallback reflect.Value) reflect.Value {
	switch val.Kind() {
	case reflect.Struct:
		return val
	case reflect.Ptr:
		return extractValue(val.Elem(), fallback)
	case reflect.Interface:
		return extractValue(val.Elem(), fallback)
	default:
		return fallback
	}
}

func recursiveFlatten(val reflect.Value, prefix string, output FlatMap) int {
	valType := val.Type()
	added := 0

	for i := 0; i < val.NumField(); i++ {
		child := val.Field(i)
		childType := valType.Field(i)
		childPrefix := ""

		key, anonymous := keyForField(childType, child)

		if childType.PkgPath != "" || (key == "" && !anonymous) {
			continue
		}

		child = extractValue(child, child)
		if !anonymous {
			childPrefix = prefix + key + "."
		}

		if child.Kind() == reflect.Struct {
			childAdded := recursiveFlatten(child, childPrefix, output)
			if childAdded != 0 {
				added += childAdded
				continue
			}
		}

		output[prefix+key] = child.Addr().Interface()
		added++
	}

	return added
}

func flattenValue(val reflect.Value) FlatMap {
	if val.Kind() == reflect.Ptr {
		return flattenValue(val.Elem())
	}

	if val.Kind() != reflect.Struct {
		panic("must be called with a struct type")
	}

	m := FlatMap{}
	recursiveFlatten(val, "", m)
	return m
}

func Flatten(val interface{}) FlatMap {
	return flattenPointer(reflect.ValueOf(val))
}
<commit_msg>Correct reference to flattenPointer<commit_after>package stats

import (
	"reflect"
	"strings"
)

type FlatMap map[string]interface{}

func isEmptyValue(v reflect.Value) bool {
	return v.Interface() == reflect.Zero(v.Type()).Interface()
}

func keyForField(field reflect.StructField, v reflect.Value) (string, bool) {
	if tag := field.Tag.Get("json"); tag != "" {
		tokens := strings.SplitN(tag, ",", 2)
		name := tokens[0]
		opts := ""

		if len(tokens) > 1 {
			opts = tokens[1]
		}

		if name == "-" || strings.Contains(opts, "omitempty") && isEmptyValue(v) {
			return "", false
		} else if name != "" {
			return name, false
		}
	}

	if field.Anonymous {
		return "", true
	}
	return field.Name, false
}

func extractValue(val, fallback reflect.Value) reflect.Value {
	switch val.Kind() {
	case reflect.Struct:
		return val
	case reflect.Ptr:
		return extractValue(val.Elem(), fallback)
	case reflect.Interface:
		return extractValue(val.Elem(), fallback)
	default:
		return fallback
	}
}

func recursiveFlatten(val reflect.Value, prefix string, output FlatMap) int {
	valType := val.Type()
	added := 0

	for i := 0; i < val.NumField(); i++ {
		child := val.Field(i)
		childType := valType.Field(i)
		childPrefix := ""

		key, anonymous := keyForField(childType, child)

		if childType.PkgPath != "" || (key == "" && !anonymous) {
			continue
		}

		child = extractValue(child, child)
		if !anonymous {
			childPrefix = prefix + key + "."
		}

		if child.Kind() == reflect.Struct {
			childAdded := recursiveFlatten(child, childPrefix, output)
			if childAdded != 0 {
				added += childAdded
				continue
			}
		}

		output[prefix+key] = child.Addr().Interface()
		added++
	}

	return added
}

func flattenValue(val reflect.Value) FlatMap {
	if val.Kind() == reflect.Ptr {
		return flattenValue(val.Elem())
	}

	if val.Kind() != reflect.Struct {
		panic("must be called with a struct type")
	}

	m := FlatMap{}
	recursiveFlatten(val, "", m)
	return m
}

func Flatten(val interface{}) FlatMap {
	return flattenValue(reflect.ValueOf(val))
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"

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

func resourceAwsEc2TransitGatewayRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEc2TransitGatewayRouteCreate,
		Read:   resourceAwsEc2TransitGatewayRouteRead,
		Delete: resourceAwsEc2TransitGatewayRouteDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"transit_gateway_attachment_id": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.NoZeroValues,
			},
			"transit_gateway_route_table_id": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.NoZeroValues,
			},
		},
	}
}

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

	destination := d.Get("destination_cidr_block").(string)
	transitGatewayRouteTableID := d.Get("transit_gateway_route_table_id").(string)

	input := &ec2.CreateTransitGatewayRouteInput{
		DestinationCidrBlock:       aws.String(destination),
		TransitGatewayAttachmentId: aws.String(d.Get("transit_gateway_attachment_id").(string)),
		TransitGatewayRouteTableId: aws.String(transitGatewayRouteTableID),
	}

	log.Printf("[DEBUG] Creating EC2 Transit Gateway Route: %s", input)
	_, err := conn.CreateTransitGatewayRoute(input)
	if err != nil {
		return fmt.Errorf("error creating EC2 Transit Gateway Route: %s", err)
	}

	d.SetId(fmt.Sprintf("%s_%s", transitGatewayRouteTableID, destination))

	return resourceAwsEc2TransitGatewayRouteRead(d, meta)
}

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

	transitGatewayRouteTableID, destination, err := decodeEc2TransitGatewayRouteID(d.Id())
	if err != nil {
		return err
	}

	// Handle EC2 eventual consistency
	var transitGatewayRoute *ec2.TransitGatewayRoute
	err = resource.Retry(1*time.Minute, func() *resource.RetryError {
		var err error
		transitGatewayRoute, err = ec2DescribeTransitGatewayRoute(conn, transitGatewayRouteTableID, destination)

		if err != nil {
			return resource.NonRetryableError(err)
		}

		if d.IsNewResource() && transitGatewayRoute == nil {
			return resource.RetryableError(&resource.NotFoundError{})
		}

		return nil
	})

	if isAWSErr(err, "InvalidRouteTableID.NotFound", "") {
		log.Printf("[WARN] EC2 Transit Gateway Route Table (%s) not found, removing from state", transitGatewayRouteTableID)
		d.SetId("")
		return nil
	}

	if isResourceNotFoundError(err) {
		log.Printf("[WARN] EC2 Transit Gateway Route (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	if err != nil {
		return fmt.Errorf("error reading EC2 Transit Gateway Route: %s", err)
	}

	if transitGatewayRoute == nil {
		log.Printf("[WARN] EC2 Transit Gateway Route (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	d.Set("destination_cidr_block", transitGatewayRoute.DestinationCidrBlock)

	d.Set("transit_gateway_attachment_id", "")
	if len(transitGatewayRoute.TransitGatewayAttachments) == 0 || transitGatewayRoute.TransitGatewayAttachments[0] != nil {
		d.Set("transit_gateway_attachment_id", transitGatewayRoute.TransitGatewayAttachments[0].TransitGatewayAttachmentId)
	}

	d.Set("transit_gateway_route_table_id", transitGatewayRouteTableID)

	return nil
}

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

	transitGatewayRouteTableID, destination, err := decodeEc2TransitGatewayRouteID(d.Id())
	if err != nil {
		return err
	}

	input := &ec2.DeleteTransitGatewayRouteInput{
		DestinationCidrBlock:       aws.String(destination),
		TransitGatewayRouteTableId: aws.String(transitGatewayRouteTableID),
	}

	log.Printf("[DEBUG] Deleting EC2 Transit Gateway Route (%s): %s", d.Id(), input)
	_, err = conn.DeleteTransitGatewayRoute(input)

	if isAWSErr(err, "InvalidRouteID.NotFound", "") {
		return nil
	}

	if err != nil {
		return fmt.Errorf("error deleting EC2 Transit Gateway Route: %s", err)
	}

	return nil
}
<commit_msg>resource/aws_ec2_transit_gateway_route: Trigger resource recreation with deleted/deleting state routes<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"

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

func resourceAwsEc2TransitGatewayRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEc2TransitGatewayRouteCreate,
		Read:   resourceAwsEc2TransitGatewayRouteRead,
		Delete: resourceAwsEc2TransitGatewayRouteDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"transit_gateway_attachment_id": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.NoZeroValues,
			},
			"transit_gateway_route_table_id": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.NoZeroValues,
			},
		},
	}
}

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

	destination := d.Get("destination_cidr_block").(string)
	transitGatewayRouteTableID := d.Get("transit_gateway_route_table_id").(string)

	input := &ec2.CreateTransitGatewayRouteInput{
		DestinationCidrBlock:       aws.String(destination),
		TransitGatewayAttachmentId: aws.String(d.Get("transit_gateway_attachment_id").(string)),
		TransitGatewayRouteTableId: aws.String(transitGatewayRouteTableID),
	}

	log.Printf("[DEBUG] Creating EC2 Transit Gateway Route: %s", input)
	_, err := conn.CreateTransitGatewayRoute(input)
	if err != nil {
		return fmt.Errorf("error creating EC2 Transit Gateway Route: %s", err)
	}

	d.SetId(fmt.Sprintf("%s_%s", transitGatewayRouteTableID, destination))

	return resourceAwsEc2TransitGatewayRouteRead(d, meta)
}

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

	transitGatewayRouteTableID, destination, err := decodeEc2TransitGatewayRouteID(d.Id())
	if err != nil {
		return err
	}

	// Handle EC2 eventual consistency
	var transitGatewayRoute *ec2.TransitGatewayRoute
	err = resource.Retry(1*time.Minute, func() *resource.RetryError {
		var err error
		transitGatewayRoute, err = ec2DescribeTransitGatewayRoute(conn, transitGatewayRouteTableID, destination)

		if err != nil {
			return resource.NonRetryableError(err)
		}

		if d.IsNewResource() && transitGatewayRoute == nil {
			return resource.RetryableError(&resource.NotFoundError{})
		}

		return nil
	})

	if isAWSErr(err, "InvalidRouteTableID.NotFound", "") {
		log.Printf("[WARN] EC2 Transit Gateway Route Table (%s) not found, removing from state", transitGatewayRouteTableID)
		d.SetId("")
		return nil
	}

	if isResourceNotFoundError(err) {
		log.Printf("[WARN] EC2 Transit Gateway Route (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	if err != nil {
		return fmt.Errorf("error reading EC2 Transit Gateway Route: %s", err)
	}

	if transitGatewayRoute == nil {
		log.Printf("[WARN] EC2 Transit Gateway Route (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	state := aws.StringValue(transitGatewayRoute.State)
	if state == ec2.TransitGatewayRouteStateDeleted || state == ec2.TransitGatewayRouteStateDeleting {
		log.Printf("[WARN] EC2 Transit Gateway Route (%s) deleted, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	d.Set("destination_cidr_block", transitGatewayRoute.DestinationCidrBlock)

	d.Set("transit_gateway_attachment_id", "")
	if len(transitGatewayRoute.TransitGatewayAttachments) == 0 || transitGatewayRoute.TransitGatewayAttachments[0] != nil {
		d.Set("transit_gateway_attachment_id", transitGatewayRoute.TransitGatewayAttachments[0].TransitGatewayAttachmentId)
	}

	d.Set("transit_gateway_route_table_id", transitGatewayRouteTableID)

	return nil
}

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

	transitGatewayRouteTableID, destination, err := decodeEc2TransitGatewayRouteID(d.Id())
	if err != nil {
		return err
	}

	input := &ec2.DeleteTransitGatewayRouteInput{
		DestinationCidrBlock:       aws.String(destination),
		TransitGatewayRouteTableId: aws.String(transitGatewayRouteTableID),
	}

	log.Printf("[DEBUG] Deleting EC2 Transit Gateway Route (%s): %s", d.Id(), input)
	_, err = conn.DeleteTransitGatewayRoute(input)

	if isAWSErr(err, "InvalidRoute.NotFound", "") || isAWSErr(err, "InvalidRouteTableID.NotFound", "") {
		return nil
	}

	if err != nil {
		return fmt.Errorf("error deleting EC2 Transit Gateway Route: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package client

import (
	"crypto/tls"
	"errors"
	"io"
	"log"
	"net/http"
	"time"

	"s3cli/config"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

// S3Blobstore encapsulates interactions with an S3 compatible blobstore
type S3Blobstore struct {
	s3Client    *s3.S3
	s3cliConfig config.S3Cli
}

var errorInvalidCredentialsSourceValue = errors.New("the client operates in read only mode. Change 'credentials_source' parameter value ")

// New returns a BlobstoreClient if the configuration file backing configFile is valid
func New(configFile io.Reader) (S3Blobstore, error) {
	c, err := config.NewFromReader(configFile)
	if err != nil {
		return S3Blobstore{}, err
	}

	s3Client := MakeClient(c)

	return S3Blobstore{s3Client: s3Client, s3cliConfig: c}, nil
}

func MakeClient(c config.S3Cli) *s3.S3 {
	transport := *http.DefaultTransport.(*http.Transport)
	transport.TLSClientConfig = &tls.Config{
		InsecureSkipVerify: !c.SSLVerifyPeer,
	}

	httpClient := &http.Client{Transport: &transport}

	s3Config := aws.NewConfig().
		WithLogLevel(aws.LogOff).
		WithS3ForcePathStyle(true).
		WithDisableSSL(!c.UseSSL).
		WithHTTPClient(httpClient)

	if c.UseRegion() {
		s3Config = s3Config.WithRegion(c.Region).WithEndpoint(c.S3Endpoint())
	} else {
		s3Config = s3Config.WithRegion(config.EmptyRegion).WithEndpoint(c.S3Endpoint())
	}

	if c.CredentialsSource == config.StaticCredentialsSource {
		s3Config = s3Config.WithCredentials(credentials.NewStaticCredentials(c.AccessKeyID, c.SecretAccessKey, ""))
	}

	if c.CredentialsSource == config.NoneCredentialsSource {
		s3Config = s3Config.WithCredentials(credentials.AnonymousCredentials)
	}

	s3Session := session.New(s3Config)
	s3Client := s3.New(s3Session)

	if c.UseV2SigningMethod {
		setv2Handlers(s3Client)
	}

	return s3Client
}

// Get fetches a blob from an S3 compatible blobstore
// Destination will be overwritten if exists
func (client *S3Blobstore) Get(src string, dest io.WriterAt) error {
	downloader := s3manager.NewDownloaderWithClient(client.s3Client)

	_, err := downloader.Download(dest, &s3.GetObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(src),
	})

	if err != nil {
		return err
	}

	return nil
}

// Put uploads a blob to an S3 compatible blobstore
func (client *S3Blobstore) Put(src io.ReadSeeker, dest string) error {
	cfg := client.s3cliConfig
	if cfg.CredentialsSource == config.NoneCredentialsSource {
		return errorInvalidCredentialsSourceValue
	}

	uploader := s3manager.NewUploaderWithClient(client.s3Client)
	uploadInput := &s3manager.UploadInput{
		Body:   src,
		Bucket: aws.String(cfg.BucketName),
		Key:    aws.String(dest),
	}
	if cfg.ServerSideEncryption != "" {
		uploadInput.ServerSideEncryption = aws.String(cfg.ServerSideEncryption)
	}
	if cfg.SSEKMSKeyID != "" {
		uploadInput.SSEKMSKeyId = aws.String(cfg.SSEKMSKeyID)
	}

	maxRetries := 3
	for retry := 0; retry <= maxRetries; retry++ {
		putResult, err := uploader.Upload(uploadInput)
		if err != nil {
			if _, ok := err.(s3manager.MultiUploadFailure); ok {
				if retry == maxRetries {
					return err
				}
				time.Sleep(time.Second * time.Duration(retry+1))
				continue
			}
			return err
		}

		log.Println("Successfully uploaded file to", putResult.Location)
	}

	return nil
}

// Delete removes a blob from an S3 compatible blobstore. If the object does
// not exist, Delete does not return an error.
func (client *S3Blobstore) Delete(dest string) error {
	if client.s3cliConfig.CredentialsSource == config.NoneCredentialsSource {
		return errorInvalidCredentialsSourceValue
	}

	deleteParams := &s3.DeleteObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(dest),
	}

	_, err := client.s3Client.DeleteObject(deleteParams)

	if err == nil {
		return nil
	}

	if reqErr, ok := err.(awserr.RequestFailure); ok {
		if reqErr.StatusCode() == 404 {
			return nil
		}
	}
	return err
}

// Exists checks if blob exists in an S3 compatible blobstore
func (client *S3Blobstore) Exists(dest string) (bool, error) {

	existsParams := &s3.HeadObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(dest),
	}

	_, err := client.s3Client.HeadObject(existsParams)

	if err == nil {
		log.Printf("File '%s' exists in bucket '%s'\n", dest, client.s3cliConfig.BucketName)
		return true, nil
	}

	if reqErr, ok := err.(awserr.RequestFailure); ok {
		if reqErr.StatusCode() == 404 {
			log.Printf("File '%s' does not exist in bucket '%s'\n", dest, client.s3cliConfig.BucketName)
			return false, nil
		}
	}
	return false, err
}
<commit_msg>Revert "Cleans up S3 client Put"<commit_after>package client

import (
	"crypto/tls"
	"errors"
	"io"
	"log"
	"net/http"
	"time"

	"s3cli/config"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

// S3Blobstore encapsulates interactions with an S3 compatible blobstore
type S3Blobstore struct {
	s3Client    *s3.S3
	s3cliConfig config.S3Cli
}

var errorInvalidCredentialsSourceValue = errors.New("the client operates in read only mode. Change 'credentials_source' parameter value ")

// New returns a BlobstoreClient if the configuration file backing configFile is valid
func New(configFile io.Reader) (S3Blobstore, error) {
	c, err := config.NewFromReader(configFile)
	if err != nil {
		return S3Blobstore{}, err
	}

	s3Client := MakeClient(c)

	return S3Blobstore{s3Client: s3Client, s3cliConfig: c}, nil
}

func MakeClient(c config.S3Cli) *s3.S3 {
	transport := *http.DefaultTransport.(*http.Transport)
	transport.TLSClientConfig = &tls.Config{
		InsecureSkipVerify: !c.SSLVerifyPeer,
	}

	httpClient := &http.Client{Transport: &transport}

	s3Config := aws.NewConfig().
		WithLogLevel(aws.LogOff).
		WithS3ForcePathStyle(true).
		WithDisableSSL(!c.UseSSL).
		WithHTTPClient(httpClient)

	if c.UseRegion() {
		s3Config = s3Config.WithRegion(c.Region).WithEndpoint(c.S3Endpoint())
	} else {
		s3Config = s3Config.WithRegion(config.EmptyRegion).WithEndpoint(c.S3Endpoint())
	}

	if c.CredentialsSource == config.StaticCredentialsSource {
		s3Config = s3Config.WithCredentials(credentials.NewStaticCredentials(c.AccessKeyID, c.SecretAccessKey, ""))
	}

	if c.CredentialsSource == config.NoneCredentialsSource {
		s3Config = s3Config.WithCredentials(credentials.AnonymousCredentials)
	}

	s3Session := session.New(s3Config)
	s3Client := s3.New(s3Session)

	if c.UseV2SigningMethod {
		setv2Handlers(s3Client)
	}

	return s3Client
}

// Get fetches a blob from an S3 compatible blobstore
// Destination will be overwritten if exists
func (client *S3Blobstore) Get(src string, dest io.WriterAt) error {
	downloader := s3manager.NewDownloaderWithClient(client.s3Client)

	_, err := downloader.Download(dest, &s3.GetObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(src),
	})

	if err != nil {
		return err
	}

	return nil
}

// Put uploads a blob to an S3 compatible blobstore
func (client *S3Blobstore) Put(src io.ReadSeeker, dest string) error {
	cfg := client.s3cliConfig
	if cfg.CredentialsSource == config.NoneCredentialsSource {
		return errorInvalidCredentialsSourceValue
	}

	uploader := s3manager.NewUploaderWithClient(client.s3Client)
	retry := 0
	maxRetries := 3
	for {
		uploadInput := &s3manager.UploadInput{
			Body:   src,
			Bucket: aws.String(cfg.BucketName),
			Key:    aws.String(dest),
		}
		if cfg.ServerSideEncryption != "" {
			uploadInput.ServerSideEncryption = aws.String(cfg.ServerSideEncryption)
		}
		if cfg.SSEKMSKeyID != "" {
			uploadInput.SSEKMSKeyId = aws.String(cfg.SSEKMSKeyID)
		}

		putResult, err := uploader.Upload(uploadInput)
		if err != nil {
			if _, ok := err.(s3manager.MultiUploadFailure); ok {
				if retry > maxRetries {
					return err
				}
				retry++
				time.Sleep(time.Second * time.Duration(retry))
				continue
			}
			return err
		}

		log.Println("Successfully uploaded file to", putResult.Location)
	}
	return nil
}

// Delete removes a blob from an S3 compatible blobstore. If the object does
// not exist, Delete does not return an error.
func (client *S3Blobstore) Delete(dest string) error {
	if client.s3cliConfig.CredentialsSource == config.NoneCredentialsSource {
		return errorInvalidCredentialsSourceValue
	}

	deleteParams := &s3.DeleteObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(dest),
	}

	_, err := client.s3Client.DeleteObject(deleteParams)

	if err == nil {
		return nil
	}

	if reqErr, ok := err.(awserr.RequestFailure); ok {
		if reqErr.StatusCode() == 404 {
			return nil
		}
	}
	return err
}

// Exists checks if blob exists in an S3 compatible blobstore
func (client *S3Blobstore) Exists(dest string) (bool, error) {

	existsParams := &s3.HeadObjectInput{
		Bucket: aws.String(client.s3cliConfig.BucketName),
		Key:    aws.String(dest),
	}

	_, err := client.s3Client.HeadObject(existsParams)

	if err == nil {
		log.Printf("File '%s' exists in bucket '%s'\n", dest, client.s3cliConfig.BucketName)
		return true, nil
	}

	if reqErr, ok := err.(awserr.RequestFailure); ok {
		if reqErr.StatusCode() == 404 {
			log.Printf("File '%s' does not exist in bucket '%s'\n", dest, client.s3cliConfig.BucketName)
			return false, nil
		}
	}
	return false, err
}
<|endoftext|>


<commit_before>// Copyright 2016,2017 Yaacov Zamir <kobi.zamir@gmail.com>
// and other contributors.
//
// 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 handler http server handler functions
package handler

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"

	"github.com/MohawkTSDB/mohawk/src/alerts"
	"github.com/MohawkTSDB/mohawk/src/storage"
)

// const defaultLimit default REST API call query limit
const defaultLimit = 2000

// const defaultOrder default REST API call query order
const defaultOrder = "DESC"

// const secondaryOrder secondary REST API call query order
const secondaryOrder = "ASC"

// APIHhandler common variables to be used by all APIHhandler functions
// 	version the version of the Hawkular server we are mocking
// 	storage the storage to be used by the APIHhandler functions
type APIHhandler struct {
	Verbose bool
	Storage storage.Storage
	Alerts  *alerts.AlertRules
}

// GetAlertsStatus return a json alerts status struct
func (h APIHhandler) GetAlertsStatus(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	if h.Alerts == nil {
		w.WriteHeader(200)
		fmt.Fprintln(w, `{"AlertsService":"UNAVAILABLE"}`)
		return
	}

	resTemplate := `{"AlertsService":"STARTED","AlertsInterval":"%ds","Heartbeat":"%d","ServerURL":"%s"}`
	res := fmt.Sprintf(resTemplate, h.Alerts.AlertsInterval, h.Alerts.Heartbeat, h.Alerts.ServerURL)

	w.WriteHeader(200)
	fmt.Fprintln(w, res)
}

// GetAlerts return a list of alerts
func (h APIHhandler) GetAlerts(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []alerts.Alert

	// if no alerts return empty list
	if h.Alerts == nil {
		w.WriteHeader(200)
		fmt.Fprintln(w, `[]`)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)
	id := r.Form.Get("id")
	state := r.Form.Get("state")

	res = h.Alerts.FilterAlerts(tenant, id, state)
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetTenants return a list of metrics tenants
func (h APIHhandler) GetTenants(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []storage.Tenant

	res = h.Storage.GetTenants()
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetMetrics return a list of metrics definitions
func (h APIHhandler) GetMetrics(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []storage.Item

	r.ParseForm()

	// we only use gauges
	if typeStr, ok := r.Form["type"]; ok && len(typeStr) > 0 && typeStr[0] != "gauge" {
		w.WriteHeader(200)
		fmt.Fprintln(w, "[]")

		return
	}

	// get tenant
	tenant := parseTenant(r)

	// get a list of gauges
	if tagsStr, ok := r.Form["tags"]; ok && len(tagsStr) > 0 {
		tags := parseTags(tagsStr[0])
		if !validTags(tags) {
			badID(w, h.Verbose)
			return
		}
		res = h.Storage.GetItemList(tenant, tags)
	} else {
		res = h.Storage.GetItemList(tenant, map[string]string{})
	}
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetData return a list of metrics raw / stat data
func (h APIHhandler) GetData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) {
		badID(w, h.Verbose)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)

	// get timespan
	end, start, bucketDuration := parseTimespan(r)

	limit := int64(20000)
	if v, ok := r.Form["limit"]; ok && len(v) > 0 {
		if i, err := strconv.Atoi(v[0]); err == nil && i > 0 {
			limit = int64(i)
		}
	}

	order := defaultOrder
	if v, ok := r.Form["order"]; ok && len(v) > 0 && v[0] == secondaryOrder {
		order = secondaryOrder
	}

	if h.Verbose {
		log.Printf("ID: %s@%s, End: %d, Start: %d, Limit: %d, Order: %s, bucketDuration: %ds", tenant, id, end, start, limit, order, bucketDuration)
	}

	// call storage for data
	resStr := getData(h, tenant, id, end, start, limit, order, bucketDuration)

	// output to client
	w.WriteHeader(200)
	fmt.Fprintf(w, resStr)
}

// DeleteData delete a list of metrics raw  data
func (h APIHhandler) DeleteData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) {
		badID(w, h.Verbose)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)

	// get timespan
	end, start, _ := parseTimespan(r)

	if h.Verbose {
		log.Printf("ID: %s@%s, End: %d, Start: %d", tenant, id, end, start)
	}

	// call storage for data
	if start < end {
		h.Storage.DeleteData(tenant, id, end, start)

		// output to client
		w.WriteHeader(200)
		fmt.Fprintf(w, "{}")
		return
	}

	w.WriteHeader(504)
	fmt.Fprintf(w, "{\"error\":\"504\",\"message\":\"Can't delete time rage - 504\"}")
}

// PostQuery send timestamp, value to the storage
func (h APIHhandler) PostQuery(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u dataQuery
	var end int64
	var endStr string
	var start int64
	var startStr string
	var bucketDuration int64
	var bucketDurationStr string
	var limit int64
	var err error

	decoder := json.NewDecoder(r.Body)
	decoder.UseNumber()
	decoder.Decode(&u)

	// get tenant
	tenant := parseTenant(r)

	for _, id := range u.IDs {
		if !validStr(id) {
			badID(w, h.Verbose)
			return
		}
	}
	numOfItems := len(u.IDs) - 1

	switch v := u.Start.(type) {
	case string:
		startStr = u.Start.(string)
	default:
		startStr = fmt.Sprintf("%+v", v)
	}

	switch v := u.End.(type) {
	case string:
		endStr = u.End.(string)
	default:
		endStr = fmt.Sprintf("%+v", v)
	}

	switch v := u.BucketDuration.(type) {
	case string:
		bucketDurationStr = u.BucketDuration.(string)
	default:
		bucketDurationStr = fmt.Sprintf("%+v", v)
	}

	end, start, bucketDuration = parseTimespanStrings(endStr, startStr, bucketDurationStr)

	if limit, err = u.Limit.Int64(); err != nil || limit < 1 {
		limit = int64(defaultLimit)
	}

	order := defaultOrder
	if u.Order == secondaryOrder {
		order = secondaryOrder
	}

	if h.Verbose {
		log.Printf("Tenant: %s, IDs: %+v", tenant, u.IDs)
		log.Printf("End: %d(%s), Start: %d(%s), Limit: %d, Order: %s, bucketDuration: %ds", end, endStr, start, startStr, limit, order, bucketDuration)
	}

	w.WriteHeader(200)
	fmt.Fprintf(w, "[")

	for i, id := range u.IDs {
		// call storage for data
		resStr := getData(h, tenant, id, end, start, limit, order, bucketDuration)

		// write data
		fmt.Fprintf(w, "{\"id\": \"%s\", \"data\": %s}", id, resStr)
		if i < numOfItems {
			fmt.Fprintf(w, ",")
		}
	}

	fmt.Fprintf(w, "]")
}

// PostData send timestamp, value to the storage
func (h APIHhandler) PostData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u []postDataItems
	json.NewDecoder(r.Body).Decode(&u)

	for _, item := range u {
		if !validStr(item.ID) {
			badID(w, h.Verbose)
			return
		}
	}

	// get tenant
	tenant := parseTenant(r)

	for _, item := range u {
		id := item.ID

		for _, data := range item.Data {
			timestamp, _ := data.Timestamp.Int64()
			value, _ := data.Value.Float64()

			if h.Verbose {
				log.Printf("Tenant: %s, ID: %+v {timestamp: %+v, value: %+v}\n", tenant, id, timestamp, value)
			}
			h.Storage.PostRawData(tenant, id, timestamp, value)
		}
	}

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// PutTags send tag, value pairs to the storage
func (h APIHhandler) PutTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var tags map[string]string
	json.NewDecoder(r.Body).Decode(&tags)

	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) || !validTags(tags) {
		badID(w, h.Verbose)
		return
	}

	// get tenant
	tenant := parseTenant(r)

	if h.Verbose {
		log.Printf("Tenant: %s, ID: %+v {tags: %+v}\n", tenant, id, tags)
	}
	h.Storage.PutTags(tenant, id, tags)

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// PutMultiTags send tags pet dataItem - tag, value pairs to the storage
func (h APIHhandler) PutMultiTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u []putTags
	json.NewDecoder(r.Body).Decode(&u)

	for _, item := range u {
		if !validStr(item.ID) {
			badID(w, h.Verbose)
			return
		}
	}

	// get tenant
	tenant := parseTenant(r)

	for _, item := range u {
		id := item.ID
		if validTags(item.Tags) {
			if h.Verbose {
				log.Printf("Tenant: %s, ID: %+v {tags: %+v}\n", tenant, id, item.Tags)
			}
			h.Storage.PutTags(tenant, id, item.Tags)
		}
	}

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// DeleteTags delete a tag
func (h APIHhandler) DeleteTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	tagsStr := argv["tags"]
	if !validStr(id) || !validStr(tagsStr) {
		badID(w, h.Verbose)
		return
	}
	tags := strings.Split(tagsStr, ",")

	// get tenant
	tenant := parseTenant(r)

	h.Storage.DeleteTags(tenant, id, tags)

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// getData querys data from the storage, and return a json string
func getData(h APIHhandler, tenant string, id string, end int64, start int64, limit int64, order string, bucketDuration int64) string {
	var resStr string

	// call storage for data
	if bucketDuration == 0 {
		res := h.Storage.GetRawData(tenant, id, end, start, limit, order)
		resJSON, _ := json.Marshal(res)
		resStr = string(resJSON)
	} else {
		res := h.Storage.GetStatData(tenant, id, end, start, limit, order, bucketDuration)
		resJSON, _ := json.Marshal(res)
		resStr = string(resJSON)
	}

	return resStr
}
<commit_msg>add comments<commit_after>// Copyright 2016,2017 Yaacov Zamir <kobi.zamir@gmail.com>
// and other contributors.
//
// 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 handler http server handler functions
package handler

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"

	"github.com/MohawkTSDB/mohawk/src/alerts"
	"github.com/MohawkTSDB/mohawk/src/storage"
)

// const defaultLimit default REST API call query limit
const defaultLimit = 2000

// const defaultOrder default REST API call query order
const defaultOrder = "DESC"

// const secondaryOrder secondary REST API call query order
const secondaryOrder = "ASC"

// APIHhandler common variables to be used by all APIHhandler functions
// 	version the version of the Hawkular server we are mocking
// 	storage the storage to be used by the APIHhandler functions
type APIHhandler struct {
	Verbose bool
	Storage storage.Storage
	Alerts  *alerts.AlertRules
}

// GetAlertsStatus return a json alerts status struct
func (h APIHhandler) GetAlertsStatus(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	if h.Alerts == nil {
		w.WriteHeader(200)
		fmt.Fprintln(w, `{"AlertsService":"UNAVAILABLE"}`)
		return
	}

	resTemplate := `{"AlertsService":"STARTED","AlertsInterval":"%ds","Heartbeat":"%d","ServerURL":"%s"}`
	res := fmt.Sprintf(resTemplate, h.Alerts.AlertsInterval, h.Alerts.Heartbeat, h.Alerts.ServerURL)

	w.WriteHeader(200)
	fmt.Fprintln(w, res)
}

// GetAlerts return a list of alerts
func (h APIHhandler) GetAlerts(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []alerts.Alert

	// if no alerts return empty list
	if h.Alerts == nil {
		w.WriteHeader(200)
		fmt.Fprintln(w, `[]`)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)
	id := r.Form.Get("id")
	state := r.Form.Get("state")

	res = h.Alerts.FilterAlerts(tenant, id, state)
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetTenants return a list of metrics tenants
func (h APIHhandler) GetTenants(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []storage.Tenant

	res = h.Storage.GetTenants()
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetMetrics return a list of metrics definitions
func (h APIHhandler) GetMetrics(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var res []storage.Item

	r.ParseForm()

	// we only use gauges
	if typeStr, ok := r.Form["type"]; ok && len(typeStr) > 0 && typeStr[0] != "gauge" {
		w.WriteHeader(200)
		fmt.Fprintln(w, "[]")

		return
	}

	// get tenant
	tenant := parseTenant(r)

	// get a list of gauges
	if tagsStr, ok := r.Form["tags"]; ok && len(tagsStr) > 0 {
		tags := parseTags(tagsStr[0])
		if !validTags(tags) {
			badID(w, h.Verbose)
			return
		}
		res = h.Storage.GetItemList(tenant, tags)
	} else {
		res = h.Storage.GetItemList(tenant, map[string]string{})
	}
	resJSON, _ := json.Marshal(res)

	w.WriteHeader(200)
	fmt.Fprintln(w, string(resJSON))
}

// GetData return a list of metrics raw / stat data
func (h APIHhandler) GetData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) {
		badID(w, h.Verbose)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)

	// get timespan
	end, start, bucketDuration := parseTimespan(r)

	limit := int64(20000)
	if v, ok := r.Form["limit"]; ok && len(v) > 0 {
		if i, err := strconv.Atoi(v[0]); err == nil && i > 0 {
			limit = int64(i)
		}
	}

	order := defaultOrder
	if v, ok := r.Form["order"]; ok && len(v) > 0 && v[0] == secondaryOrder {
		order = secondaryOrder
	}

	if h.Verbose {
		log.Printf("ID: %s@%s, End: %d, Start: %d, Limit: %d, Order: %s, bucketDuration: %ds", tenant, id, end, start, limit, order, bucketDuration)
	}

	// call storage for data
	resStr := getData(h, tenant, id, end, start, limit, order, bucketDuration)

	// output to client
	w.WriteHeader(200)
	fmt.Fprintf(w, resStr)
}

// DeleteData delete a list of metrics raw  data
func (h APIHhandler) DeleteData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) {
		badID(w, h.Verbose)
		return
	}

	// get data from the form arguments
	r.ParseForm()

	// get tenant
	tenant := parseTenant(r)

	// get timespan
	end, start, _ := parseTimespan(r)

	if h.Verbose {
		log.Printf("ID: %s@%s, End: %d, Start: %d", tenant, id, end, start)
	}

	// call storage for data
	if start < end {
		h.Storage.DeleteData(tenant, id, end, start)

		// output to client
		w.WriteHeader(200)
		fmt.Fprintf(w, "{}")
		return
	}

	w.WriteHeader(504)
	fmt.Fprintf(w, "{\"error\":\"504\",\"message\":\"Can't delete time rage - 504\"}")
}

// PostQuery send timestamp, value to the storage
func (h APIHhandler) PostQuery(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u dataQuery
	var end int64
	var endStr string
	var start int64
	var startStr string
	var bucketDuration int64
	var bucketDurationStr string
	var limit int64
	var err error

	decoder := json.NewDecoder(r.Body)
	decoder.UseNumber()
	decoder.Decode(&u)

	// get tenant
	tenant := parseTenant(r)

	// get ids list
	for _, id := range u.IDs {
		if !validStr(id) {
			badID(w, h.Verbose)
			return
		}
	}
	numOfItems := len(u.IDs) - 1

	// get start time string
	switch v := u.Start.(type) {
	case string:
		startStr = u.Start.(string)
	default:
		startStr = fmt.Sprintf("%+v", v)
	}

	// get end time string
	switch v := u.End.(type) {
	case string:
		endStr = u.End.(string)
	default:
		endStr = fmt.Sprintf("%+v", v)
	}

	// get bucket duration string
	switch v := u.BucketDuration.(type) {
	case string:
		bucketDurationStr = u.BucketDuration.(string)
	default:
		bucketDurationStr = fmt.Sprintf("%+v", v)
	}

	// get query items limit
	if limit, err = u.Limit.Int64(); err != nil || limit < 1 {
		limit = int64(defaultLimit)
	}

	// get query order
	order := defaultOrder
	if u.Order == secondaryOrder {
		order = secondaryOrder
	}

	// calc timestamps from end, start and bucket duration strings
	end, start, bucketDuration = parseTimespanStrings(endStr, startStr, bucketDurationStr)

	if h.Verbose {
		log.Printf("Tenant: %s, IDs: %+v", tenant, u.IDs)
		log.Printf("End: %d(%s), Start: %d(%s), Limit: %d, Order: %s, bucketDuration: %ds", end, endStr, start, startStr, limit, order, bucketDuration)
	}

	w.WriteHeader(200)
	fmt.Fprintf(w, "[")

	for i, id := range u.IDs {
		// call storage for data
		resStr := getData(h, tenant, id, end, start, limit, order, bucketDuration)

		// write data
		fmt.Fprintf(w, "{\"id\": \"%s\", \"data\": %s}", id, resStr)
		if i < numOfItems {
			fmt.Fprintf(w, ",")
		}
	}

	fmt.Fprintf(w, "]")
}

// PostData send timestamp, value to the storage
func (h APIHhandler) PostData(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u []postDataItems
	json.NewDecoder(r.Body).Decode(&u)

	for _, item := range u {
		if !validStr(item.ID) {
			badID(w, h.Verbose)
			return
		}
	}

	// get tenant
	tenant := parseTenant(r)

	for _, item := range u {
		id := item.ID

		for _, data := range item.Data {
			timestamp, _ := data.Timestamp.Int64()
			value, _ := data.Value.Float64()

			if h.Verbose {
				log.Printf("Tenant: %s, ID: %+v {timestamp: %+v, value: %+v}\n", tenant, id, timestamp, value)
			}
			h.Storage.PostRawData(tenant, id, timestamp, value)
		}
	}

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// PutTags send tag, value pairs to the storage
func (h APIHhandler) PutTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var tags map[string]string
	json.NewDecoder(r.Body).Decode(&tags)

	// use the id from the argv list
	id := argv["id"]
	if !validStr(id) || !validTags(tags) {
		badID(w, h.Verbose)
		return
	}

	// get tenant
	tenant := parseTenant(r)

	if h.Verbose {
		log.Printf("Tenant: %s, ID: %+v {tags: %+v}\n", tenant, id, tags)
	}
	h.Storage.PutTags(tenant, id, tags)

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// PutMultiTags send tags pet dataItem - tag, value pairs to the storage
func (h APIHhandler) PutMultiTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	var u []putTags
	json.NewDecoder(r.Body).Decode(&u)

	for _, item := range u {
		if !validStr(item.ID) {
			badID(w, h.Verbose)
			return
		}
	}

	// get tenant
	tenant := parseTenant(r)

	for _, item := range u {
		id := item.ID
		if validTags(item.Tags) {
			if h.Verbose {
				log.Printf("Tenant: %s, ID: %+v {tags: %+v}\n", tenant, id, item.Tags)
			}
			h.Storage.PutTags(tenant, id, item.Tags)
		}
	}

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// DeleteTags delete a tag
func (h APIHhandler) DeleteTags(w http.ResponseWriter, r *http.Request, argv map[string]string) {
	// use the id from the argv list
	id := argv["id"]
	tagsStr := argv["tags"]
	if !validStr(id) || !validStr(tagsStr) {
		badID(w, h.Verbose)
		return
	}
	tags := strings.Split(tagsStr, ",")

	// get tenant
	tenant := parseTenant(r)

	h.Storage.DeleteTags(tenant, id, tags)

	w.WriteHeader(200)
	fmt.Fprintln(w, "{}")
}

// getData querys data from the storage, and return a json string
func getData(h APIHhandler, tenant string, id string, end int64, start int64, limit int64, order string, bucketDuration int64) string {
	var resStr string

	// call storage for data
	if bucketDuration == 0 {
		res := h.Storage.GetRawData(tenant, id, end, start, limit, order)
		resJSON, _ := json.Marshal(res)
		resStr = string(resJSON)
	} else {
		res := h.Storage.GetStatData(tenant, id, end, start, limit, order, bucketDuration)
		resJSON, _ := json.Marshal(res)
		resStr = string(resJSON)
	}

	return resStr
}
<|endoftext|>