<commit_before>// Package qemu provides implementations of a net.Conn and net.Listener backed by qemu_pipe
package qemu

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"sync"
	"syscall"
	"time"
)

const (
	qemuDriver = "/dev/qemu_pipe"
	qemuSvc    = "pipe:unix:"
	ioErrMsg   = "input/output error"
	rdyMsg     = "rdy"
)

var errClosed = errors.New("error connection closed")
var errNotImplemented = errors.New("error not implemented")

type qemuAddr string

// Network returns the network type of the connection
func (a qemuAddr) Network() string {
	return qemuDriver
}

// String returns the description of the connection
func (a qemuAddr) String() string {
	return string(a)
}

// Conn implements the net.Conn interface on top of a qemu_pipe
type Conn struct {
	// Backed by qemu_pipe
	conn io.ReadWriteCloser

	// Dummy addr
	addr net.Addr

	// Bytes remaining in the connection buffer
	// it would be tempting to simplify the code and use
	// an intermediate buffer to hold overflow buffer
	// but bytes.Buffer does not shrink which causes memory usage
	// to blow up
	left int

	closedReads  bool
	closedWrites bool

	readsCloseChan  chan struct{}
	writesCloseChan chan struct{}

	readLock  *sync.Mutex
	writeLock *sync.Mutex
}

// Read reads from from the Conn connection.
// Note that each message is prepended with the size, so we need to keep
// track of how many bytes we need to read across Read calls
func (q *Conn) Read(b []byte) (int, error) {
	q.readLock.Lock()
	defer q.readLock.Unlock()

	// Normally this could be done by just checking status != io.EOF, however
	// a read on /dev/qemu-pipe associated with a closed connection will return
	// EIO with the string "input/output error". Since errno isn't visible to us,
	// we check the error message and ensure the target string is not present.
	n, err := q.read(b)
	if err != nil {
		go q.CloseRead()
		if strings.Contains(err.Error(), ioErrMsg) {
			return n, io.EOF
		}
	}
	return n, err

}

func (q *Conn) read(b []byte) (int, error) {
	if q.closedReads {
		return 0, errClosed
	}

	toRead := q.left
	if toRead > len(b) {
		toRead = len(b)
	}

	// read leftovers from previous reads before trying to read the size
	if toRead > 0 {
		n, err := io.ReadFull(q.conn, b[:toRead])
		if err != nil {
			return n, err
		}
		q.left = q.left - n

		// b might be bigger than remaining bytes but conn might be empty and
		// we dont want to block on size read, so return early.
		return n, nil
	}

	var recd uint32
	if err := binary.Read(q.conn, binary.LittleEndian, &recd); err != nil {
		return 0, err
	}

	// The other side has signaled an EOF. Close connection for reads, we might have leftover writes
	if recd == 0 {
		return 0, io.EOF
	}

	toRead = int(recd)
	if toRead > len(b) {
		toRead = len(b)
	}

	n, err := io.ReadFull(q.conn, b[:toRead])
	if err != nil {
		return n, err
	}
	q.left = int(recd) - toRead
	return n, nil
}

// Write writes the contents of b to the underlying connection
func (q *Conn) Write(b []byte) (int, error) {
	q.writeLock.Lock()
	defer q.writeLock.Unlock()

	if q.closedWrites {
		return 0, errClosed
	}

	// Prepend the message with size
	if err := binary.Write(q.conn, binary.LittleEndian, uint32(len(b))); err != nil {
		return 0, err
	}
	return q.conn.Write(b)
}

// Close closes the connection
func (q *Conn) Close() error {
	return q.CloseWrite()
}

// CloseRead closes the read side of the connection
func (q *Conn) CloseRead() error {
	q.readLock.Lock()
	defer q.readLock.Unlock()

	if q.closedReads {
		return errClosed
	}
	q.closedReads = true
	close(q.readsCloseChan)
	return nil
}

// CloseWrite closes the write side of the connection
func (q *Conn) CloseWrite() error {
	q.writeLock.Lock()
	defer q.writeLock.Unlock()

	if q.closedWrites == true {
		return errClosed
	}
	q.closedWrites = true

	err := q.sendClose()
	close(q.writesCloseChan)
	return err
}

func (q *Conn) sendClose() error {
	if err := binary.Write(q.conn, binary.LittleEndian, uint32(0)); err != nil {
		return err
	}
	_, e := q.conn.Write([]byte{})
	return e
}

// LocalAddr returns the qemu address
func (q *Conn) LocalAddr() net.Addr {
	return q.addr
}

// RemoteAddr returns the qemu address
func (q *Conn) RemoteAddr() net.Addr {
	return q.addr
}

// SetDeadline sets the connection deadline
func (q *Conn) SetDeadline(t time.Time) error {
	return errNotImplemented
}

// SetReadDeadline sets the read deadline
func (q *Conn) SetReadDeadline(t time.Time) error {
	return errNotImplemented
}

// SetWriteDeadline sets the write deadline
func (q *Conn) SetWriteDeadline(t time.Time) error {
	return errNotImplemented
}

// closeConn waits for the read end and the write end of th connection
// to be closed and then closes the underlying connection
func (q *Conn) closeConn() {
	// remember the ABC
	<-q.readsCloseChan
	<-q.writesCloseChan
	q.conn.Close()
}

func makeConn(conn io.ReadWriteCloser) *Conn {
	return &Conn{
		conn:            conn,
		addr:            qemuAddr(""),
		readsCloseChan:  make(chan struct{}),
		writesCloseChan: make(chan struct{}),
		readLock:        &sync.Mutex{},
		writeLock:       &sync.Mutex{},
	}
}

// ConnBuilder implements a qemu connection builder. It wraps around listener
// listening on a qemu pipe. It accepts connectsion and sync with the client
// before returning
type ConnBuilder struct {
	lis net.Listener
}

// Close closes the underlying net.Listener
func (b *ConnBuilder) Close() error {
	return b.lis.Close()
}

// Next will connect to the guest and return the connection.
func (b *ConnBuilder) Next() (net.Conn, error) {
	for {
		conn, err := b.lis.Accept()
		if err != nil {
			return nil, err
		}

		// sync with the server
		rdy := []byte(rdyMsg)
		if _, err := conn.Write(rdy); err != nil {
			conn.Close()
			continue
		}
		if _, err := io.ReadFull(conn, rdy); err != nil {
			conn.Close()
			continue
		}
		if !bytes.Equal([]byte(rdyMsg), rdy) {
			conn.Close()
			continue
		}

		q := makeConn(conn)

		go q.closeConn()
		return q, nil
	}
}

// MakeConnBuilder creates a new ConnBuilder struct
func MakeConnBuilder(emuDir, socket string) (*ConnBuilder, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	if err := os.Chdir(emuDir); err != nil {
		return nil, err
	}

	if err := os.Remove(socket); err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	lis, err := net.Listen("unix", socket)
	if err != nil {
		return nil, err
	}

	if err := os.Chdir(wd); err != nil {
		return nil, err
	}

	return &ConnBuilder{lis: lis}, nil
}

func openQemuDevBlocking() (*os.File, error) {
	// Open device manually in blocking mode. Qemu pipes don't support polling io.
	r, err := syscall.Open(qemuDriver, os.O_RDWR|syscall.O_CLOEXEC, 0600)
	if err != nil {
		return nil, err
	}

	if err := syscall.SetNonblock(r, false); err != nil {
		syscall.Close(r)
		return nil, err
	}
	return os.NewFile(uintptr(r), qemuDriver), nil
}

// Pipe implements a net.Listener on top of a guest qemu pipe
type Pipe struct {
	socketName string
	closed     bool
}

// Accept creates a new net.Conn backed by a qemu_pipe connetion
func (q *Pipe) Accept() (net.Conn, error) {

	log.Println("Creating new conn")
	if q.closed {
		return nil, errClosed
	}

	// Each new file descriptor we open will create a new connection
	// We need to wait on the host to be ready:
	// 1) poll the qemu_pipe driver with the desiered socket name
	// 2) wait until the client is read to send/recv, we do this waiting until we read a rdy message
	var conn *os.File
	var err error
	br := false
	for {
		if conn != nil {
			// Got an error, close connection and try again
			conn.Close()
			time.Sleep(20 * time.Millisecond)
		}

		conn, err = openQemuDevBlocking()
		if err != nil {
			return nil, err
		}
		log.Println("File opened")

		svcName := qemuSvc + q.socketName
		buff := make([]byte, len(svcName)+1)
		copy(buff, svcName)

		// retry loop to wait until we can start the service on the qemu_pipe
		for {
			log.Println("Writing service")
			written, err := conn.Write(buff)
			if err != nil {
				// The host has not opened the socket. Sleep and try again
				conn.Close()
				time.Sleep(100 * time.Millisecond)
				break
			}
			buff = buff[written:]
			if len(buff) == 0 {
				log.Println("Wrote service")
				br = true
				break
			}
		}

		if br {
			// Wait for the client to open a socket on the host
			waitBuff := make([]byte, len(rdyMsg))
			log.Println("Reading rdy")
			if _, err := io.ReadFull(conn, waitBuff); err != nil {
				br = false
				continue
			}
			if !bytes.Equal([]byte(rdyMsg), waitBuff) {
				br = false
				continue
			}
			log.Println("Writing rdy")
			if _, err := conn.Write(waitBuff); err != nil {
				br = false
				continue
			}

			log.Println("Done")
			q := makeConn(conn)

			go q.closeConn()
			return q, nil

		}
	}

}

// Close closes the connection
func (q *Pipe) Close() error {
	q.closed = true
	return nil
}

// Addr returns the connection address
func (q *Pipe) Addr() net.Addr {
	return qemuAddr(q.socketName)
}

// MakePipe will return a new net.Listener
// backed by a qemu pipe. Qemu pipes are implemented as virtual
// devices. To get a handle an open("/dev/qemu_pipe") is issued.
// The virtual driver keeps a map of file descriptors to available
// services. In this case we open a unix socket service and return that.
func MakePipe(socketName string) (*Pipe, error) {
	if _, err := os.Stat(qemuDriver); err != nil {
		return nil, err
	}

	return &Pipe{socketName: socketName}, nil
}
<commit_msg>change connection closing<commit_after>// Package qemu provides implementations of a net.Conn and net.Listener backed by qemu_pipe
package qemu

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"sync"
	"syscall"
	"time"
)

const (
	qemuDriver = "/dev/qemu_pipe"
	qemuSvc    = "pipe:unix:"
	ioErrMsg   = "input/output error"
	rdyMsg     = "rdy"
)

var errClosed = errors.New("error connection closed")
var errNotImplemented = errors.New("error not implemented")

type qemuAddr string

// Network returns the network type of the connection
func (a qemuAddr) Network() string {
	return qemuDriver
}

// String returns the description of the connection
func (a qemuAddr) String() string {
	return string(a)
}

// Conn implements the net.Conn interface on top of a qemu_pipe
type Conn struct {
	// Backed by qemu_pipe
	conn io.ReadWriteCloser

	// Dummy addr
	addr net.Addr

	// Bytes remaining in the connection buffer
	// it would be tempting to simplify the code and use
	// an intermediate buffer to hold overflow buffer
	// but bytes.Buffer does not shrink which causes memory usage
	// to blow up
	left int

	closedReads  bool
	closedWrites bool
	closed	     bool

	readsCloseChan  chan struct{}
	writesCloseChan chan struct{}

	readLock  *sync.Mutex
	writeLock *sync.Mutex
	closeLock *sync.Mutex
}

// Read reads from from the Conn connection.
// Note that each message is prepended with the size, so we need to keep
// track of how many bytes we need to read across Read calls
func (q *Conn) Read(b []byte) (int, error) {
	q.readLock.Lock()
	defer q.readLock.Unlock()

	// Normally this could be done by just checking status != io.EOF, however
	// a read on /dev/qemu-pipe associated with a closed connection will return
	// EIO with the string "input/output error". Since errno isn't visible to us,
	// we check the error message and ensure the target string is not present.
	n, err := q.read(b)
	if err != nil {
		if strings.Contains(err.Error(), ioErrMsg) {
			return n, io.EOF
		}
	}
	return n, err

}

func (q *Conn) read(b []byte) (int, error) {
	if q.closedReads {
		return 0, errClosed
	}

	toRead := q.left
	if toRead > len(b) {
		toRead = len(b)
	}

	// read leftovers from previous reads before trying to read the size
	if toRead > 0 {
		n, err := io.ReadFull(q.conn, b[:toRead])
		if err != nil {
			return n, err
		}
		q.left = q.left - n

		// b might be bigger than remaining bytes but conn might be empty and
		// we dont want to block on size read, so return early.
		return n, nil
	}

	var recd uint32
	if err := binary.Read(q.conn, binary.LittleEndian, &recd); err != nil {
		return 0, err
	}

	// The other side has signaled an EOF. Close connection for reads, we might have leftover writes
	if recd == 0 {
		return 0, io.EOF
	}

	toRead = int(recd)
	if toRead > len(b) {
		toRead = len(b)
	}

	n, err := io.ReadFull(q.conn, b[:toRead])
	if err != nil {
		return n, err
	}
	q.left = int(recd) - toRead
	return n, nil
}

// Write writes the contents of b to the underlying connection
func (q *Conn) Write(b []byte) (int, error) {
	q.writeLock.Lock()
	defer q.writeLock.Unlock()

	if q.closedWrites {
		return 0, errClosed
	}

	// Prepend the message with size
	if err := binary.Write(q.conn, binary.LittleEndian, uint32(len(b))); err != nil {
		return 0, err
	}
	return q.conn.Write(b)
}

// Close closes the connection
func (q *Conn) Close() error {
	q.closeLock.Lock()
	defer q.closeLock.Unlock()

	if q.closed {
		return errClosed
	}

	q.closed = true

	q.CloseWrite()
	q.CloseRead()

	q.conn.Close()
	return nil

}

// CloseRead closes the read side of the connection
func (q *Conn) CloseRead() error {
	q.readLock.Lock()
	defer q.readLock.Unlock()

	if q.closedReads {
		return errClosed
	}
	q.closedReads = true
	close(q.readsCloseChan)
	return nil
}

// CloseWrite closes the write side of the connection
func (q *Conn) CloseWrite() error {
	q.writeLock.Lock()
	defer q.writeLock.Unlock()

	if q.closedWrites == true {
		return errClosed
	}
	q.closedWrites = true

	err := q.sendClose()
	close(q.writesCloseChan)
	return err
}

func (q *Conn) sendClose() error {
	if err := binary.Write(q.conn, binary.LittleEndian, uint32(0)); err != nil {
		return err
	}
	_, e := q.conn.Write([]byte{})
	return e
}

// LocalAddr returns the qemu address
func (q *Conn) LocalAddr() net.Addr {
	return q.addr
}

// RemoteAddr returns the qemu address
func (q *Conn) RemoteAddr() net.Addr {
	return q.addr
}

// SetDeadline sets the connection deadline
func (q *Conn) SetDeadline(t time.Time) error {
	return errNotImplemented
}

// SetReadDeadline sets the read deadline
func (q *Conn) SetReadDeadline(t time.Time) error {
	return errNotImplemented
}

// SetWriteDeadline sets the write deadline
func (q *Conn) SetWriteDeadline(t time.Time) error {
	return errNotImplemented
}

// closeConn waits for the read end and the write end of th connection
// to be closed and then closes the underlying connection
func (q *Conn) closeConn() {
	// remember the ABC
	<-q.readsCloseChan
	<-q.writesCloseChan
	q.conn.Close()
}

func makeConn(conn io.ReadWriteCloser) *Conn {
	return &Conn{
		conn:            conn,
		addr:            qemuAddr(""),
		readsCloseChan:  make(chan struct{}),
		writesCloseChan: make(chan struct{}),
		readLock:        &sync.Mutex{},
		writeLock:       &sync.Mutex{},
		closeLock:	 &sync.Mutex{},
	}
}

// ConnBuilder implements a qemu connection builder. It wraps around listener
// listening on a qemu pipe. It accepts connectsion and sync with the client
// before returning
type ConnBuilder struct {
	lis net.Listener
}

// Close closes the underlying net.Listener
func (b *ConnBuilder) Close() error {
	return b.lis.Close()
}

// Next will connect to the guest and return the connection.
func (b *ConnBuilder) Next() (net.Conn, error) {
	for {
		conn, err := b.lis.Accept()
		if err != nil {
			return nil, err
		}

		// sync with the server
		rdy := []byte(rdyMsg)
		if _, err := conn.Write(rdy); err != nil {
			conn.Close()
			continue
		}
		if _, err := io.ReadFull(conn, rdy); err != nil {
			conn.Close()
			continue
		}
		if !bytes.Equal([]byte(rdyMsg), rdy) {
			conn.Close()
			continue
		}

		q := makeConn(conn)

		go q.closeConn()
		return q, nil
	}
}

// MakeConnBuilder creates a new ConnBuilder struct
func MakeConnBuilder(emuDir, socket string) (*ConnBuilder, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	if err := os.Chdir(emuDir); err != nil {
		return nil, err
	}

	if err := os.Remove(socket); err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	lis, err := net.Listen("unix", socket)
	if err != nil {
		return nil, err
	}

	if err := os.Chdir(wd); err != nil {
		return nil, err
	}

	return &ConnBuilder{lis: lis}, nil
}

func openQemuDevBlocking() (*os.File, error) {
	// Open device manually in blocking mode. Qemu pipes don't support polling io.
	r, err := syscall.Open(qemuDriver, os.O_RDWR|syscall.O_CLOEXEC, 0600)
	if err != nil {
		return nil, err
	}

	if err := syscall.SetNonblock(r, false); err != nil {
		syscall.Close(r)
		return nil, err
	}
	return os.NewFile(uintptr(r), qemuDriver), nil
}

// Pipe implements a net.Listener on top of a guest qemu pipe
type Pipe struct {
	socketName string
	closed     bool
}

// Accept creates a new net.Conn backed by a qemu_pipe connetion
func (q *Pipe) Accept() (net.Conn, error) {

	log.Println("Creating new conn")
	if q.closed {
		return nil, errClosed
	}

	// Each new file descriptor we open will create a new connection
	// We need to wait on the host to be ready:
	// 1) poll the qemu_pipe driver with the desiered socket name
	// 2) wait until the client is read to send/recv, we do this waiting until we read a rdy message
	var conn *os.File
	var err error
	br := false
	for {
		if conn != nil {
			// Got an error, close connection and try again
			conn.Close()
			time.Sleep(20 * time.Millisecond)
		}

		conn, err = openQemuDevBlocking()
		if err != nil {
			return nil, err
		}
		log.Println("File opened")

		svcName := qemuSvc + q.socketName
		buff := make([]byte, len(svcName)+1)
		copy(buff, svcName)

		// retry loop to wait until we can start the service on the qemu_pipe
		for {
			log.Println("Writing service")
			written, err := conn.Write(buff)
			if err != nil {
				// The host has not opened the socket. Sleep and try again
				conn.Close()
				time.Sleep(100 * time.Millisecond)
				break
			}
			buff = buff[written:]
			if len(buff) == 0 {
				log.Println("Wrote service")
				br = true
				break
			}
		}

		if br {
			// Wait for the client to open a socket on the host
			waitBuff := make([]byte, len(rdyMsg))
			log.Println("Reading rdy")
			if _, err := io.ReadFull(conn, waitBuff); err != nil {
				br = false
				continue
			}
			if !bytes.Equal([]byte(rdyMsg), waitBuff) {
				br = false
				continue
			}
			log.Println("Writing rdy")
			if _, err := conn.Write(waitBuff); err != nil {
				br = false
				continue
			}

			log.Println("Done")
			q := makeConn(conn)

			go q.closeConn()
			return q, nil

		}
	}

}

// Close closes the connection
func (q *Pipe) Close() error {
	q.closed = true
	return nil
}

// Addr returns the connection address
func (q *Pipe) Addr() net.Addr {
	return qemuAddr(q.socketName)
}

// MakePipe will return a new net.Listener
// backed by a qemu pipe. Qemu pipes are implemented as virtual
// devices. To get a handle an open("/dev/qemu_pipe") is issued.
// The virtual driver keeps a map of file descriptors to available
// services. In this case we open a unix socket service and return that.
func MakePipe(socketName string) (*Pipe, error) {
	if _, err := os.Stat(qemuDriver); err != nil {
		return nil, err
	}

	return &Pipe{socketName: socketName}, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"

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

func resourceAwsCodeCommitRepository() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCodeCommitRepositoryCreate,
		Update: resourceAwsCodeCommitRepositoryUpdate,
		Read:   resourceAwsCodeCommitRepositoryRead,
		Delete: resourceAwsCodeCommitRepositoryDelete,

		Schema: map[string]*schema.Schema{
			"repository_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if len(value) > 100 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 100 characters", k))
					}
					return
				},
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if len(value) > 1000 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 1000 characters", k))
					}
					return
				},
			},

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

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

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

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

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

func resourceAwsCodeCommitRepositoryCreate(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn
	region := meta.(*AWSClient).region

	//	This is a temporary thing - we need to ensure that CodeCommit is only being run against us-east-1
	//	As this is the only place that AWS currently supports it
	if region != "us-east-1" {
		return fmt.Errorf("CodeCommit can only be used with US-East-1")
	}

	input := &codecommit.CreateRepositoryInput{
		RepositoryName:        aws.String(d.Get("repository_name").(string)),
		RepositoryDescription: aws.String(d.Get("description").(string)),
	}

	out, err := codecommitconn.CreateRepository(input)
	if err != nil {
		return fmt.Errorf("Error creating CodeCommit Repository: %s", err)
	}

	d.SetId(d.Get("repository_name").(string))
	d.Set("repository_id", *out.RepositoryMetadata.RepositoryId)
	d.Set("arn", *out.RepositoryMetadata.Arn)
	d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp)
	d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh)

	return resourceAwsCodeCommitRepositoryUpdate(d, meta)
}

func resourceAwsCodeCommitRepositoryUpdate(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	if d.HasChange("default_branch") {
		if err := resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn, d); err != nil {
			return err
		}
	}

	if d.HasChange("description") {
		if err := resourceAwsCodeCommitUpdateDescription(codecommitconn, d); err != nil {
			return err
		}
	}

	return resourceAwsCodeCommitRepositoryRead(d, meta)
}

func resourceAwsCodeCommitRepositoryRead(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	input := &codecommit.GetRepositoryInput{
		RepositoryName: aws.String(d.Id()),
	}

	out, err := codecommitconn.GetRepository(input)
	if err != nil {
		return fmt.Errorf("Error reading CodeCommit Repository: %s", err.Error())
	}

	d.Set("repository_id", *out.RepositoryMetadata.RepositoryId)
	d.Set("arn", *out.RepositoryMetadata.Arn)
	d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp)
	d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh)
	if out.RepositoryMetadata.DefaultBranch != nil {
		d.Set("default_branch", *out.RepositoryMetadata.DefaultBranch)
	}

	return nil
}

func resourceAwsCodeCommitRepositoryDelete(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	log.Printf("[DEBUG] CodeCommit Delete Repository: %s", d.Id())
	_, err := codecommitconn.DeleteRepository(&codecommit.DeleteRepositoryInput{
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		return fmt.Errorf("Error deleting CodeCommit Repository: %s", err.Error())
	}

	return nil
}

func resourceAwsCodeCommitUpdateDescription(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error {
	branchInput := &codecommit.UpdateRepositoryDescriptionInput{
		RepositoryName:        aws.String(d.Id()),
		RepositoryDescription: aws.String(d.Get("description").(string)),
	}

	_, err := codecommitconn.UpdateRepositoryDescription(branchInput)
	if err != nil {
		return fmt.Errorf("Error Updating Repository Description for CodeCommit Repository: %s", err.Error())
	}

	return nil
}

func resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error {
	branchInput := &codecommit.UpdateDefaultBranchInput{
		RepositoryName:    aws.String(d.Id()),
		DefaultBranchName: aws.String(d.Get("default_branch").(string)),
	}

	_, err := codecommitconn.UpdateDefaultBranch(branchInput)
	if err != nil {
		return fmt.Errorf("Error Updating Default Branch for CodeCommit Repository: %s", err.Error())
	}

	return nil
}
<commit_msg>Added the documentation for the CodeCommit repository<commit_after>package aws

import (
	"fmt"
	"log"

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

func resourceAwsCodeCommitRepository() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCodeCommitRepositoryCreate,
		Update: resourceAwsCodeCommitRepositoryUpdate,
		Read:   resourceAwsCodeCommitRepositoryRead,
		Delete: resourceAwsCodeCommitRepositoryDelete,

		Schema: map[string]*schema.Schema{
			"repository_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if len(value) > 100 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 100 characters", k))
					}
					return
				},
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if len(value) > 1000 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 1000 characters", k))
					}
					return
				},
			},

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

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

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

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

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

func resourceAwsCodeCommitRepositoryCreate(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn
	region := meta.(*AWSClient).region

	//	This is a temporary thing - we need to ensure that CodeCommit is only being run against us-east-1
	//	As this is the only place that AWS currently supports it
	if region != "us-east-1" {
		return fmt.Errorf("CodeCommit can only be used with us-east-1. You are trying to use it on %s", region)
	}

	input := &codecommit.CreateRepositoryInput{
		RepositoryName:        aws.String(d.Get("repository_name").(string)),
		RepositoryDescription: aws.String(d.Get("description").(string)),
	}

	out, err := codecommitconn.CreateRepository(input)
	if err != nil {
		return fmt.Errorf("Error creating CodeCommit Repository: %s", err)
	}

	d.SetId(d.Get("repository_name").(string))
	d.Set("repository_id", *out.RepositoryMetadata.RepositoryId)
	d.Set("arn", *out.RepositoryMetadata.Arn)
	d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp)
	d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh)

	return resourceAwsCodeCommitRepositoryUpdate(d, meta)
}

func resourceAwsCodeCommitRepositoryUpdate(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	if d.HasChange("default_branch") {
		if err := resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn, d); err != nil {
			return err
		}
	}

	if d.HasChange("description") {
		if err := resourceAwsCodeCommitUpdateDescription(codecommitconn, d); err != nil {
			return err
		}
	}

	return resourceAwsCodeCommitRepositoryRead(d, meta)
}

func resourceAwsCodeCommitRepositoryRead(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	input := &codecommit.GetRepositoryInput{
		RepositoryName: aws.String(d.Id()),
	}

	out, err := codecommitconn.GetRepository(input)
	if err != nil {
		return fmt.Errorf("Error reading CodeCommit Repository: %s", err.Error())
	}

	d.Set("repository_id", *out.RepositoryMetadata.RepositoryId)
	d.Set("arn", *out.RepositoryMetadata.Arn)
	d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp)
	d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh)
	if out.RepositoryMetadata.DefaultBranch != nil {
		d.Set("default_branch", *out.RepositoryMetadata.DefaultBranch)
	}

	return nil
}

func resourceAwsCodeCommitRepositoryDelete(d *schema.ResourceData, meta interface{}) error {
	codecommitconn := meta.(*AWSClient).codecommitconn

	log.Printf("[DEBUG] CodeCommit Delete Repository: %s", d.Id())
	_, err := codecommitconn.DeleteRepository(&codecommit.DeleteRepositoryInput{
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		return fmt.Errorf("Error deleting CodeCommit Repository: %s", err.Error())
	}

	return nil
}

func resourceAwsCodeCommitUpdateDescription(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error {
	branchInput := &codecommit.UpdateRepositoryDescriptionInput{
		RepositoryName:        aws.String(d.Id()),
		RepositoryDescription: aws.String(d.Get("description").(string)),
	}

	_, err := codecommitconn.UpdateRepositoryDescription(branchInput)
	if err != nil {
		return fmt.Errorf("Error Updating Repository Description for CodeCommit Repository: %s", err.Error())
	}

	return nil
}

func resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error {
	branchInput := &codecommit.UpdateDefaultBranchInput{
		RepositoryName:    aws.String(d.Id()),
		DefaultBranchName: aws.String(d.Get("default_branch").(string)),
	}

	_, err := codecommitconn.UpdateDefaultBranch(branchInput)
	if err != nil {
		return fmt.Errorf("Error Updating Default Branch for CodeCommit Repository: %s", err.Error())
	}

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsSpotInstanceRequest() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSpotInstanceRequestCreate,
		Read:   resourceAwsSpotInstanceRequestRead,
		Delete: resourceAwsSpotInstanceRequestDelete,
		Update: resourceAwsSpotInstanceRequestUpdate,

		Schema: func() map[string]*schema.Schema {
			// The Spot Instance Request Schema is based on the AWS Instance schema.
			s := resourceAwsInstance().Schema

			// Everything on a spot instance is ForceNew except tags
			for k, v := range s {
				if k == "tags" {
					continue
				}
				v.ForceNew = true
			}

			s["spot_price"] = &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			}
			s["spot_type"] = &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "persistent",
			}
			s["wait_for_fulfillment"] = &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			}
			s["spot_bid_status"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["spot_request_state"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["spot_instance_id"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["block_duration_minutes"] = &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				ForceNew: true,
			}

			return s
		}(),
	}
}

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

	instanceOpts, err := buildAwsInstanceOpts(d, meta)
	if err != nil {
		return err
	}

	spotOpts := &ec2.RequestSpotInstancesInput{
		SpotPrice: aws.String(d.Get("spot_price").(string)),
		Type:      aws.String(d.Get("spot_type").(string)),

		// Though the AWS API supports creating spot instance requests for multiple
		// instances, for TF purposes we fix this to one instance per request.
		// Users can get equivalent behavior out of TF's "count" meta-parameter.
		InstanceCount: aws.Int64(1),

		LaunchSpecification: &ec2.RequestSpotLaunchSpecification{
			BlockDeviceMappings: instanceOpts.BlockDeviceMappings,
			EbsOptimized:        instanceOpts.EBSOptimized,
			Monitoring:          instanceOpts.Monitoring,
			IamInstanceProfile:  instanceOpts.IAMInstanceProfile,
			ImageId:             instanceOpts.ImageID,
			InstanceType:        instanceOpts.InstanceType,
			KeyName:             instanceOpts.KeyName,
			Placement:           instanceOpts.SpotPlacement,
			SecurityGroupIds:    instanceOpts.SecurityGroupIDs,
			SecurityGroups:      instanceOpts.SecurityGroups,
			SubnetId:            instanceOpts.SubnetID,
			UserData:            instanceOpts.UserData64,
		},
	}

	if v, ok := d.GetOk("block_duration_minutes"); ok {
		spotOpts.BlockDurationMinutes = aws.Int64(int64(v.(int)))
	}

	// If the instance is configured with a Network Interface (a subnet, has
	// public IP, etc), then the instanceOpts.SecurityGroupIds and SubnetId will
	// be nil
	if len(instanceOpts.NetworkInterfaces) > 0 {
		spotOpts.LaunchSpecification.SecurityGroupIds = instanceOpts.NetworkInterfaces[0].Groups
		spotOpts.LaunchSpecification.SubnetId = instanceOpts.NetworkInterfaces[0].SubnetId
	}

	// Make the spot instance request
	log.Printf("[DEBUG] Requesting spot bid opts: %s", spotOpts)

	var resp *ec2.RequestSpotInstancesOutput
	err = resource.Retry(15*time.Second, func() *resource.RetryError {
		var err error
		resp, err = conn.RequestSpotInstances(spotOpts)
		// IAM instance profiles can take ~10 seconds to propagate in AWS:
		// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
		if isAWSErr(err, "InvalidParameterValue", "Invalid IAM Instance Profile") {
			log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...")
			return resource.RetryableError(err)
		}
		// IAM roles can also take time to propagate in AWS:
		if isAWSErr(err, "InvalidParameterValue", " has no associated IAM Roles") {
			log.Printf("[DEBUG] IAM Instance Profile appears to have no IAM roles, retrying...")
			return resource.RetryableError(err)
		}
		return resource.NonRetryableError(err)
	})

	if err != nil {
		return fmt.Errorf("Error requesting spot instances: %s", err)
	}
	if len(resp.SpotInstanceRequests) != 1 {
		return fmt.Errorf(
			"Expected response with length 1, got: %s", resp)
	}

	sir := *resp.SpotInstanceRequests[0]
	d.SetId(*sir.SpotInstanceRequestId)

	if d.Get("wait_for_fulfillment").(bool) {
		spotStateConf := &resource.StateChangeConf{
			// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html
			Pending:    []string{"start", "pending-evaluation", "pending-fulfillment"},
			Target:     []string{"fulfilled"},
			Refresh:    SpotInstanceStateRefreshFunc(conn, sir),
			Timeout:    10 * time.Minute,
			Delay:      10 * time.Second,
			MinTimeout: 3 * time.Second,
		}

		log.Printf("[DEBUG] waiting for spot bid to resolve... this may take several minutes.")
		_, err = spotStateConf.WaitForState()

		if err != nil {
			return fmt.Errorf("Error while waiting for spot request (%s) to resolve: %s", sir, err)
		}
	}

	return resourceAwsSpotInstanceRequestUpdate(d, meta)
}

// Update spot state, etc
func resourceAwsSpotInstanceRequestRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	req := &ec2.DescribeSpotInstanceRequestsInput{
		SpotInstanceRequestIds: []*string{aws.String(d.Id())},
	}
	resp, err := conn.DescribeSpotInstanceRequests(req)

	if err != nil {
		// If the spot request was not found, return nil so that we can show
		// that it is gone.
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" {
			d.SetId("")
			return nil
		}

		// Some other error, report it
		return err
	}

	// If nothing was found, then return no state
	if len(resp.SpotInstanceRequests) == 0 {
		d.SetId("")
		return nil
	}

	request := resp.SpotInstanceRequests[0]

	// if the request is cancelled, then it is gone
	if *request.State == "cancelled" {
		d.SetId("")
		return nil
	}

	d.Set("spot_bid_status", *request.Status.Code)
	// Instance ID is not set if the request is still pending
	if request.InstanceId != nil {
		d.Set("spot_instance_id", *request.InstanceId)
		// Read the instance data, setting up connection information
		if err := readInstance(d, meta); err != nil {
			return fmt.Errorf("[ERR] Error reading Spot Instance Data: %s", err)
		}
	}

	d.Set("spot_request_state", request.State)
	d.Set("block_duration_minutes", request.BlockDurationMinutes)
	d.Set("tags", tagsToMap(request.Tags))

	return nil
}

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

	resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{aws.String(d.Get("spot_instance_id").(string))},
	})
	if err != nil {
		// If the instance was not found, return nil so that we can show
		// that the instance is gone.
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" {
			return fmt.Errorf("no instance found")
		}

		// Some other error, report it
		return err
	}

	// If nothing was found, then return no state
	if len(resp.Reservations) == 0 {
		return fmt.Errorf("no instances found")
	}

	instance := resp.Reservations[0].Instances[0]

	// Set these fields for connection information
	if instance != nil {
		d.Set("public_dns", instance.PublicDnsName)
		d.Set("public_ip", instance.PublicIpAddress)
		d.Set("private_dns", instance.PrivateDnsName)
		d.Set("private_ip", instance.PrivateIpAddress)

		// set connection information
		if instance.PublicIpAddress != nil {
			d.SetConnInfo(map[string]string{
				"type": "ssh",
				"host": *instance.PublicIpAddress,
			})
		} else if instance.PrivateIpAddress != nil {
			d.SetConnInfo(map[string]string{
				"type": "ssh",
				"host": *instance.PrivateIpAddress,
			})
		}
		if err := readBlockDevices(d, instance, conn); err != nil {
			return err
		}

		var ipv6Addresses []string
		if len(instance.NetworkInterfaces) > 0 {
			for _, ni := range instance.NetworkInterfaces {
				if *ni.Attachment.DeviceIndex == 0 {
					d.Set("subnet_id", ni.SubnetId)
					d.Set("network_interface_id", ni.NetworkInterfaceId)
					d.Set("associate_public_ip_address", ni.Association != nil)
					d.Set("ipv6_address_count", len(ni.Ipv6Addresses))

					for _, address := range ni.Ipv6Addresses {
						ipv6Addresses = append(ipv6Addresses, *address.Ipv6Address)
					}
				}
			}
		} else {
			d.Set("subnet_id", instance.SubnetId)
			d.Set("network_interface_id", "")
		}

		if err := d.Set("ipv6_addresses", ipv6Addresses); err != nil {
			log.Printf("[WARN] Error setting ipv6_addresses for AWS Spot Instance (%s): %s", d.Id(), err)
		}
	}

	return nil
}

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

	d.Partial(true)
	if err := setTags(conn, d); err != nil {
		return err
	} else {
		d.SetPartial("tags")
	}

	d.Partial(false)

	return resourceAwsSpotInstanceRequestRead(d, meta)
}

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

	log.Printf("[INFO] Cancelling spot request: %s", d.Id())
	_, err := conn.CancelSpotInstanceRequests(&ec2.CancelSpotInstanceRequestsInput{
		SpotInstanceRequestIds: []*string{aws.String(d.Id())},
	})

	if err != nil {
		return fmt.Errorf("Error cancelling spot request (%s): %s", d.Id(), err)
	}

	if instanceId := d.Get("spot_instance_id").(string); instanceId != "" {
		log.Printf("[INFO] Terminating instance: %s", instanceId)
		if err := awsTerminateInstance(conn, instanceId); err != nil {
			return fmt.Errorf("Error terminating spot instance: %s", err)
		}
	}

	return nil
}

// SpotInstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// an EC2 spot instance request
func SpotInstanceStateRefreshFunc(
	conn *ec2.EC2, sir ec2.SpotInstanceRequest) resource.StateRefreshFunc {

	return func() (interface{}, string, error) {
		resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
			SpotInstanceRequestIds: []*string{sir.SpotInstanceRequestId},
		})

		if err != nil {
			if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on StateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil || len(resp.SpotInstanceRequests) == 0 {
			// Sometimes AWS just has consistency issues and doesn't see
			// our request yet. Return an empty state.
			return nil, "", nil
		}

		req := resp.SpotInstanceRequests[0]
		return req, *req.Status.Code, nil
	}
}
<commit_msg>provider/aws: aws_spot_instance_request not forcenew on volume_tags (#14046)<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsSpotInstanceRequest() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSpotInstanceRequestCreate,
		Read:   resourceAwsSpotInstanceRequestRead,
		Delete: resourceAwsSpotInstanceRequestDelete,
		Update: resourceAwsSpotInstanceRequestUpdate,

		Schema: func() map[string]*schema.Schema {
			// The Spot Instance Request Schema is based on the AWS Instance schema.
			s := resourceAwsInstance().Schema

			// Everything on a spot instance is ForceNew except tags
			for k, v := range s {
				if k == "tags" || k == "volume_tags" {
					continue
				}
				v.ForceNew = true
			}

			s["spot_price"] = &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			}
			s["spot_type"] = &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "persistent",
			}
			s["wait_for_fulfillment"] = &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			}
			s["spot_bid_status"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["spot_request_state"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["spot_instance_id"] = &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			}
			s["block_duration_minutes"] = &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				ForceNew: true,
			}

			return s
		}(),
	}
}

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

	instanceOpts, err := buildAwsInstanceOpts(d, meta)
	if err != nil {
		return err
	}

	spotOpts := &ec2.RequestSpotInstancesInput{
		SpotPrice: aws.String(d.Get("spot_price").(string)),
		Type:      aws.String(d.Get("spot_type").(string)),

		// Though the AWS API supports creating spot instance requests for multiple
		// instances, for TF purposes we fix this to one instance per request.
		// Users can get equivalent behavior out of TF's "count" meta-parameter.
		InstanceCount: aws.Int64(1),

		LaunchSpecification: &ec2.RequestSpotLaunchSpecification{
			BlockDeviceMappings: instanceOpts.BlockDeviceMappings,
			EbsOptimized:        instanceOpts.EBSOptimized,
			Monitoring:          instanceOpts.Monitoring,
			IamInstanceProfile:  instanceOpts.IAMInstanceProfile,
			ImageId:             instanceOpts.ImageID,
			InstanceType:        instanceOpts.InstanceType,
			KeyName:             instanceOpts.KeyName,
			Placement:           instanceOpts.SpotPlacement,
			SecurityGroupIds:    instanceOpts.SecurityGroupIDs,
			SecurityGroups:      instanceOpts.SecurityGroups,
			SubnetId:            instanceOpts.SubnetID,
			UserData:            instanceOpts.UserData64,
		},
	}

	if v, ok := d.GetOk("block_duration_minutes"); ok {
		spotOpts.BlockDurationMinutes = aws.Int64(int64(v.(int)))
	}

	// If the instance is configured with a Network Interface (a subnet, has
	// public IP, etc), then the instanceOpts.SecurityGroupIds and SubnetId will
	// be nil
	if len(instanceOpts.NetworkInterfaces) > 0 {
		spotOpts.LaunchSpecification.SecurityGroupIds = instanceOpts.NetworkInterfaces[0].Groups
		spotOpts.LaunchSpecification.SubnetId = instanceOpts.NetworkInterfaces[0].SubnetId
	}

	// Make the spot instance request
	log.Printf("[DEBUG] Requesting spot bid opts: %s", spotOpts)

	var resp *ec2.RequestSpotInstancesOutput
	err = resource.Retry(15*time.Second, func() *resource.RetryError {
		var err error
		resp, err = conn.RequestSpotInstances(spotOpts)
		// IAM instance profiles can take ~10 seconds to propagate in AWS:
		// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
		if isAWSErr(err, "InvalidParameterValue", "Invalid IAM Instance Profile") {
			log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...")
			return resource.RetryableError(err)
		}
		// IAM roles can also take time to propagate in AWS:
		if isAWSErr(err, "InvalidParameterValue", " has no associated IAM Roles") {
			log.Printf("[DEBUG] IAM Instance Profile appears to have no IAM roles, retrying...")
			return resource.RetryableError(err)
		}
		return resource.NonRetryableError(err)
	})

	if err != nil {
		return fmt.Errorf("Error requesting spot instances: %s", err)
	}
	if len(resp.SpotInstanceRequests) != 1 {
		return fmt.Errorf(
			"Expected response with length 1, got: %s", resp)
	}

	sir := *resp.SpotInstanceRequests[0]
	d.SetId(*sir.SpotInstanceRequestId)

	if d.Get("wait_for_fulfillment").(bool) {
		spotStateConf := &resource.StateChangeConf{
			// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html
			Pending:    []string{"start", "pending-evaluation", "pending-fulfillment"},
			Target:     []string{"fulfilled"},
			Refresh:    SpotInstanceStateRefreshFunc(conn, sir),
			Timeout:    10 * time.Minute,
			Delay:      10 * time.Second,
			MinTimeout: 3 * time.Second,
		}

		log.Printf("[DEBUG] waiting for spot bid to resolve... this may take several minutes.")
		_, err = spotStateConf.WaitForState()

		if err != nil {
			return fmt.Errorf("Error while waiting for spot request (%s) to resolve: %s", sir, err)
		}
	}

	return resourceAwsSpotInstanceRequestUpdate(d, meta)
}

// Update spot state, etc
func resourceAwsSpotInstanceRequestRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	req := &ec2.DescribeSpotInstanceRequestsInput{
		SpotInstanceRequestIds: []*string{aws.String(d.Id())},
	}
	resp, err := conn.DescribeSpotInstanceRequests(req)

	if err != nil {
		// If the spot request was not found, return nil so that we can show
		// that it is gone.
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" {
			d.SetId("")
			return nil
		}

		// Some other error, report it
		return err
	}

	// If nothing was found, then return no state
	if len(resp.SpotInstanceRequests) == 0 {
		d.SetId("")
		return nil
	}

	request := resp.SpotInstanceRequests[0]

	// if the request is cancelled, then it is gone
	if *request.State == "cancelled" {
		d.SetId("")
		return nil
	}

	d.Set("spot_bid_status", *request.Status.Code)
	// Instance ID is not set if the request is still pending
	if request.InstanceId != nil {
		d.Set("spot_instance_id", *request.InstanceId)
		// Read the instance data, setting up connection information
		if err := readInstance(d, meta); err != nil {
			return fmt.Errorf("[ERR] Error reading Spot Instance Data: %s", err)
		}
	}

	d.Set("spot_request_state", request.State)
	d.Set("block_duration_minutes", request.BlockDurationMinutes)
	d.Set("tags", tagsToMap(request.Tags))

	return nil
}

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

	resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{aws.String(d.Get("spot_instance_id").(string))},
	})
	if err != nil {
		// If the instance was not found, return nil so that we can show
		// that the instance is gone.
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" {
			return fmt.Errorf("no instance found")
		}

		// Some other error, report it
		return err
	}

	// If nothing was found, then return no state
	if len(resp.Reservations) == 0 {
		return fmt.Errorf("no instances found")
	}

	instance := resp.Reservations[0].Instances[0]

	// Set these fields for connection information
	if instance != nil {
		d.Set("public_dns", instance.PublicDnsName)
		d.Set("public_ip", instance.PublicIpAddress)
		d.Set("private_dns", instance.PrivateDnsName)
		d.Set("private_ip", instance.PrivateIpAddress)

		// set connection information
		if instance.PublicIpAddress != nil {
			d.SetConnInfo(map[string]string{
				"type": "ssh",
				"host": *instance.PublicIpAddress,
			})
		} else if instance.PrivateIpAddress != nil {
			d.SetConnInfo(map[string]string{
				"type": "ssh",
				"host": *instance.PrivateIpAddress,
			})
		}
		if err := readBlockDevices(d, instance, conn); err != nil {
			return err
		}

		var ipv6Addresses []string
		if len(instance.NetworkInterfaces) > 0 {
			for _, ni := range instance.NetworkInterfaces {
				if *ni.Attachment.DeviceIndex == 0 {
					d.Set("subnet_id", ni.SubnetId)
					d.Set("network_interface_id", ni.NetworkInterfaceId)
					d.Set("associate_public_ip_address", ni.Association != nil)
					d.Set("ipv6_address_count", len(ni.Ipv6Addresses))

					for _, address := range ni.Ipv6Addresses {
						ipv6Addresses = append(ipv6Addresses, *address.Ipv6Address)
					}
				}
			}
		} else {
			d.Set("subnet_id", instance.SubnetId)
			d.Set("network_interface_id", "")
		}

		if err := d.Set("ipv6_addresses", ipv6Addresses); err != nil {
			log.Printf("[WARN] Error setting ipv6_addresses for AWS Spot Instance (%s): %s", d.Id(), err)
		}
	}

	return nil
}

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

	d.Partial(true)
	if err := setTags(conn, d); err != nil {
		return err
	} else {
		d.SetPartial("tags")
	}

	d.Partial(false)

	return resourceAwsSpotInstanceRequestRead(d, meta)
}

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

	log.Printf("[INFO] Cancelling spot request: %s", d.Id())
	_, err := conn.CancelSpotInstanceRequests(&ec2.CancelSpotInstanceRequestsInput{
		SpotInstanceRequestIds: []*string{aws.String(d.Id())},
	})

	if err != nil {
		return fmt.Errorf("Error cancelling spot request (%s): %s", d.Id(), err)
	}

	if instanceId := d.Get("spot_instance_id").(string); instanceId != "" {
		log.Printf("[INFO] Terminating instance: %s", instanceId)
		if err := awsTerminateInstance(conn, instanceId); err != nil {
			return fmt.Errorf("Error terminating spot instance: %s", err)
		}
	}

	return nil
}

// SpotInstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// an EC2 spot instance request
func SpotInstanceStateRefreshFunc(
	conn *ec2.EC2, sir ec2.SpotInstanceRequest) resource.StateRefreshFunc {

	return func() (interface{}, string, error) {
		resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
			SpotInstanceRequestIds: []*string{sir.SpotInstanceRequestId},
		})

		if err != nil {
			if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on StateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil || len(resp.SpotInstanceRequests) == 0 {
			// Sometimes AWS just has consistency issues and doesn't see
			// our request yet. Return an empty state.
			return nil, "", nil
		}

		req := resp.SpotInstanceRequests[0]
		return req, *req.Status.Code, nil
	}
}
<|endoftext|>


<commit_before>package system

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type Shell struct {
	coverage   bool
	gobin      string
	reports    string
	extraFlags []string
}

func (self *Shell) GoTest(directory, packageName string) (output string, err error) {
	output, err = self.compileDependencies(directory)
	if err == nil {
		output, err = self.goTest(directory, packageName)
	}
	return
}

func (self *Shell) compileDependencies(directory string) (output string, err error) {
	return self.execute(directory, self.gobin, "test", "-i")
}

func (self *Shell) goTest(directory, packageName string) (output string, err error) {
	reportFilename := strings.Replace(packageName, string(os.PathSeparator), "-", -1)
	reportPath := filepath.Join(self.reports, reportFilename)
	profile := reportPath + ".txt"
	output, err = self.runWithCoverage(directory, profile)

	if err != nil && self.coverage {
		output, err = self.runWithoutCoverage(directory)
	} else if self.coverage {
		self.generateCoverageReports(directory, profile, reportPath+".html")
	}
	return
}

func (self *Shell) runWithCoverage(directory, profile string) (string, error) {
	arguments := []string{"test", "-v", "-timeout=-42s", "-covermode=set", "-coverprofile=" + profile}
	arguments = append(arguments, self.extraFlags...)
	return self.execute(directory, self.gobin, arguments...)
}
func (self *Shell) runWithoutCoverage(directory string) (string, error) {
	arguments := []string{"test", "-v", "-timeout=-42s"}
	arguments = append(arguments, self.extraFlags...)
	return self.execute(directory, self.gobin, arguments...)
}

func (self *Shell) generateCoverageReports(directory, profile, html string) {
	self.execute(directory, self.gobin, "tool", "cover", "-html="+profile, "-o", html)
}

func (self *Shell) execute(directory, name string, args ...string) (output string, err error) {
	command := exec.Command(name, args...)
	command.Dir = directory
	rawOutput, err := command.CombinedOutput()
	output = string(rawOutput)
	return
}

func (self *Shell) Getenv(key string) string {
	return os.Getenv(key)
}

func (self *Shell) Setenv(key, value string) error {
	if self.Getenv(key) != value {
		return os.Setenv(key, value)
	}
	return nil
}

func NewShell(gobin string, extraFlags string, cover bool, reports string) *Shell {
	self := new(Shell)
	self.gobin = gobin
	self.extraFlags = strings.Split(extraFlags, " ")
	self.reports = reports
	self.coverage = cover && goVersion_1_2_orGreater() && ensureReportDirectoryExists(self.reports)
	return self
}

func goVersion_1_2_orGreater() bool {
	version := runtime.Version() // 'go1.2....'
	major, minor := version[2], version[4]
	return major >= byte('1') && minor >= byte('2')
}

func ensureReportDirectoryExists(reports string) bool {
	if exists(reports) {
		return true
	}

	if err := os.Mkdir(reports, 0755); err == nil {
		return true
	}

	log.Printf(ReportDirectoryUnavailable, reports)
	return false
}

func exists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

const ReportDirectoryUnavailable = "Could not find or create the coverage report directory (at: '%s'). You probably won't see any coverage statistics...\n"
<commit_msg>Now making sure cover tool is installed.<commit_after>package system

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type Shell struct {
	coverage   bool
	gobin      string
	reports    string
	extraFlags []string // -short
}

func (self *Shell) GoTest(directory, packageName string) (output string, err error) {
	output, err = self.compileDependencies(directory)
	if err == nil {
		output, err = self.goTest(directory, packageName)
	}
	return
}

func (self *Shell) compileDependencies(directory string) (output string, err error) {
	return self.execute(directory, self.gobin, "test", "-i")
}

func (self *Shell) goTest(directory, packageName string) (output string, err error) {
	if !self.coverage {
		return self.runWithoutCoverage(directory)
	}

	reportFilename := strings.Replace(packageName, string(os.PathSeparator), "-", -1)
	reportPath := filepath.Join(self.reports, reportFilename)
	profile := reportPath + ".txt"
	output, err = self.runWithCoverage(directory, profile)

	if err != nil && self.coverage {
		output, err = self.runWithoutCoverage(directory)
	} else if self.coverage {
		self.generateCoverageReports(directory, profile, reportPath+".html")
	}
	return
}

func (self *Shell) runWithCoverage(directory, profile string) (string, error) {
	arguments := []string{"test", "-v", "-timeout=-42s", "-covermode=set", "-coverprofile=" + profile}
	arguments = append(arguments, self.extraFlags...)
	return self.execute(directory, self.gobin, arguments...)
}
func (self *Shell) runWithoutCoverage(directory string) (string, error) {
	arguments := []string{"test", "-v", "-timeout=-42s"}
	arguments = append(arguments, self.extraFlags...)
	return self.execute(directory, self.gobin, arguments...)
}

func (self *Shell) generateCoverageReports(directory, profile, html string) {
	self.execute(directory, self.gobin, "tool", "cover", "-html="+profile, "-o", html)
}

func (self *Shell) execute(directory, name string, args ...string) (output string, err error) {
	command := exec.Command(name, args...)
	command.Dir = directory
	rawOutput, err := command.CombinedOutput()
	output = string(rawOutput)
	return
}

func (self *Shell) Getenv(key string) string {
	return os.Getenv(key)
}

func (self *Shell) Setenv(key, value string) error {
	if self.Getenv(key) != value {
		return os.Setenv(key, value)
	}
	return nil
}

func NewShell(gobin string, extraFlags string, cover bool, reports string) *Shell {
	self := new(Shell)
	self.gobin = gobin
	self.extraFlags = strings.Split(extraFlags, " ")
	self.coverage = self.coverageEnabled(cover, reports)
	self.reports = reports
	return self
}

func (self *Shell) coverageEnabled(cover bool, reports string) bool {
	return (cover &&
		goVersion_1_2_orGreater() &&
		self.coverToolInstalled() &&
		ensureReportDirectoryExists(reports))
}

func goVersion_1_2_orGreater() bool {
	version := runtime.Version() // 'go1.2....'
	major, minor := version[2], version[4]
	version_1_2 := major >= byte('1') && minor >= byte('2')
	if !version_1_2 {
		log.Printf(pleaseUpgradeGoVersion, version)
		return false
	}
	return true
}

func (self *Shell) coverToolInstalled() bool {
	working, err := os.Getwd()
	if err != nil {
		working = "."
	}
	output, _ := self.execute(working, "go", "tool", "cover")
	installed := strings.Contains(output, "Usage of 'go tool cover':")
	if !installed {
		log.Print(coverToolMissing)
		return false
	}
	return true
}

func ensureReportDirectoryExists(reports string) bool {
	if exists(reports) {
		return true
	}

	if err := os.Mkdir(reports, 0755); err == nil {
		return true
	}

	log.Printf(reportDirectoryUnavailable, reports)
	return false
}

func exists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

const (
	pleaseUpgradeGoVersion     = "Go version is less that 1.2 (%s), please upgrade to the latest stable version to enable coverage reporting.\n"
	coverToolMissing           = "Go cover tool is not installed or not accessible: `go get code.google.com/p/go.tools/cmd/cover`\n"
	reportDirectoryUnavailable = "Could not find or create the coverage report directory (at: '%s'). You probably won't see any coverage statistics...\n"
)
<|endoftext|>


<commit_before>package imagestore

import (
	"io"
	"io/ioutil"

	"github.com/mitchellh/goamz/s3"
)

type S3ImageStore struct {
	bucketName     string
	storeRoot      string
	client         *s3.S3
	namePathMapper *NamePathMapper
}

func NewS3ImageStore(bucket string, root string, client *s3.S3, mapper *NamePathMapper) *S3ImageStore {
	return &S3ImageStore{
		bucketName:     bucket,
		storeRoot:      root,
		client:         client,
		namePathMapper: mapper,
	}
}

func (this *S3ImageStore) Exists(obj *StoreObject) (bool, error) {
	bucket := this.client.Bucket(this.bucketName)
	response, err := bucket.Head(this.toPath(obj))
	if err != nil {
		return false, err
	}

	return (response.StatusCode == 200), nil
}

func (this *S3ImageStore) Save(src io.Reader, obj *StoreObject) (*StoreObject, error) {
	bucket := this.client.Bucket(this.bucketName)

	data, err := ioutil.ReadAll(src)
	if err != nil {
		return nil, err
	}

	err = bucket.Put(this.toPath(obj), data, obj.MimeType, s3.PublicReadWrite)
	if err != nil {
		return nil, err
	}

	obj.Url = "https://s3.amazonaws.com/" + this.bucketName + this.toPath(obj)
	return obj, nil
}

func (this *S3ImageStore) toPath(obj *StoreObject) string {
	return this.storeRoot + "/" + this.namePathMapper.mapToPath(obj)
}
<commit_msg>Use `bucket.URL()` to generate url for an object.<commit_after>package imagestore

import (
	"io"
	"io/ioutil"

	"github.com/mitchellh/goamz/s3"
)

type S3ImageStore struct {
	bucketName     string
	storeRoot      string
	client         *s3.S3
	namePathMapper *NamePathMapper
}

func NewS3ImageStore(bucket string, root string, client *s3.S3, mapper *NamePathMapper) *S3ImageStore {
	return &S3ImageStore{
		bucketName:     bucket,
		storeRoot:      root,
		client:         client,
		namePathMapper: mapper,
	}
}

func (this *S3ImageStore) Exists(obj *StoreObject) (bool, error) {
	bucket := this.client.Bucket(this.bucketName)
	response, err := bucket.Head(this.toPath(obj))
	if err != nil {
		return false, err
	}

	return (response.StatusCode == 200), nil
}

func (this *S3ImageStore) Save(src io.Reader, obj *StoreObject) (*StoreObject, error) {
	bucket := this.client.Bucket(this.bucketName)

	data, err := ioutil.ReadAll(src)
	if err != nil {
		return nil, err
	}

	err = bucket.Put(this.toPath(obj), data, obj.MimeType, s3.PublicReadWrite)
	if err != nil {
		return nil, err
	}

	obj.Url = bucket.URL(this.toPath(obj))
	return obj, nil
}

func (this *S3ImageStore) toPath(obj *StoreObject) string {
	return this.storeRoot + "/" + this.namePathMapper.mapToPath(obj)
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 perf is to add performance measuring hooks to a runner, such as cpu, or trace profiles.
package perf

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"runtime/pprof"
	"runtime/trace"

	"github.com/apache/beam/sdks/go/pkg/beam/core/util/hooks"
	fnpb "github.com/apache/beam/sdks/go/pkg/beam/model/fnexecution_v1"
)

// CaptureHook is used by the harness to have the runner
// persist a trace record with the supplied name and comment.
// The type of trace can be determined by the prefix of the string.
//
// * prof: A profile compatible with traces produced by runtime/pprof
// * trace: A trace compatible with traces produced by runtime/trace
type CaptureHook func(context.Context, string, io.Reader) error

// CaptureHookFactory creates a CaptureHook from the supplied options.
type CaptureHookFactory func([]string) CaptureHook

var profCaptureHookRegistry = make(map[string]CaptureHookFactory)

var enabledProfCaptureHooks []string

func init() {
	hf := func(opts []string) hooks.Hook {
		enabledProfCaptureHooks = opts
		enabled := len(enabledProfCaptureHooks) > 0
		var cpuProfBuf bytes.Buffer
		return hooks.Hook{
			Req: func(ctx context.Context, _ *fnpb.InstructionRequest) (context.Context, error) {
				if !enabled {
					return ctx, nil
				}
				cpuProfBuf.Reset()
				return ctx, pprof.StartCPUProfile(&cpuProfBuf)
			},
			Resp: func(ctx context.Context, req *fnpb.InstructionRequest, _ *fnpb.InstructionResponse) error {
				if !enabled {
					return nil
				}
				pprof.StopCPUProfile()
				for _, h := range enabledProfCaptureHooks {
					name, opts := hooks.Decode(h)
					if err := profCaptureHookRegistry[name](opts)(ctx, fmt.Sprintf("prof%s", req.InstructionId), &cpuProfBuf); err != nil {
						return err
					}
				}
				return nil
			},
		}
	}
	hooks.RegisterHook("prof", hf)

	hf = func(opts []string) hooks.Hook {
		var traceProfBuf bytes.Buffer
		enabledTraceCaptureHooks = opts
		enabled := len(enabledTraceCaptureHooks) > 0
		return hooks.Hook{
			Req: func(ctx context.Context, _ *fnpb.InstructionRequest) (context.Context, error) {
				if !enabled {
					return ctx, nil
				}
				traceProfBuf.Reset()
				return ctx, trace.Start(&traceProfBuf)
			},
			Resp: func(ctx context.Context, req *fnpb.InstructionRequest, _ *fnpb.InstructionResponse) error {
				if !enabled {
					return nil
				}
				trace.Stop()
				for _, h := range enabledTraceCaptureHooks {
					name, opts := hooks.Decode(h)
					if err := traceCaptureHookRegistry[name](opts)(ctx, fmt.Sprintf("trace_prof%s", req.InstructionId), &traceProfBuf); err != nil {
						return err
					}
				}
				return nil
			},
		}
	}
	hooks.RegisterHook("trace", hf)
}

// RegisterProfCaptureHook registers a CaptureHookFactory for the
// supplied identifier. It panics if the same identifier is
// registered twice.
func RegisterProfCaptureHook(name string, c CaptureHookFactory) {
	if _, exists := profCaptureHookRegistry[name]; exists {
		panic(fmt.Sprintf("RegisterProfCaptureHook: %s registered twice", name))
	}
	profCaptureHookRegistry[name] = c
}

// EnableProfCaptureHook actives a registered profile capture hook for a given pipeline.
func EnableProfCaptureHook(name string, opts ...string) {
	_, exists := profCaptureHookRegistry[name]
	if !exists {
		panic(fmt.Sprintf("EnableProfCaptureHook: %s not registered", name))
	}

	enc := hooks.Encode(name, opts)

	for i, h := range enabledProfCaptureHooks {
		n, _ := hooks.Decode(h)
		if h == n {
			// Rewrite the registration with the current arguments
			enabledProfCaptureHooks[i] = enc
			hooks.EnableHook("prof", enabledProfCaptureHooks...)
			return
		}
	}

	enabledProfCaptureHooks = append(enabledProfCaptureHooks, enc)
	hooks.EnableHook("prof", enabledProfCaptureHooks...)
}

var traceCaptureHookRegistry = make(map[string]CaptureHookFactory)
var enabledTraceCaptureHooks []string

// RegisterTraceCaptureHook registers a CaptureHookFactory for the
// supplied identifier. It panics if the same identifier is
// registered twice.
func RegisterTraceCaptureHook(name string, c CaptureHookFactory) {
	if _, exists := traceCaptureHookRegistry[name]; exists {
		panic(fmt.Sprintf("RegisterTraceCaptureHook: %s registered twice", name))
	}
	traceCaptureHookRegistry[name] = c
}

// EnableTraceCaptureHook actives a registered profile capture hook for a given pipeline.
func EnableTraceCaptureHook(name string, opts ...string) {
	if _, exists := traceCaptureHookRegistry[name]; !exists {
		panic(fmt.Sprintf("EnableTraceCaptureHook: %s not registered", name))
	}

	enc := hooks.Encode(name, opts)
	for i, h := range enabledTraceCaptureHooks {
		n, _ := hooks.Decode(h)
		if h == n {
			// Rewrite the registration with the current arguments
			enabledTraceCaptureHooks[i] = enc
			hooks.EnableHook("trace", enabledTraceCaptureHooks...)
			return
		}
	}
	enabledTraceCaptureHooks = append(enabledTraceCaptureHooks, enc)
	hooks.EnableHook("trace", enabledTraceCaptureHooks...)
}
<commit_msg>Update perf.go: only trigger on processing bundles<commit_after>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 perf is to add performance measuring hooks to a runner, such as cpu, or trace profiles.
package perf

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"runtime/pprof"
	"runtime/trace"

	"github.com/apache/beam/sdks/go/pkg/beam/core/util/hooks"
	fnpb "github.com/apache/beam/sdks/go/pkg/beam/model/fnexecution_v1"
)

// CaptureHook is used by the harness to have the runner
// persist a trace record with the supplied name and comment.
// The type of trace can be determined by the prefix of the string.
//
// * prof: A profile compatible with traces produced by runtime/pprof
// * trace: A trace compatible with traces produced by runtime/trace
type CaptureHook func(context.Context, string, io.Reader) error

// CaptureHookFactory creates a CaptureHook from the supplied options.
type CaptureHookFactory func([]string) CaptureHook

var profCaptureHookRegistry = make(map[string]CaptureHookFactory)

var enabledProfCaptureHooks []string

func init() {
	hf := func(opts []string) hooks.Hook {
		enabledProfCaptureHooks = opts
		enabled := len(enabledProfCaptureHooks) > 0
		var cpuProfBuf bytes.Buffer
		return hooks.Hook{
			Req: func(ctx context.Context,  req *fnpb.InstructionRequest) (context.Context, error) {
				if !enabled || req.GetProcessBundle() == nil {
					return ctx, nil
				}
				cpuProfBuf.Reset()
				return ctx, pprof.StartCPUProfile(&cpuProfBuf)
			},
			Resp: func(ctx context.Context, req *fnpb.InstructionRequest, _ *fnpb.InstructionResponse) error {
				if !enabled || req.GetProcessBundle() == nil {
					return nil
				}
				pprof.StopCPUProfile()
				for _, h := range enabledProfCaptureHooks {
					name, opts := hooks.Decode(h)
					if err := profCaptureHookRegistry[name](opts)(ctx, fmt.Sprintf("prof%s", req.InstructionId), &cpuProfBuf); err != nil {
						return err
					}
				}
				return nil
			},
		}
	}
	hooks.RegisterHook("prof", hf)

	hf = func(opts []string) hooks.Hook {
		var traceProfBuf bytes.Buffer
		enabledTraceCaptureHooks = opts
		enabled := len(enabledTraceCaptureHooks) > 0
		return hooks.Hook{
			Req: func(ctx context.Context, _ *fnpb.InstructionRequest) (context.Context, error) {
				if !enabled {
					return ctx, nil
				}
				traceProfBuf.Reset()
				return ctx, trace.Start(&traceProfBuf)
			},
			Resp: func(ctx context.Context, req *fnpb.InstructionRequest, _ *fnpb.InstructionResponse) error {
				if !enabled {
					return nil
				}
				trace.Stop()
				for _, h := range enabledTraceCaptureHooks {
					name, opts := hooks.Decode(h)
					if err := traceCaptureHookRegistry[name](opts)(ctx, fmt.Sprintf("trace_prof%s", req.InstructionId), &traceProfBuf); err != nil {
						return err
					}
				}
				return nil
			},
		}
	}
	hooks.RegisterHook("trace", hf)
}

// RegisterProfCaptureHook registers a CaptureHookFactory for the
// supplied identifier. It panics if the same identifier is
// registered twice.
func RegisterProfCaptureHook(name string, c CaptureHookFactory) {
	if _, exists := profCaptureHookRegistry[name]; exists {
		panic(fmt.Sprintf("RegisterProfCaptureHook: %s registered twice", name))
	}
	profCaptureHookRegistry[name] = c
}

// EnableProfCaptureHook actives a registered profile capture hook for a given pipeline.
func EnableProfCaptureHook(name string, opts ...string) {
	_, exists := profCaptureHookRegistry[name]
	if !exists {
		panic(fmt.Sprintf("EnableProfCaptureHook: %s not registered", name))
	}

	enc := hooks.Encode(name, opts)

	for i, h := range enabledProfCaptureHooks {
		n, _ := hooks.Decode(h)
		if h == n {
			// Rewrite the registration with the current arguments
			enabledProfCaptureHooks[i] = enc
			hooks.EnableHook("prof", enabledProfCaptureHooks...)
			return
		}
	}

	enabledProfCaptureHooks = append(enabledProfCaptureHooks, enc)
	hooks.EnableHook("prof", enabledProfCaptureHooks...)
}

var traceCaptureHookRegistry = make(map[string]CaptureHookFactory)
var enabledTraceCaptureHooks []string

// RegisterTraceCaptureHook registers a CaptureHookFactory for the
// supplied identifier. It panics if the same identifier is
// registered twice.
func RegisterTraceCaptureHook(name string, c CaptureHookFactory) {
	if _, exists := traceCaptureHookRegistry[name]; exists {
		panic(fmt.Sprintf("RegisterTraceCaptureHook: %s registered twice", name))
	}
	traceCaptureHookRegistry[name] = c
}

// EnableTraceCaptureHook actives a registered profile capture hook for a given pipeline.
func EnableTraceCaptureHook(name string, opts ...string) {
	if _, exists := traceCaptureHookRegistry[name]; !exists {
		panic(fmt.Sprintf("EnableTraceCaptureHook: %s not registered", name))
	}

	enc := hooks.Encode(name, opts)
	for i, h := range enabledTraceCaptureHooks {
		n, _ := hooks.Decode(h)
		if h == n {
			// Rewrite the registration with the current arguments
			enabledTraceCaptureHooks[i] = enc
			hooks.EnableHook("trace", enabledTraceCaptureHooks...)
			return
		}
	}
	enabledTraceCaptureHooks = append(enabledTraceCaptureHooks, enc)
	hooks.EnableHook("trace", enabledTraceCaptureHooks...)
}
<|endoftext|>


<commit_before>package main

import "C"

//export string_output
func string_output() *C.char {
    return C.CString("Hello")
}

func main(){}
<commit_msg>Use proper memory management for C string allocated by Go library.<commit_after>package main

// #include <stdlib.h>
import "C"
import "unsafe"

//export string_output
func string_output() *C.char {
    var cstr = C.CString("Hello")
    defer C.free(unsafe.Pointer(cstr))
    return cstr
}

func main(){}
<|endoftext|>


<commit_before>package rest

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

	"github.com/mweagle/Sparta"
	"github.com/pkg/errors"
)

var allHTTPMethods = strings.Join([]string{
	http.MethodGet,
	http.MethodHead,
	http.MethodPost,
	http.MethodPut,
	http.MethodPatch,
	http.MethodDelete,
	http.MethodConnect,
	http.MethodOptions,
	http.MethodTrace,
}, " ")

// MethodHandlerMap is a map of http method names to their handlers
type MethodHandlerMap map[string]*MethodHandler

// MethodHandler represents a handler for a given HTTP method
type MethodHandler struct {
	DefaultCode  int
	allowedCodes []int
	Handler      interface{}
	privileges   []sparta.IAMRolePrivilege
	headers      []string
}

// AllowedCodes is a fluent builder to append additional HTTP status codes
// for the given MethodHandler. It's primarily used to disamgiguate
// input from the NewMethodHandler constructor
func (mh *MethodHandler) AllowedCodes(codes ...int) *MethodHandler {
	if mh.allowedCodes == nil {
		mh.allowedCodes = make([]int, 0)
	}
	for _, eachCode := range codes {
		mh.allowedCodes = append(mh.allowedCodes, eachCode)
	}
	return mh
}

// Privileges is the fluent builder to associated IAM privileges with this
// HTTP handler
func (mh *MethodHandler) Privileges(privileges ...sparta.IAMRolePrivilege) *MethodHandler {
	if mh.privileges == nil {
		mh.privileges = make([]sparta.IAMRolePrivilege, 0)
	}
	for _, eachPrivilege := range privileges {
		mh.privileges = append(mh.privileges, eachPrivilege)
	}
	return mh
}

// Headers is the fluent builder that defines what headers this method returns
func (mh *MethodHandler) Headers(headerNames ...string) *MethodHandler {
	if mh.headers == nil {
		mh.headers = make([]string, 0)
	}
	for _, eachHeader := range headerNames {
		mh.headers = append(mh.headers, eachHeader)
	}
	return mh
}

// NewMethodHandler is a constructor function to return a new MethodHandler
// pointer instance.
func NewMethodHandler(handler interface{}, defaultCode int) *MethodHandler {
	return &MethodHandler{
		DefaultCode: defaultCode,
		Handler:     handler,
	}
}

// ResourceDefinition represents a set of handlers for a given URL path
type ResourceDefinition struct {
	URL            string
	MethodHandlers MethodHandlerMap
}

// Resource defines the interface an object must define in order to
// provide a ResourceDefinition
type Resource interface {
	ResourceDefinition() (ResourceDefinition, error)
}

// RegisterResource creates a set of lambda handlers for the given resource
// and registers them with the apiGateway. The sparta Lambda handler returned
// slice is eligible
func RegisterResource(apiGateway *sparta.API,
	resource Resource) (map[string]*sparta.LambdaAWSInfo, error) {

	definition, definitionErr := resource.ResourceDefinition()
	if definitionErr != nil {
		return nil, errors.Wrapf(definitionErr, "requesting ResourceDefinition from provider")
	}

	urlParts, urlPartsErr := url.Parse(definition.URL)
	if urlPartsErr != nil {
		return nil, errors.Wrapf(urlPartsErr, "parsing REST URL: %s", definition.URL)
	}
	// Any query params?
	queryParams, queryParamsErr := url.ParseQuery(urlParts.RawQuery)
	if nil != queryParamsErr {
		return nil, errors.Wrap(queryParamsErr, "parsing REST URL query params")
	}

	// Any path params?
	pathParams := []string{}
	pathParts := strings.Split(urlParts.Path, "/")
	for _, eachPathPart := range pathParts {
		trimmedPathPart := strings.Trim(eachPathPart, "{}")
		if trimmedPathPart != eachPathPart {
			pathParams = append(pathParams, trimmedPathPart)
		}
	}

	// Local function to produce a friendlyname for the provider
	lambdaName := func(methodName string) string {
		nameValue := fmt.Sprintf("%T_%s", resource, methodName)
		return strings.Trim(nameValue, "_-.()*")
	}

	// Local function to handle registering the function with API Gateway
	createAPIGEntry := func(methodName string,
		methodHandler *MethodHandler,
		handler *sparta.LambdaAWSInfo) error {
		apiGWResource, apiGWResourceErr := apiGateway.NewResource(definition.URL, handler)
		if apiGWResourceErr != nil {
			return errors.Wrapf(apiGWResourceErr, "attempting to create API Gateway Resource")
		}
		allowedCodes := methodHandler.allowedCodes
		if allowedCodes == nil {
			allowedCodes = []int{}
		}
		// We only return http.StatusOK
		apiMethod, apiMethodErr := apiGWResource.NewMethod(methodName,
			methodHandler.DefaultCode,
			allowedCodes...)
		if apiMethodErr != nil {
			return apiMethodErr
		}
		// Do anything smart with the URL? Split the URL into components to first see
		// if it's a URL template
		for _, eachPathPart := range pathParams {
			apiMethod.Parameters[fmt.Sprintf("method.request.path.%s", eachPathPart)] = true
		}

		// Then parse it to see what's up with the query param names
		for eachQueryParam := range queryParams {
			apiMethod.Parameters[fmt.Sprintf("method.request.querystring.%s", eachQueryParam)] = true
		}
		// Any headers?
		for _, eachHeader := range methodHandler.headers {
			// Make this an optional header on the method response
			lowercaseHeader := strings.ToLower(eachHeader)
			methodHeaderKey := fmt.Sprintf("method.response.header.%s", lowercaseHeader)

			for _, eachResponse := range apiMethod.Responses {
				eachResponse.Parameters[methodHeaderKey] = false
			}
			// Add it to the integration mappings
			// Then ensure every integration response knows how to pass it along...
			inputSelector := fmt.Sprintf(`'$input.json("$.headers.%s")'`, lowercaseHeader)
			for _, eachIntegrationResponse := range apiMethod.Integration.Responses {
				if len(eachIntegrationResponse.Parameters) <= 0 {
					eachIntegrationResponse.Parameters = make(map[string]interface{})
				}
				eachIntegrationResponse.Parameters[methodHeaderKey] = inputSelector
			}
		}

		return nil
	}
	resourceMap := make(map[string]*sparta.LambdaAWSInfo, 0)

	// Great, walk the map of handlers
	for eachMethod, eachMethodDefinition := range definition.MethodHandlers {
		if !strings.Contains(allHTTPMethods, eachMethod) {
			return nil, errors.Errorf("unsupported HTTP method name: %s", eachMethod)
		}
		lambdaFn := sparta.HandleAWSLambda(lambdaName(eachMethod),
			eachMethodDefinition.Handler,
			sparta.IAMRoleDefinition{})
		resourceMap[eachMethod] = lambdaFn

		// Any privs?
		if len(eachMethodDefinition.privileges) != 0 {
			lambdaFn.RoleDefinition.Privileges = eachMethodDefinition.privileges
		}

		// Register the route...
		apiGWRegistrationErr := createAPIGEntry(eachMethod, eachMethodDefinition, lambdaFn)
		if apiGWRegistrationErr != nil {
			return nil, errors.Wrapf(apiGWRegistrationErr, "attemping to create resource for method: %s", http.MethodHead)
		}
	}
	if len(resourceMap) <= 0 {
		return nil, errors.Errorf("No resource methodHandlers found for resource: %T", resource)
	}
	return resourceMap, nil
}
<commit_msg>Prefer StatusCodes fluent builder name<commit_after>package rest

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

	"github.com/mweagle/Sparta"
	"github.com/pkg/errors"
)

var allHTTPMethods = strings.Join([]string{
	http.MethodGet,
	http.MethodHead,
	http.MethodPost,
	http.MethodPut,
	http.MethodPatch,
	http.MethodDelete,
	http.MethodConnect,
	http.MethodOptions,
	http.MethodTrace,
}, " ")

// MethodHandlerMap is a map of http method names to their handlers
type MethodHandlerMap map[string]*MethodHandler

// MethodHandler represents a handler for a given HTTP method
type MethodHandler struct {
	DefaultCode int
	statusCodes []int
	Handler     interface{}
	privileges  []sparta.IAMRolePrivilege
	headers     []string
}

// StatusCodes is a fluent builder to append additional HTTP status codes
// for the given MethodHandler. It's primarily used to disamgiguate
// input from the NewMethodHandler constructor
func (mh *MethodHandler) StatusCodes(codes ...int) *MethodHandler {
	if mh.statusCodes == nil {
		mh.statusCodes = make([]int, 0)
	}
	for _, eachCode := range codes {
		mh.statusCodes = append(mh.statusCodes, eachCode)
	}
	return mh
}

// Privileges is the fluent builder to associated IAM privileges with this
// HTTP handler
func (mh *MethodHandler) Privileges(privileges ...sparta.IAMRolePrivilege) *MethodHandler {
	if mh.privileges == nil {
		mh.privileges = make([]sparta.IAMRolePrivilege, 0)
	}
	for _, eachPrivilege := range privileges {
		mh.privileges = append(mh.privileges, eachPrivilege)
	}
	return mh
}

// Headers is the fluent builder that defines what headers this method returns
func (mh *MethodHandler) Headers(headerNames ...string) *MethodHandler {
	if mh.headers == nil {
		mh.headers = make([]string, 0)
	}
	for _, eachHeader := range headerNames {
		mh.headers = append(mh.headers, eachHeader)
	}
	return mh
}

// NewMethodHandler is a constructor function to return a new MethodHandler
// pointer instance.
func NewMethodHandler(handler interface{}, defaultCode int) *MethodHandler {
	return &MethodHandler{
		DefaultCode: defaultCode,
		Handler:     handler,
	}
}

// ResourceDefinition represents a set of handlers for a given URL path
type ResourceDefinition struct {
	URL            string
	MethodHandlers MethodHandlerMap
}

// Resource defines the interface an object must define in order to
// provide a ResourceDefinition
type Resource interface {
	ResourceDefinition() (ResourceDefinition, error)
}

// RegisterResource creates a set of lambda handlers for the given resource
// and registers them with the apiGateway. The sparta Lambda handler returned
// slice is eligible
func RegisterResource(apiGateway *sparta.API,
	resource Resource) (map[string]*sparta.LambdaAWSInfo, error) {

	definition, definitionErr := resource.ResourceDefinition()
	if definitionErr != nil {
		return nil, errors.Wrapf(definitionErr, "requesting ResourceDefinition from provider")
	}

	urlParts, urlPartsErr := url.Parse(definition.URL)
	if urlPartsErr != nil {
		return nil, errors.Wrapf(urlPartsErr, "parsing REST URL: %s", definition.URL)
	}
	// Any query params?
	queryParams, queryParamsErr := url.ParseQuery(urlParts.RawQuery)
	if nil != queryParamsErr {
		return nil, errors.Wrap(queryParamsErr, "parsing REST URL query params")
	}

	// Any path params?
	pathParams := []string{}
	pathParts := strings.Split(urlParts.Path, "/")
	for _, eachPathPart := range pathParts {
		trimmedPathPart := strings.Trim(eachPathPart, "{}")
		if trimmedPathPart != eachPathPart {
			pathParams = append(pathParams, trimmedPathPart)
		}
	}

	// Local function to produce a friendlyname for the provider
	lambdaName := func(methodName string) string {
		nameValue := fmt.Sprintf("%T_%s", resource, methodName)
		return strings.Trim(nameValue, "_-.()*")
	}

	// Local function to handle registering the function with API Gateway
	createAPIGEntry := func(methodName string,
		methodHandler *MethodHandler,
		handler *sparta.LambdaAWSInfo) error {
		apiGWResource, apiGWResourceErr := apiGateway.NewResource(definition.URL, handler)
		if apiGWResourceErr != nil {
			return errors.Wrapf(apiGWResourceErr, "attempting to create API Gateway Resource")
		}
		statusCodes := methodHandler.statusCodes
		if statusCodes == nil {
			statusCodes = []int{}
		}
		// We only return http.StatusOK
		apiMethod, apiMethodErr := apiGWResource.NewMethod(methodName,
			methodHandler.DefaultCode,
			statusCodes...)
		if apiMethodErr != nil {
			return apiMethodErr
		}
		// Do anything smart with the URL? Split the URL into components to first see
		// if it's a URL template
		for _, eachPathPart := range pathParams {
			apiMethod.Parameters[fmt.Sprintf("method.request.path.%s", eachPathPart)] = true
		}

		// Then parse it to see what's up with the query param names
		for eachQueryParam := range queryParams {
			apiMethod.Parameters[fmt.Sprintf("method.request.querystring.%s", eachQueryParam)] = true
		}
		// Any headers?
		for _, eachHeader := range methodHandler.headers {
			// Make this an optional header on the method response
			lowercaseHeader := strings.ToLower(eachHeader)
			methodHeaderKey := fmt.Sprintf("method.response.header.%s", lowercaseHeader)

			for _, eachResponse := range apiMethod.Responses {
				eachResponse.Parameters[methodHeaderKey] = false
			}
			// Add it to the integration mappings
			// Then ensure every integration response knows how to pass it along...
			inputSelector := fmt.Sprintf(`'$input.json("$.headers.%s")'`, lowercaseHeader)
			for _, eachIntegrationResponse := range apiMethod.Integration.Responses {
				if len(eachIntegrationResponse.Parameters) <= 0 {
					eachIntegrationResponse.Parameters = make(map[string]interface{})
				}
				eachIntegrationResponse.Parameters[methodHeaderKey] = inputSelector
			}
		}

		return nil
	}
	resourceMap := make(map[string]*sparta.LambdaAWSInfo, 0)

	// Great, walk the map of handlers
	for eachMethod, eachMethodDefinition := range definition.MethodHandlers {
		if !strings.Contains(allHTTPMethods, eachMethod) {
			return nil, errors.Errorf("unsupported HTTP method name: %s", eachMethod)
		}
		lambdaFn := sparta.HandleAWSLambda(lambdaName(eachMethod),
			eachMethodDefinition.Handler,
			sparta.IAMRoleDefinition{})
		resourceMap[eachMethod] = lambdaFn

		// Any privs?
		if len(eachMethodDefinition.privileges) != 0 {
			lambdaFn.RoleDefinition.Privileges = eachMethodDefinition.privileges
		}

		// Register the route...
		apiGWRegistrationErr := createAPIGEntry(eachMethod, eachMethodDefinition, lambdaFn)
		if apiGWRegistrationErr != nil {
			return nil, errors.Wrapf(apiGWRegistrationErr, "attemping to create resource for method: %s", http.MethodHead)
		}
	}
	if len(resourceMap) <= 0 {
		return nil, errors.Errorf("No resource methodHandlers found for resource: %T", resource)
	}
	return resourceMap, nil
}
<|endoftext|>


<commit_before>package auth

import "github.com/micro/go-micro/v2/auth"

// TokenCookieName is the name of the cookie which stores the auth token
const TokenCookieName = "micro-token"

// SystemRules are the default rules which are applied to the runtime services
var SystemRules = []*auth.Rule{
	&auth.Rule{
		ID:       "default",
		Scope:    "*",
		Resource: &auth.Resource{Type: "*", Name: "*", Endpoint: "*"},
	},
	&auth.Rule{
		ID:       "auth-public",
		Scope:    "",
		Resource: &auth.Resource{Type: "service", Name: "go.micro.auth", Endpoint: "*"},
	},
	&auth.Rule{
		ID:       "registry-get",
		Scope:    "",
		Resource: &auth.Resource{Type: "service", Name: "go.micro.registry", Endpoint: "Registry.GetService"},
	},
	&auth.Rule{
		ID:       "registry-list",
		Scope:    "",
		Resource: &auth.Resource{Type: "service", Name: "go.micro.registry", Endpoint: "Registry.ListServices"},
	},
}
<commit_msg>internal/auth: make all server endpoints public by default<commit_after>package auth

import "github.com/micro/go-micro/v2/auth"

// TokenCookieName is the name of the cookie which stores the auth token
const TokenCookieName = "micro-token"

// SystemRules are the default rules which are applied to the runtime services
var SystemRules = []*auth.Rule{
	&auth.Rule{
		ID:       "default",
		Scope:    "",
		Resource: &auth.Resource{Type: "*", Name: "*", Endpoint: "*"},
	},
}
<|endoftext|>


<commit_before>// +build !linux

package xattr

func Get(path, name string) ([]byte, error) {
	return nil, nil
}
func Set(path, name string, value []byte) error {
	return nil
}
func List(path string) ([]string, error) {
	return nil, nil
}
<commit_msg>xattr: the unsupported features weren't linted<commit_after>// +build !linux

package xattr

// Get would return the extended attributes, but this unsupported feature
// returns nil, nil
func Get(path, name string) ([]byte, error) {
	return nil, nil
}

// Set would set the extended attributes, but this unsupported feature returns
// nil
func Set(path, name string, value []byte) error {
	return nil
}

// List would return the keys of extended attributes, but this unsupported
// feature returns nil, nil
func List(path string) ([]string, error) {
	return nil, nil
}
<|endoftext|>