<commit_before>package gotest

import (
	"testing"
	"os"
	"os/exec"
	"bytes"
	"strings"
)

// HELPER
// copy test source file `*.c` to tmp dir
func copyCSourceFile(name string, t *testing.T) (string, string) {
	t.Logf("Copying file %s ...", name)

	absPath, _ := os.Getwd()
	baseDir, projectDir := absPath+"/tmp", absPath+"/../.."
	os.MkdirAll(baseDir, os.ModePerm)

	cpCmd := exec.Command("cp", projectDir+"/src/test/resources/c/"+name, baseDir+"/Main.c")
	cpErr := cpCmd.Run()

	if cpErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(cpErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return baseDir, projectDir
}

// HELPER
// compile C source file
func compileC(name, baseDir, projectDir string, t *testing.T) (string) {
	t.Logf("Compiling file %s ...", name)

	var compilerStderr bytes.Buffer
	compilerCmd := exec.Command(projectDir+"/bin/c_compiler", "-basedir="+baseDir)
	compilerCmd.Stderr = &compilerStderr
	compilerErr := compilerCmd.Run()

	if compilerErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return compilerStderr.String()
}

// HELPER
// run C binary in our container
func runC(baseDir, projectDir string, t *testing.T) (string) {
	t.Log("Running binary /Main ...")

	var containerStdout bytes.Buffer
	containerArgs := []string{"-basedir=" + baseDir, "-input=10:10:23PM", "-expected=22:10:23", "-memory=16"}
	containerCmd := exec.Command(projectDir+"/bin/c_container", containerArgs...)
	containerCmd.Stdout = &containerStdout
	containerErr := containerCmd.Run()

	if containerErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return containerStdout.String()
}

func Test_C_AC(t *testing.T) {
	name := "ac.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)
	if !strings.Contains(containerErr, "\"status\":0") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr + " => status != 0")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_0(t *testing.T) {
	name := "compiler_bomb_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_1(t *testing.T) {
	name := "compiler_bomb_1.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_2(t *testing.T) {
	name := "compiler_bomb_2.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Fork_Bomb(t *testing.T) {
	name := "fork_bomb.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "Runtime Error") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Get_Host_By_Name(t *testing.T) {
	name := "tcp_client.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	// Main.c:(.text+0x28): warning: Using 'gethostbyname' in statically linked applications
	// requires at runtime the shared libraries from the glibc version used for linking
	if !strings.Contains(containerErr, "\"status\":2") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Include_Leaks(t *testing.T) {
	name := "include_leaks.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "/etc/shadow") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `/etc/shadow`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Infinite_Loop(t *testing.T) {
	name := "infinite_loop.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "Runtime Error") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Memory_Allocation(t *testing.T) {
	name := "memory_allocation.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	// `Killed` is sent to tty by kernel (and record will also be kept in /var/log/message)
	// both stdout and stderr are empty which will lead to status WA
	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Plain_Text(t *testing.T) {
	name := "plain_text.c"
	baseDir, projectDir := copyCSourceFile(name, t)

	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "error") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `error`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Run_Command_Line_0(t *testing.T) {
	name := "run_command_line_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Run_Command_Line_1(t *testing.T) {
	name := "run_command_line_1.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Syscall_0(t *testing.T) {
	name := "syscall_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}
<commit_msg>bugfix: wrong test filename<commit_after>package gotest

import (
	"testing"
	"os"
	"os/exec"
	"bytes"
	"strings"
)

// HELPER
// copy test source file `*.c` to tmp dir
func copyCSourceFile(name string, t *testing.T) (string, string) {
	t.Logf("Copying file %s ...", name)

	absPath, _ := os.Getwd()
	baseDir, projectDir := absPath+"/tmp", absPath+"/../.."
	os.MkdirAll(baseDir, os.ModePerm)

	cpCmd := exec.Command("cp", projectDir+"/src/test/resources/c/"+name, baseDir+"/Main.c")
	cpErr := cpCmd.Run()

	if cpErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(cpErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return baseDir, projectDir
}

// HELPER
// compile C source file
func compileC(name, baseDir, projectDir string, t *testing.T) (string) {
	t.Logf("Compiling file %s ...", name)

	var compilerStderr bytes.Buffer
	compilerCmd := exec.Command(projectDir+"/bin/c_compiler", "-basedir="+baseDir)
	compilerCmd.Stderr = &compilerStderr
	compilerErr := compilerCmd.Run()

	if compilerErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return compilerStderr.String()
}

// HELPER
// run C binary in our container
func runC(baseDir, projectDir string, t *testing.T) (string) {
	t.Log("Running binary /Main ...")

	var containerStdout bytes.Buffer
	containerArgs := []string{"-basedir=" + baseDir, "-input=10:10:23PM", "-expected=22:10:23", "-memory=16"}
	containerCmd := exec.Command(projectDir+"/bin/c_container", containerArgs...)
	containerCmd.Stdout = &containerStdout
	containerErr := containerCmd.Run()

	if containerErr != nil {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr.Error())
		t.FailNow()
	}

	t.Log("Done")
	return containerStdout.String()
}

func Test_C_AC(t *testing.T) {
	name := "ac.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)
	if !strings.Contains(containerErr, "\"status\":0") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr + " => status != 0")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_0(t *testing.T) {
	name := "compiler_bomb_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_1(t *testing.T) {
	name := "compiler_bomb_1.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Compiler_Bomb_2(t *testing.T) {
	name := "compiler_bomb_2.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "signal: killed") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `signal: killed`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Fork_Bomb(t *testing.T) {
	name := "fork_bomb.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "Runtime Error") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Get_Host_By_Name(t *testing.T) {
	name := "get_host_by_name.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	// Main.c:(.text+0x28): warning: Using 'gethostbyname' in statically linked applications
	// requires at runtime the shared libraries from the glibc version used for linking
	if !strings.Contains(containerErr, "\"status\":2") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Include_Leaks(t *testing.T) {
	name := "include_leaks.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "/etc/shadow") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `/etc/shadow`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Infinite_Loop(t *testing.T) {
	name := "infinite_loop.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "Runtime Error") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Memory_Allocation(t *testing.T) {
	name := "memory_allocation.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	// `Killed` is sent to tty by kernel (and record will also be kept in /var/log/message)
	// both stdout and stderr are empty which will lead to status WA
	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Plain_Text(t *testing.T) {
	name := "plain_text.c"
	baseDir, projectDir := copyCSourceFile(name, t)

	compilerStderr := compileC(name, baseDir, projectDir, t)

	if !strings.Contains(compilerStderr, "error") {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr + " => Compile error does not contain string `error`")
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Run_Command_Line_0(t *testing.T) {
	name := "run_command_line_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Run_Command_Line_1(t *testing.T) {
	name := "run_command_line_1.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}

func Test_C_Syscall_0(t *testing.T) {
	name := "syscall_0.c"
	baseDir, projectDir := copyCSourceFile(name, t)
	compilerStderr := compileC(name, baseDir, projectDir, t)

	if len(compilerStderr) > 0 {
		os.RemoveAll(baseDir + "/")
		t.Error(compilerStderr)
		t.FailNow()
	}

	containerErr := runC(baseDir, projectDir, t)

	if !strings.Contains(containerErr, "\"status\":5") {
		os.RemoveAll(baseDir + "/")
		t.Error(containerErr)
		t.FailNow()
	}

	os.RemoveAll(baseDir + "/")
}
<|endoftext|>


<commit_before>package conn

import (
	"fmt"
	"io"
	"net"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
	tec "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-temp-err-catcher"
	ic "github.com/jbenet/go-ipfs/p2p/crypto"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
)

// listener is an object that can accept connections. It implements Listener
type listener struct {
	manet.Listener

	local peer.ID    // LocalPeer is the identity of the local Peer
	privk ic.PrivKey // private key to use to initialize secure conns

	cg ctxgroup.ContextGroup
}

func (l *listener) teardown() error {
	defer log.Debugf("listener closed: %s %s", l.local, l.Multiaddr())
	return l.Listener.Close()
}

func (l *listener) Close() error {
	log.Debugf("listener closing: %s %s", l.local, l.Multiaddr())
	return l.cg.Close()
}

func (l *listener) String() string {
	return fmt.Sprintf("<Listener %s %s>", l.local, l.Multiaddr())
}

// Accept waits for and returns the next connection to the listener.
// Note that unfortunately this
func (l *listener) Accept() (net.Conn, error) {

	// listeners dont have contexts. given changes dont make sense here anymore
	// note that the parent of listener will Close, which will interrupt all io.
	// Contexts and io don't mix.
	ctx := context.Background()

	var catcher tec.TempErrCatcher

	catcher.IsTemp = func(e error) bool {
		// ignore connection breakages up to this point. but log them
		if e == io.EOF {
			log.Debugf("listener ignoring conn with EOF: %s", e)
			return true
		}

		te, ok := e.(tec.Temporary)
		if ok {
			log.Debugf("listener ignoring conn with temporary err: %s", e)
			return te.Temporary()
		}
		return false
	}

	for {
		maconn, err := l.Listener.Accept()
		if err != nil {
			if catcher.IsTemporary(err) {
				continue
			}
			return nil, err
		}

		c, err := newSingleConn(ctx, l.local, "", maconn)
		if err != nil {
			if catcher.IsTemporary(err) {
				continue
			}
			return nil, err
		}

		if l.privk == nil {
			log.Warning("listener %s listening INSECURELY!", l)
			return c, nil
		}
		sc, err := newSecureConn(ctx, l.privk, c)
		if err != nil {
			if catcher.IsTemporary(err) {
				continue
			}
			return nil, err
		}
		return sc, nil
	}
}

func (l *listener) Addr() net.Addr {
	return l.Listener.Addr()
}

// Multiaddr is the identity of the local Peer.
// If there is an error converting from net.Addr to ma.Multiaddr,
// the return value will be nil.
func (l *listener) Multiaddr() ma.Multiaddr {
	maddr, err := manet.FromNetAddr(l.Addr())
	if err != nil {
		return nil // error
	}
	return maddr
}

// LocalPeer is the identity of the local Peer.
func (l *listener) LocalPeer() peer.ID {
	return l.local
}

func (l *listener) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"listener": map[string]interface{}{
			"peer":    l.LocalPeer(),
			"address": l.Multiaddr(),
			"secure":  (l.privk != nil),
		},
	}
}

// Listen listens on the particular multiaddr, with given peer and peerstore.
func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {

	ml, err := manet.Listen(addr)
	if err != nil {
		return nil, fmt.Errorf("Failed to listen on %s: %s", addr, err)
	}

	l := &listener{
		Listener: ml,
		local:    local,
		privk:    sk,
		cg:       ctxgroup.WithContext(ctx),
	}
	l.cg.SetTeardown(l.teardown)

	log.Infof("swarm listening on %s", l.Multiaddr())
	log.Event(ctx, "swarmListen", l)
	return l, nil
}
<commit_msg>p2p/net/conn/Listener: ignore conns failed to secure<commit_after>package conn

import (
	"fmt"
	"io"
	"net"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
	tec "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-temp-err-catcher"
	ic "github.com/jbenet/go-ipfs/p2p/crypto"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
)

// listener is an object that can accept connections. It implements Listener
type listener struct {
	manet.Listener

	local peer.ID    // LocalPeer is the identity of the local Peer
	privk ic.PrivKey // private key to use to initialize secure conns

	cg ctxgroup.ContextGroup
}

func (l *listener) teardown() error {
	defer log.Debugf("listener closed: %s %s", l.local, l.Multiaddr())
	return l.Listener.Close()
}

func (l *listener) Close() error {
	log.Debugf("listener closing: %s %s", l.local, l.Multiaddr())
	return l.cg.Close()
}

func (l *listener) String() string {
	return fmt.Sprintf("<Listener %s %s>", l.local, l.Multiaddr())
}

// Accept waits for and returns the next connection to the listener.
// Note that unfortunately this
func (l *listener) Accept() (net.Conn, error) {

	// listeners dont have contexts. given changes dont make sense here anymore
	// note that the parent of listener will Close, which will interrupt all io.
	// Contexts and io don't mix.
	ctx := context.Background()

	var catcher tec.TempErrCatcher

	catcher.IsTemp = func(e error) bool {
		// ignore connection breakages up to this point. but log them
		if e == io.EOF {
			log.Debugf("listener ignoring conn with EOF: %s", e)
			return true
		}

		te, ok := e.(tec.Temporary)
		if ok {
			log.Debugf("listener ignoring conn with temporary err: %s", e)
			return te.Temporary()
		}
		return false
	}

	for {
		maconn, err := l.Listener.Accept()
		if err != nil {
			if catcher.IsTemporary(err) {
				continue
			}
			return nil, err
		}

		c, err := newSingleConn(ctx, l.local, "", maconn)
		if err != nil {
			if catcher.IsTemporary(err) {
				continue
			}
			return nil, err
		}

		if l.privk == nil {
			log.Warning("listener %s listening INSECURELY!", l)
			return c, nil
		}
		sc, err := newSecureConn(ctx, l.privk, c)
		if err != nil {
			log.Info("ignoring conn we failed to secure: %s %s", err, sc)
			continue
		}
		return sc, nil
	}
}

func (l *listener) Addr() net.Addr {
	return l.Listener.Addr()
}

// Multiaddr is the identity of the local Peer.
// If there is an error converting from net.Addr to ma.Multiaddr,
// the return value will be nil.
func (l *listener) Multiaddr() ma.Multiaddr {
	maddr, err := manet.FromNetAddr(l.Addr())
	if err != nil {
		return nil // error
	}
	return maddr
}

// LocalPeer is the identity of the local Peer.
func (l *listener) LocalPeer() peer.ID {
	return l.local
}

func (l *listener) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"listener": map[string]interface{}{
			"peer":    l.LocalPeer(),
			"address": l.Multiaddr(),
			"secure":  (l.privk != nil),
		},
	}
}

// Listen listens on the particular multiaddr, with given peer and peerstore.
func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {

	ml, err := manet.Listen(addr)
	if err != nil {
		return nil, fmt.Errorf("Failed to listen on %s: %s", addr, err)
	}

	l := &listener{
		Listener: ml,
		local:    local,
		privk:    sk,
		cg:       ctxgroup.WithContext(ctx),
	}
	l.cg.SetTeardown(l.teardown)

	log.Infof("swarm listening on %s", l.Multiaddr())
	log.Event(ctx, "swarmListen", l)
	return l, nil
}
<|endoftext|>


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

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"runtime"

	"github.com/vishvananda/netlink"

	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/containernetworking/cni/pkg/ip"
	"github.com/containernetworking/cni/pkg/ipam"
	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/projectcalico/calico-cni/k8s"
	. "github.com/projectcalico/calico-cni/utils"
	"github.com/projectcalico/libcalico-go/lib/api"
	"github.com/projectcalico/libcalico-go/lib/errors"
	cnet "github.com/projectcalico/libcalico-go/lib/net"
)

var hostname string

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()

	hostname, _ = os.Hostname()
}

func cmdAdd(args *skel.CmdArgs) error {
	// Unmarshall the network config, and perform validation
	conf := NetConf{}
	if err := json.Unmarshal(args.StdinData, &conf); err != nil {
		return fmt.Errorf("failed to load netconf: %v", err)
	}

	ConfigureLogging(conf.LogLevel)

	workload, orchestrator, err := GetIdentifiers(args)
	if err != nil {
		return err
	}

	logger := CreateContextLogger(workload)

	// Allow the hostname to be overridden by the network config
	if conf.Hostname != "" {
		hostname = conf.Hostname
	}

	logger.WithFields(log.Fields{
		"Orchestrator": orchestrator,
		"Node":         hostname,
	}).Info("Extracted identifiers")

	logger.WithFields(log.Fields{"NetConfg": conf}).Info("Loaded CNI NetConf")
	calicoClient, err := CreateClient(conf)
	if err != nil {
		return err
	}

	// Always check if there's an existing endpoint.
	endpoints, err := calicoClient.WorkloadEndpoints().List(api.WorkloadEndpointMetadata{
		Node:         hostname,
		Orchestrator: orchestrator,
		Workload:     workload})
	if err != nil {
		return err
	}

	logger.Debugf("Retrieved endpoints: %v", endpoints)

	var endpoint *api.WorkloadEndpoint
	if len(endpoints.Items) == 1 {
		endpoint = &endpoints.Items[0]
	}

	fmt.Fprintf(os.Stderr, "Calico CNI checking for existing endpoint: %v\n", endpoint)

	// Collect the result in this variable - this is ultimately what gets "returned" by this function by printing
	// it to stdout.
	var result *types.Result

	// If running under Kubernetes then branch off into the kubernetes code, otherwise handle everything in this
	// function.
	if orchestrator == "k8s" {
		if result, err = k8s.CmdAddK8s(args, conf, hostname, calicoClient, endpoint); err != nil {
			return err
		}
	} else {
		// Default CNI behavior - use the CNI network name as the Calico profile.
		profileID := conf.Name

		if endpoint != nil {
			// There is an existing endpoint - no need to create another.
			// This occurs when adding an existing container to a new CNI network
			// Find the IP address from the endpoint and use that in the response.
			// Don't create the veth or do any networking.
			// Just update the profile on the endpoint. The profile will be created if needed during the
			// profile processing step.
			fmt.Fprintf(os.Stderr, "Calico CNI appending profile: %s\n", profileID)
			endpoint.Spec.Profiles = append(endpoint.Spec.Profiles, profileID)
			result, err = CreateResultFromEndpoint(endpoint)
			logger.WithField("result", result).Debug("Created result from endpoint")
			if err != nil {
				return err
			}
		} else {
			// There's no existing endpoint, so we need to do the following:
			// 1) Call the configured IPAM plugin to get IP address(es)
			// 2) Configure the Calico endpoint
			// 3) Create the veth, configuring it on both the host and container namespace.

			// 1) Run the IPAM plugin and make sure there's an IP address returned.
			logger.WithFields(log.Fields{"paths": os.Getenv("CNI_PATH"),
				"type": conf.IPAM.Type}).Debug("Looking for IPAM plugin in paths")
			result, err = ipam.ExecAdd(conf.IPAM.Type, args.StdinData)
			logger.WithField("result", result).Info("Got result from IPAM plugin")
			if err != nil {
				return err
			}

			// Parse endpoint labels passed in by Mesos, and store in a map.
			labels := map[string]string{}
			for _, label := range conf.Args.Mesos.NetworkInfo.Labels.Labels {
				labels[label.Key] = label.Value
			}

			// 2) Create the endpoint object
			endpoint = api.NewWorkloadEndpoint()
			endpoint.Metadata.Name = args.IfName
			endpoint.Metadata.Node = hostname
			endpoint.Metadata.Orchestrator = orchestrator
			endpoint.Metadata.Workload = workload
			endpoint.Metadata.Labels = labels
			endpoint.Spec.Profiles = []string{profileID}

			logger.WithField("endpoint", endpoint).Debug("Populated endpoint (without nets)")
			if err = PopulateEndpointNets(endpoint, result); err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
			logger.WithField("endpoint", endpoint).Info("Populated endpoint (with nets)")

			fmt.Fprintf(os.Stderr, "Calico CNI using IPs: %s\n", endpoint.Spec.IPNetworks)

			// 3) Set up the veth
			hostVethName, contVethMac, err := DoNetworking(args, conf, result, logger, "")
			if err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}

			logger.WithFields(log.Fields{
				"HostVethName":     hostVethName,
				"ContainerVethMac": contVethMac,
			}).Info("Networked namespace")

			mac, err := net.ParseMAC(contVethMac)
			if err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}

			endpoint.Spec.MAC = &cnet.MAC{HardwareAddr: mac}
			endpoint.Spec.InterfaceName = hostVethName
		}

		// Write the endpoint object (either the newly created one, or the updated one with a new ProfileIDs).
		if _, err := calicoClient.WorkloadEndpoints().Apply(endpoint); err != nil {
			// Cleanup IP allocation and return the error.
			ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
			return err
		}

		logger.WithField("endpoint", endpoint).Info("Wrote endpoint to datastore")
	}

	// Handle profile creation - this is only done if there isn't a specific policy handler.
	if conf.Policy.PolicyType == "" {
		logger.Debug("Handling profiles")
		// Start by checking if the profile already exists. If it already exists then there is no work to do.
		// The CNI plugin never updates a profile.
		exists := true
		_, err = calicoClient.Profiles().Get(api.ProfileMetadata{Name: conf.Name})
		if err != nil {
			_, ok := err.(errors.ErrorResourceDoesNotExist)
			if ok {
				exists = false
			} else {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
		}

		if !exists {
			// The profile doesn't exist so needs to be created. The rules vary depending on whether k8s is being used.
			// Under k8s (without full policy support) the rule is permissive and allows all traffic.
			// Otherwise, incoming traffic is only allowed from profiles with the same tag.
			fmt.Fprintf(os.Stderr, "Calico CNI creating profile: %s\n", conf.Name)
			var inboundRules []api.Rule
			if orchestrator == "k8s" {
				inboundRules = []api.Rule{{Action: "allow"}}
			} else {
				inboundRules = []api.Rule{{Action: "allow", Source: api.EntityRule{Tag: conf.Name}}}
			}

			profile := &api.Profile{
				Metadata: api.ProfileMetadata{
					Name: conf.Name,
					Tags: []string{conf.Name},
				},
				Spec: api.ProfileSpec{
					EgressRules: []api.Rule{{Action: "allow"}},
					IngressRules: inboundRules,
				},
			}

			logger.WithField("profile", profile).Info("Creating profile")

			if _, err := calicoClient.Profiles().Create(profile); err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
		}
	}

	return result.Print()
}

func cmdDel(args *skel.CmdArgs) error {
	conf := NetConf{}
	if err := json.Unmarshal(args.StdinData, &conf); err != nil {
		return fmt.Errorf("failed to load netconf: %v", err)
	}

	ConfigureLogging(conf.LogLevel)

	workload, orchestrator, err := GetIdentifiers(args)
	if err != nil {
		return err
	}

	logger := CreateContextLogger(workload)

	// Allow the hostname to be overridden by the network config
	if conf.Hostname != "" {
		hostname = conf.Hostname
	}

	logger.WithFields(log.Fields{
		"Workload":     workload,
		"Orchestrator": orchestrator,
		"Node":         hostname,
	}).Info("Extracted identifiers")

	// Always try to release the address. Don't deal with any errors till the endpoints are cleaned up.
	fmt.Fprintf(os.Stderr, "Calico CNI releasing IP address\n")
	logger.WithFields(log.Fields{"paths": os.Getenv("CNI_PATH"),
		"type": conf.IPAM.Type}).Debug("Looking for IPAM plugin in paths")
	ipamErr := ipam.ExecDel(conf.IPAM.Type, args.StdinData)

	if ipamErr != nil {
		logger.Error(ipamErr)
	}

	calicoClient, err := CreateClient(conf)
	if err != nil {
		return err
	}

	if err := calicoClient.WorkloadEndpoints().Delete(api.WorkloadEndpointMetadata{
		Name:         args.IfName,
		Node:         hostname,
		Orchestrator: orchestrator,
		Workload:     workload}); err != nil {
		return err
	}

	// Only try to delete the device if a namespace was passed in.
	if args.Netns != "" {
		fmt.Fprintf(os.Stderr, "Calico CNI deleting device in netns %s\n", args.Netns)
		err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
			_, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4)
			return err
		})

		if err != nil {
			return err
		}
	}

	// Return the IPAM error if there was one. The IPAM error will be lost if there was also an error in cleaning up
	// the device or endpoint, but crucially, the user will know the overall operation failed.
	return ipamErr
}

// VERSION is filled out during the build process (using git describe output)
var VERSION string

func main() {
	// Display the version on "-v", otherwise just delegate to the skel code.
	// Use a new flag set so as not to conflict with existing libraries which use "flag"
	flagSet := flag.NewFlagSet("Calico", flag.ExitOnError)

	version := flagSet.Bool("v", false, "Display version")
	err := flagSet.Parse(os.Args[1:])
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	if *version {
		fmt.Println(VERSION)
		os.Exit(0)
	}

	if err := AddIgnoreUnknownArgs(); err != nil {
		os.Exit(1)
	}

	skel.PluginMain(cmdAdd, cmdDel)
}
<commit_msg>Fix go formatting<commit_after>// Copyright 2015 Tigera Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"runtime"

	"github.com/vishvananda/netlink"

	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/containernetworking/cni/pkg/ip"
	"github.com/containernetworking/cni/pkg/ipam"
	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/projectcalico/calico-cni/k8s"
	. "github.com/projectcalico/calico-cni/utils"
	"github.com/projectcalico/libcalico-go/lib/api"
	"github.com/projectcalico/libcalico-go/lib/errors"
	cnet "github.com/projectcalico/libcalico-go/lib/net"
)

var hostname string

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()

	hostname, _ = os.Hostname()
}

func cmdAdd(args *skel.CmdArgs) error {
	// Unmarshall the network config, and perform validation
	conf := NetConf{}
	if err := json.Unmarshal(args.StdinData, &conf); err != nil {
		return fmt.Errorf("failed to load netconf: %v", err)
	}

	ConfigureLogging(conf.LogLevel)

	workload, orchestrator, err := GetIdentifiers(args)
	if err != nil {
		return err
	}

	logger := CreateContextLogger(workload)

	// Allow the hostname to be overridden by the network config
	if conf.Hostname != "" {
		hostname = conf.Hostname
	}

	logger.WithFields(log.Fields{
		"Orchestrator": orchestrator,
		"Node":         hostname,
	}).Info("Extracted identifiers")

	logger.WithFields(log.Fields{"NetConfg": conf}).Info("Loaded CNI NetConf")
	calicoClient, err := CreateClient(conf)
	if err != nil {
		return err
	}

	// Always check if there's an existing endpoint.
	endpoints, err := calicoClient.WorkloadEndpoints().List(api.WorkloadEndpointMetadata{
		Node:         hostname,
		Orchestrator: orchestrator,
		Workload:     workload})
	if err != nil {
		return err
	}

	logger.Debugf("Retrieved endpoints: %v", endpoints)

	var endpoint *api.WorkloadEndpoint
	if len(endpoints.Items) == 1 {
		endpoint = &endpoints.Items[0]
	}

	fmt.Fprintf(os.Stderr, "Calico CNI checking for existing endpoint: %v\n", endpoint)

	// Collect the result in this variable - this is ultimately what gets "returned" by this function by printing
	// it to stdout.
	var result *types.Result

	// If running under Kubernetes then branch off into the kubernetes code, otherwise handle everything in this
	// function.
	if orchestrator == "k8s" {
		if result, err = k8s.CmdAddK8s(args, conf, hostname, calicoClient, endpoint); err != nil {
			return err
		}
	} else {
		// Default CNI behavior - use the CNI network name as the Calico profile.
		profileID := conf.Name

		if endpoint != nil {
			// There is an existing endpoint - no need to create another.
			// This occurs when adding an existing container to a new CNI network
			// Find the IP address from the endpoint and use that in the response.
			// Don't create the veth or do any networking.
			// Just update the profile on the endpoint. The profile will be created if needed during the
			// profile processing step.
			fmt.Fprintf(os.Stderr, "Calico CNI appending profile: %s\n", profileID)
			endpoint.Spec.Profiles = append(endpoint.Spec.Profiles, profileID)
			result, err = CreateResultFromEndpoint(endpoint)
			logger.WithField("result", result).Debug("Created result from endpoint")
			if err != nil {
				return err
			}
		} else {
			// There's no existing endpoint, so we need to do the following:
			// 1) Call the configured IPAM plugin to get IP address(es)
			// 2) Configure the Calico endpoint
			// 3) Create the veth, configuring it on both the host and container namespace.

			// 1) Run the IPAM plugin and make sure there's an IP address returned.
			logger.WithFields(log.Fields{"paths": os.Getenv("CNI_PATH"),
				"type": conf.IPAM.Type}).Debug("Looking for IPAM plugin in paths")
			result, err = ipam.ExecAdd(conf.IPAM.Type, args.StdinData)
			logger.WithField("result", result).Info("Got result from IPAM plugin")
			if err != nil {
				return err
			}

			// Parse endpoint labels passed in by Mesos, and store in a map.
			labels := map[string]string{}
			for _, label := range conf.Args.Mesos.NetworkInfo.Labels.Labels {
				labels[label.Key] = label.Value
			}

			// 2) Create the endpoint object
			endpoint = api.NewWorkloadEndpoint()
			endpoint.Metadata.Name = args.IfName
			endpoint.Metadata.Node = hostname
			endpoint.Metadata.Orchestrator = orchestrator
			endpoint.Metadata.Workload = workload
			endpoint.Metadata.Labels = labels
			endpoint.Spec.Profiles = []string{profileID}

			logger.WithField("endpoint", endpoint).Debug("Populated endpoint (without nets)")
			if err = PopulateEndpointNets(endpoint, result); err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
			logger.WithField("endpoint", endpoint).Info("Populated endpoint (with nets)")

			fmt.Fprintf(os.Stderr, "Calico CNI using IPs: %s\n", endpoint.Spec.IPNetworks)

			// 3) Set up the veth
			hostVethName, contVethMac, err := DoNetworking(args, conf, result, logger, "")
			if err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}

			logger.WithFields(log.Fields{
				"HostVethName":     hostVethName,
				"ContainerVethMac": contVethMac,
			}).Info("Networked namespace")

			mac, err := net.ParseMAC(contVethMac)
			if err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}

			endpoint.Spec.MAC = &cnet.MAC{HardwareAddr: mac}
			endpoint.Spec.InterfaceName = hostVethName
		}

		// Write the endpoint object (either the newly created one, or the updated one with a new ProfileIDs).
		if _, err := calicoClient.WorkloadEndpoints().Apply(endpoint); err != nil {
			// Cleanup IP allocation and return the error.
			ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
			return err
		}

		logger.WithField("endpoint", endpoint).Info("Wrote endpoint to datastore")
	}

	// Handle profile creation - this is only done if there isn't a specific policy handler.
	if conf.Policy.PolicyType == "" {
		logger.Debug("Handling profiles")
		// Start by checking if the profile already exists. If it already exists then there is no work to do.
		// The CNI plugin never updates a profile.
		exists := true
		_, err = calicoClient.Profiles().Get(api.ProfileMetadata{Name: conf.Name})
		if err != nil {
			_, ok := err.(errors.ErrorResourceDoesNotExist)
			if ok {
				exists = false
			} else {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
		}

		if !exists {
			// The profile doesn't exist so needs to be created. The rules vary depending on whether k8s is being used.
			// Under k8s (without full policy support) the rule is permissive and allows all traffic.
			// Otherwise, incoming traffic is only allowed from profiles with the same tag.
			fmt.Fprintf(os.Stderr, "Calico CNI creating profile: %s\n", conf.Name)
			var inboundRules []api.Rule
			if orchestrator == "k8s" {
				inboundRules = []api.Rule{{Action: "allow"}}
			} else {
				inboundRules = []api.Rule{{Action: "allow", Source: api.EntityRule{Tag: conf.Name}}}
			}

			profile := &api.Profile{
				Metadata: api.ProfileMetadata{
					Name: conf.Name,
					Tags: []string{conf.Name},
				},
				Spec: api.ProfileSpec{
					EgressRules:  []api.Rule{{Action: "allow"}},
					IngressRules: inboundRules,
				},
			}

			logger.WithField("profile", profile).Info("Creating profile")

			if _, err := calicoClient.Profiles().Create(profile); err != nil {
				// Cleanup IP allocation and return the error.
				ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData)
				return err
			}
		}
	}

	return result.Print()
}

func cmdDel(args *skel.CmdArgs) error {
	conf := NetConf{}
	if err := json.Unmarshal(args.StdinData, &conf); err != nil {
		return fmt.Errorf("failed to load netconf: %v", err)
	}

	ConfigureLogging(conf.LogLevel)

	workload, orchestrator, err := GetIdentifiers(args)
	if err != nil {
		return err
	}

	logger := CreateContextLogger(workload)

	// Allow the hostname to be overridden by the network config
	if conf.Hostname != "" {
		hostname = conf.Hostname
	}

	logger.WithFields(log.Fields{
		"Workload":     workload,
		"Orchestrator": orchestrator,
		"Node":         hostname,
	}).Info("Extracted identifiers")

	// Always try to release the address. Don't deal with any errors till the endpoints are cleaned up.
	fmt.Fprintf(os.Stderr, "Calico CNI releasing IP address\n")
	logger.WithFields(log.Fields{"paths": os.Getenv("CNI_PATH"),
		"type": conf.IPAM.Type}).Debug("Looking for IPAM plugin in paths")
	ipamErr := ipam.ExecDel(conf.IPAM.Type, args.StdinData)

	if ipamErr != nil {
		logger.Error(ipamErr)
	}

	calicoClient, err := CreateClient(conf)
	if err != nil {
		return err
	}

	if err := calicoClient.WorkloadEndpoints().Delete(api.WorkloadEndpointMetadata{
		Name:         args.IfName,
		Node:         hostname,
		Orchestrator: orchestrator,
		Workload:     workload}); err != nil {
		return err
	}

	// Only try to delete the device if a namespace was passed in.
	if args.Netns != "" {
		fmt.Fprintf(os.Stderr, "Calico CNI deleting device in netns %s\n", args.Netns)
		err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
			_, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4)
			return err
		})

		if err != nil {
			return err
		}
	}

	// Return the IPAM error if there was one. The IPAM error will be lost if there was also an error in cleaning up
	// the device or endpoint, but crucially, the user will know the overall operation failed.
	return ipamErr
}

// VERSION is filled out during the build process (using git describe output)
var VERSION string

func main() {
	// Display the version on "-v", otherwise just delegate to the skel code.
	// Use a new flag set so as not to conflict with existing libraries which use "flag"
	flagSet := flag.NewFlagSet("Calico", flag.ExitOnError)

	version := flagSet.Bool("v", false, "Display version")
	err := flagSet.Parse(os.Args[1:])
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	if *version {
		fmt.Println(VERSION)
		os.Exit(0)
	}

	if err := AddIgnoreUnknownArgs(); err != nil {
		os.Exit(1)
	}

	skel.PluginMain(cmdAdd, cmdDel)
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"os"
	"reflect"
	"sort"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/elb"
)

func TestAccAWSELB_basic(t *testing.T) {
	var conf elb.LoadBalancer
	ssl_certificate_id := os.Getenv("AWS_SSL_CERTIFICATE_ID")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "name", "foobar-terraform-test"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.2487133097", "us-west-2a"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.221770259", "us-west-2b"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.2050015877", "us-west-2c"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.instance_port", "8000"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.instance_protocol", "http"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.ssl_certificate_id", ssl_certificate_id),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.lb_port", "80"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.lb_protocol", "http"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "cross_zone_load_balancing", "true"),
				),
			},
		},
	})
}

func TestAccAWSELB_InstanceAttaching(t *testing.T) {
	var conf elb.LoadBalancer

	testCheckInstanceAttached := func(count int) resource.TestCheckFunc {
		return func(*terraform.State) error {
			if len(conf.Instances) != count {
				return fmt.Errorf("instance count does not match")
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
				),
			},

			resource.TestStep{
				Config: testAccAWSELBConfigNewInstance,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testCheckInstanceAttached(1),
				),
			},
		},
	})
}

func TestAccAWSELB_AddSubnet(t *testing.T) {
	var conf elb.LoadBalancer

	testCheckSubnetsAdded := func(count int) resource.TestCheckFunc {
		return func(*terraform.State) error {
			if len(conf.Subnets) != count {
				return fmt.Errorf("subnet count does not match")
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfigVPC,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
				),
			},

			resource.TestStep{
				Config: testAccAWSELBAddSubnets,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testCheckSubnetsAdded(2),
				),
			},
		},
	})
}

func TestAccAWSELB_HealthCheck(t *testing.T) {
	var conf elb.LoadBalancer

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfigHealthCheck,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributesHealthCheck(&conf),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.healthy_threshold", "5"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.unhealthy_threshold", "5"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.target", "HTTP:8000/"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.timeout", "30"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.interval", "60"),
				),
			},
		},
	})
}
func testAccCheckAWSELBDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).elbconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_elb" {
			continue
		}

		describe, err := conn.DescribeLoadBalancers(&elb.DescribeLoadBalancer{
			Names: []string{rs.Primary.ID},
		})

		if err == nil {
			if len(describe.LoadBalancers) != 0 &&
				describe.LoadBalancers[0].LoadBalancerName == rs.Primary.ID {
				return fmt.Errorf("ELB still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(*elb.Error)
		if !ok {
			return err
		}

		if providerErr.Code != "InvalidLoadBalancerName.NotFound" {
			return fmt.Errorf("Unexpected error: %s", err)
		}
	}

	return nil
}

func testAccCheckAWSELBAttributes(conf *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"}
		sort.StringSlice(conf.AvailabilityZones).Sort()
		if !reflect.DeepEqual(conf.AvailabilityZones, zones) {
			return fmt.Errorf("bad availability_zones")
		}

		if conf.LoadBalancerName != "foobar-terraform-test" {
			return fmt.Errorf("bad name")
		}

		l := elb.Listener{
			InstancePort:     8000,
			InstanceProtocol: "HTTP",
			LoadBalancerPort: 80,
			Protocol:         "HTTP",
		}

		if !reflect.DeepEqual(conf.Listeners[0], l) {
			return fmt.Errorf(
				"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
				conf.Listeners[0],
				l)
		}

		if conf.DNSName == "" {
			return fmt.Errorf("empty dns_name")
		}

		return nil
	}
}

func testAccCheckAWSELBAttributesHealthCheck(conf *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"}
		sort.StringSlice(conf.AvailabilityZones).Sort()
		if !reflect.DeepEqual(conf.AvailabilityZones, zones) {
			return fmt.Errorf("bad availability_zones")
		}

		if conf.LoadBalancerName != "foobar-terraform-test" {
			return fmt.Errorf("bad name")
		}

		check := elb.HealthCheck{
			Timeout:            30,
			UnhealthyThreshold: 5,
			HealthyThreshold:   5,
			Interval:           60,
			Target:             "HTTP:8000/",
		}

		if !reflect.DeepEqual(conf.HealthCheck, check) {
			return fmt.Errorf(
				"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
				conf.HealthCheck,
				check)
		}

		if conf.DNSName == "" {
			return fmt.Errorf("empty dns_name")
		}

		return nil
	}
}

func testAccCheckAWSELBExists(n string, res *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ELB ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).elbconn

		describe, err := conn.DescribeLoadBalancers(&elb.DescribeLoadBalancer{
			Names: []string{rs.Primary.ID},
		})

		if err != nil {
			return err
		}

		if len(describe.LoadBalancers) != 1 ||
			describe.LoadBalancers[0].LoadBalancerName != rs.Primary.ID {
			return fmt.Errorf("ELB not found")
		}

		*res = describe.LoadBalancers[0]

		return nil
	}
}

const testAccAWSELBConfig = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  cross_zone_load_balancing = true
}
`

const testAccAWSELBConfigNewInstance = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  instances = ["${aws_instance.foo.id}"]
}

resource "aws_instance" "foo" {
	# us-west-2
	ami = "ami-043a5034"
	instance_type = "t1.micro"
}
`
const testAccAWSELBConfigVPC = `
resource "aws_elb" "bar" {
  vpc_id = "${aws_vpc.foobar.id}"
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  subnets = ["${aws_subnet.baz.id}"]

}

resource "aws_subnet.baz" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.69.0/24"
}

resource "aws_vpc" "foobar" {
  cidr_block = "10.0.0.0/16"
}
`

const testAccAWSELBAddSubnets = `
resource "aws_elb" "bar" {
  vpc_id = "${aws_vpc.foobar.id}"
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  subnets = ["${aws_subnet.baz.id}",
             "${aws_subnet.foo.id}"]
}

resource "aws_subnet.foo" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.68.0/24"
}

resource "aws_subnet.baz" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.69.0/24"
}

resource "aws_vpc" "foobar" {
  cidr_block = "10.0.0.0/16"
}
`

const testAccAWSELBConfigListenerSSLCertificateId = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    ssl_certificate_id = "%s"
    lb_port = 443
    lb_protocol = "https"
  }
}
`

const testAccAWSELBConfigHealthCheck = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  health_check {
    healthy_threshold = 5
    unhealthy_threshold = 5
    target = "HTTP:8000/"
    interval = 60
    timeout = 30
  }
}
`
<commit_msg>epic typo<commit_after>package aws

import (
	"fmt"
	"os"
	"reflect"
	"sort"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/elb"
)

func TestAccAWSELB_basic(t *testing.T) {
	var conf elb.LoadBalancer
	ssl_certificate_id := os.Getenv("AWS_SSL_CERTIFICATE_ID")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "name", "foobar-terraform-test"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.2487133097", "us-west-2a"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.221770259", "us-west-2b"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "availability_zones.2050015877", "us-west-2c"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.instance_port", "8000"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.instance_protocol", "http"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.ssl_certificate_id", ssl_certificate_id),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.lb_port", "80"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "listener.206423021.lb_protocol", "http"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "cross_zone_load_balancing", "true"),
				),
			},
		},
	})
}

func TestAccAWSELB_InstanceAttaching(t *testing.T) {
	var conf elb.LoadBalancer

	testCheckInstanceAttached := func(count int) resource.TestCheckFunc {
		return func(*terraform.State) error {
			if len(conf.Instances) != count {
				return fmt.Errorf("instance count does not match")
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
				),
			},

			resource.TestStep{
				Config: testAccAWSELBConfigNewInstance,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testCheckInstanceAttached(1),
				),
			},
		},
	})
}

func TestAccAWSELB_AddSubnet(t *testing.T) {
	var conf elb.LoadBalancer

	testCheckSubnetsAdded := func(count int) resource.TestCheckFunc {
		return func(*terraform.State) error {
			if len(conf.Subnets) != count {
				return fmt.Errorf("subnet count does not match")
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfigVPC,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributes(&conf),
				),
			},

			resource.TestStep{
				Config: testAccAWSELBAddSubnets,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testCheckSubnetsAdded(2),
				),
			},
		},
	})
}

func TestAccAWSELB_HealthCheck(t *testing.T) {
	var conf elb.LoadBalancer

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSELBDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSELBConfigHealthCheck,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSELBExists("aws_elb.bar", &conf),
					testAccCheckAWSELBAttributesHealthCheck(&conf),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.healthy_threshold", "5"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.unhealthy_threshold", "5"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.target", "HTTP:8000/"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.timeout", "30"),
					resource.TestCheckResourceAttr(
						"aws_elb.bar", "health_check.3484319807.interval", "60"),
				),
			},
		},
	})
}
func testAccCheckAWSELBDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).elbconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_elb" {
			continue
		}

		describe, err := conn.DescribeLoadBalancers(&elb.DescribeLoadBalancer{
			Names: []string{rs.Primary.ID},
		})

		if err == nil {
			if len(describe.LoadBalancers) != 0 &&
				describe.LoadBalancers[0].LoadBalancerName == rs.Primary.ID {
				return fmt.Errorf("ELB still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(*elb.Error)
		if !ok {
			return err
		}

		if providerErr.Code != "InvalidLoadBalancerName.NotFound" {
			return fmt.Errorf("Unexpected error: %s", err)
		}
	}

	return nil
}

func testAccCheckAWSELBAttributes(conf *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"}
		sort.StringSlice(conf.AvailabilityZones).Sort()
		if !reflect.DeepEqual(conf.AvailabilityZones, zones) {
			return fmt.Errorf("bad availability_zones")
		}

		if conf.LoadBalancerName != "foobar-terraform-test" {
			return fmt.Errorf("bad name")
		}

		l := elb.Listener{
			InstancePort:     8000,
			InstanceProtocol: "HTTP",
			LoadBalancerPort: 80,
			Protocol:         "HTTP",
		}

		if !reflect.DeepEqual(conf.Listeners[0], l) {
			return fmt.Errorf(
				"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
				conf.Listeners[0],
				l)
		}

		if conf.DNSName == "" {
			return fmt.Errorf("empty dns_name")
		}

		return nil
	}
}

func testAccCheckAWSELBAttributesHealthCheck(conf *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"}
		sort.StringSlice(conf.AvailabilityZones).Sort()
		if !reflect.DeepEqual(conf.AvailabilityZones, zones) {
			return fmt.Errorf("bad availability_zones")
		}

		if conf.LoadBalancerName != "foobar-terraform-test" {
			return fmt.Errorf("bad name")
		}

		check := elb.HealthCheck{
			Timeout:            30,
			UnhealthyThreshold: 5,
			HealthyThreshold:   5,
			Interval:           60,
			Target:             "HTTP:8000/",
		}

		if !reflect.DeepEqual(conf.HealthCheck, check) {
			return fmt.Errorf(
				"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
				conf.HealthCheck,
				check)
		}

		if conf.DNSName == "" {
			return fmt.Errorf("empty dns_name")
		}

		return nil
	}
}

func testAccCheckAWSELBExists(n string, res *elb.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ELB ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).elbconn

		describe, err := conn.DescribeLoadBalancers(&elb.DescribeLoadBalancer{
			Names: []string{rs.Primary.ID},
		})

		if err != nil {
			return err
		}

		if len(describe.LoadBalancers) != 1 ||
			describe.LoadBalancers[0].LoadBalancerName != rs.Primary.ID {
			return fmt.Errorf("ELB not found")
		}

		*res = describe.LoadBalancers[0]

		return nil
	}
}

const testAccAWSELBConfig = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  cross_zone_load_balancing = true
}
`

const testAccAWSELBConfigNewInstance = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  instances = ["${aws_instance.foo.id}"]
}

resource "aws_instance" "foo" {
	# us-west-2
	ami = "ami-043a5034"
	instance_type = "t1.micro"
}
`
const testAccAWSELBConfigVPC = `
resource "aws_elb" "bar" {
  vpc_id = "${aws_vpc.foobar.id}"
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  subnets = ["${aws_subnet.baz.id}"]

}

resource "aws_subnet" "baz" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.69.0/24"
}

resource "aws_vpc" "foobar" {
  cidr_block = "10.0.0.0/16"
}
`

const testAccAWSELBAddSubnets = `
resource "aws_elb" "bar" {
  vpc_id = "${aws_vpc.foobar.id}"
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  subnets = ["${aws_subnet.baz.id}",
             "${aws_subnet.foo.id}"]
}

resource "aws_subnet" "foo" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.68.0/24"
}

resource "aws_subnet" "baz" {
  vpc_id = "${aws_vpc.foobar.id}"
  cidr_block = "10.0.69.0/24"
}

resource "aws_vpc" "foobar" {
  cidr_block = "10.0.0.0/16"
}
`

const testAccAWSELBConfigListenerSSLCertificateId = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    ssl_certificate_id = "%s"
    lb_port = 443
    lb_protocol = "https"
  }
}
`

const testAccAWSELBConfigHealthCheck = `
resource "aws_elb" "bar" {
  name = "foobar-terraform-test"
  availability_zones = ["us-west-2a"]

  listener {
    instance_port = 8000
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }

  health_check {
    healthy_threshold = 5
    unhealthy_threshold = 5
    target = "HTTP:8000/"
    interval = 60
    timeout = 30
  }
}
`
<|endoftext|>


<commit_before>package vedis

// #include "vedis.h"
import "C"
import "fmt"

func execute(v *Vedis, format string, values ...interface{}) error {
	command := fmt.Sprintf(format, values...)
	if status := C.vedis_exec(v.ptr, C.CString(command), -1); status != C.VEDIS_OK {
		return newError(status, v.ptr)
	}
	return nil
}

func result(v *Vedis) (*C.vedis_value, error) {
	value := new(C.vedis_value)
	if status := C.vedis_exec_result(v.ptr, &value); status != C.VEDIS_OK {
		return nil, newError(status, v.ptr)
	}
	return value, nil
}

func toString(value *C.vedis_value) string {
	length := new(C.int)
	return C.GoString(C.vedis_value_to_string(value, length))
}

func toInt(value *C.vedis_value) int {
	return int(C.vedis_value_to_int(value))
}
<commit_msg>don't allocate unnecessary memory<commit_after>package vedis

// #include "vedis.h"
import "C"
import "fmt"

func execute(v *Vedis, format string, values ...interface{}) error {
	command := fmt.Sprintf(format, values...)
	if status := C.vedis_exec(v.ptr, C.CString(command), -1); status != C.VEDIS_OK {
		return newError(status, v.ptr)
	}
	return nil
}

func result(v *Vedis) (*C.vedis_value, error) {
	var value *C.vedis_value
	if status := C.vedis_exec_result(v.ptr, &value); status != C.VEDIS_OK {
		return nil, newError(status, v.ptr)
	}
	return value, nil
}

func toString(value *C.vedis_value) string {
	var length *C.int
	return C.GoString(C.vedis_value_to_string(value, length))
}

func toInt(value *C.vedis_value) int {
	return int(C.vedis_value_to_int(value))
}
<|endoftext|>


<commit_before>package aws

import (
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

func resourceAwsInstance() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsInstanceCreate,
		Read:   resourceAwsInstanceRead,
		Update: resourceAwsInstanceUpdate,
		Delete: resourceAwsInstanceDelete,

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

			"associate_public_ip_address": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
			},

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

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

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

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

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

			"source_dest_check": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},

			"user_data": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				StateFunc: func(v interface{}) string {
					switch v.(type) {
					case string:
						hash := sha1.Sum([]byte(v.(string)))
						return hex.EncodeToString(hash[:])
					default:
						return ""
					}
				},
			},

			"security_groups": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

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

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

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

			"ebs_optimized": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},

			"iam_instance_profile": &schema.Schema{
				Type:     schema.TypeString,
				ForceNew: true,
				Optional: true,
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Figure out user data
	userData := ""
	if v := d.Get("user_data"); v != nil {
		userData = v.(string)
	}

	associatePublicIPAddress := false
	if v := d.Get("associate_public_ip_address"); v != nil {
		associatePublicIPAddress = v.(bool)
	}

	// Build the creation struct
	runOpts := &ec2.RunInstances{
		ImageId:                  d.Get("ami").(string),
		AvailZone:                d.Get("availability_zone").(string),
		InstanceType:             d.Get("instance_type").(string),
		KeyName:                  d.Get("key_name").(string),
		SubnetId:                 d.Get("subnet_id").(string),
		PrivateIPAddress:         d.Get("private_ip").(string),
		AssociatePublicIpAddress: associatePublicIPAddress,
		UserData:                 []byte(userData),
		EbsOptimized:             d.Get("ebs_optimized").(bool),
		IamInstanceProfile:       d.Get("iam_instance_profile").(string),
	}

	if v := d.Get("security_groups"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)

			var g ec2.SecurityGroup
			if runOpts.SubnetId != "" {
				g.Id = str
			} else {
				g.Name = str
			}

			runOpts.SecurityGroups = append(runOpts.SecurityGroups, g)
		}
	}

	// Create the instance
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return fmt.Errorf("Error launching source instance: %s", err)
	}

	instance := &runResp.Instances[0]
	log.Printf("[INFO] Instance ID: %s", instance.InstanceId)

	// Store the resulting ID so we can look this up later
	d.SetId(instance.InstanceId)

	// Wait for the instance to become running so we can get some attributes
	// that aren't available until later.
	log.Printf(
		"[DEBUG] Waiting for instance (%s) to become running",
		instance.InstanceId)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending"},
		Target:     "running",
		Refresh:    InstanceStateRefreshFunc(ec2conn, instance.InstanceId),
		Timeout:    10 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	instanceRaw, err := stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to become ready: %s",
			instance.InstanceId, err)
	}

	instance = instanceRaw.(*ec2.Instance)

	// Initialize the connection info
	d.SetConnInfo(map[string]string{
		"type": "ssh",
		"host": instance.PublicIpAddress,
	})

	// Set our attributes
	if err := resourceAwsInstanceRead(d, meta); err != nil {
		return err
	}

	// Update if we need to
	return resourceAwsInstanceUpdate(d, meta)
}

func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	modify := false
	opts := new(ec2.ModifyInstance)

	if v, ok := d.GetOk("source_dest_check"); ok {
		opts.SourceDestCheck = v.(bool)
		opts.SetSourceDestCheck = true
		modify = true
	}

	if modify {
		log.Printf("[INFO] Modifing instance %s: %#v", d.Id(), opts)
		if _, err := ec2conn.ModifyInstance(d.Id(), opts); err != nil {
			return err
		}

		// TODO(mitchellh): wait for the attributes we modified to
		// persist the change...
	}

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

	return nil
}

func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	log.Printf("[INFO] Terminating instance: %s", d.Id())
	if _, err := ec2conn.TerminateInstances([]string{d.Id()}); err != nil {
		return fmt.Errorf("Error terminating instance: %s", err)
	}

	log.Printf(
		"[DEBUG] Waiting for instance (%s) to become terminated",
		d.Id())

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending", "running", "shutting-down", "stopped", "stopping"},
		Target:     "terminated",
		Refresh:    InstanceStateRefreshFunc(ec2conn, d.Id()),
		Timeout:    10 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err := stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to terminate: %s",
			d.Id(), err)
	}

	d.SetId("")
	return nil
}

func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	resp, err := ec2conn.Instances([]string{d.Id()}, ec2.NewFilter())
	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.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
			d.SetId("")
			return nil
		}

		// Some other error, report it
		return err
	}

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

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

	// If the instance is terminated, then it is gone
	if instance.State.Name == "terminated" {
		d.SetId("")
		return nil
	}

	d.Set("availability_zone", instance.AvailZone)
	d.Set("key_name", instance.KeyName)
	d.Set("public_dns", instance.DNSName)
	d.Set("public_ip", instance.PublicIpAddress)
	d.Set("private_dns", instance.PrivateDNSName)
	d.Set("private_ip", instance.PrivateIpAddress)
	d.Set("subnet_id", instance.SubnetId)
	d.Set("ebs_optimized", instance.EbsOptimized)
	d.Set("tags", tagsToMap(instance.Tags))

	// Determine whether we're referring to security groups with
	// IDs or names. We use a heuristic to figure this out. By default,
	// we use IDs if we're in a VPC. However, if we previously had an
	// all-name list of security groups, we use names. Or, if we had any
	// IDs, we use IDs.
	useID := instance.SubnetId != ""
	if v := d.Get("security_groups"); v != nil {
		match := false
		for _, v := range v.(*schema.Set).List() {
			if strings.HasPrefix(v.(string), "sg-") {
				match = true
				break
			}
		}

		useID = match
	}

	// Build up the security groups
	sgs := make([]string, len(instance.SecurityGroups))
	for i, sg := range instance.SecurityGroups {
		if useID {
			sgs[i] = sg.Id
		} else {
			sgs[i] = sg.Name
		}
	}
	d.Set("security_groups", sgs)

	return nil
}

// InstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// an EC2 instance.
func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.Instances([]string{instanceID}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on InstanceStateRefresh: %s", err)
				return nil, "", err
			}
		}

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

		i := &resp.Reservations[0].Instances[0]
		return i, i.State.Name, nil
	}
}
<commit_msg>added block_device attribute<commit_after>package aws

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

func resourceAwsInstance() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsInstanceCreate,
		Read:   resourceAwsInstanceRead,
		Update: resourceAwsInstanceUpdate,
		Delete: resourceAwsInstanceDelete,

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

			"associate_public_ip_address": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
			},

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

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

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

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

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

			"source_dest_check": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},

			"user_data": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				StateFunc: func(v interface{}) string {
					switch v.(type) {
					case string:
						hash := sha1.Sum([]byte(v.(string)))
						return hex.EncodeToString(hash[:])
					default:
						return ""
					}
				},
			},

			"security_groups": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

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

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

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

			"ebs_optimized": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},

			"iam_instance_profile": &schema.Schema{
				Type:     schema.TypeString,
				ForceNew: true,
				Optional: true,
			},
			"tags": tagsSchema(),

			"block_device": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"device_name": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
							ForceNew: true,
						},

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

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

						"volume_size": &schema.Schema{
							Type:     schema.TypeInt,
							Optional: true,
							ForceNew: true,
						},

						"delete_on_termination": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							Default:  true,
							ForceNew: true,
						},

						"encrypted": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							ForceNew: true,
						},
					},
				},
				Set: resourceAwsInstanceBlockDevicesHash,
			},
		},
	}
}

func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Figure out user data
	userData := ""
	if v := d.Get("user_data"); v != nil {
		userData = v.(string)
	}

	associatePublicIPAddress := false
	if v := d.Get("associate_public_ip_address"); v != nil {
		associatePublicIPAddress = v.(bool)
	}

	// Build the creation struct
	runOpts := &ec2.RunInstances{
		ImageId:                  d.Get("ami").(string),
		AvailZone:                d.Get("availability_zone").(string),
		InstanceType:             d.Get("instance_type").(string),
		KeyName:                  d.Get("key_name").(string),
		SubnetId:                 d.Get("subnet_id").(string),
		PrivateIPAddress:         d.Get("private_ip").(string),
		AssociatePublicIpAddress: associatePublicIPAddress,
		UserData:                 []byte(userData),
		EbsOptimized:             d.Get("ebs_optimized").(bool),
		IamInstanceProfile:       d.Get("iam_instance_profile").(string),
	}

	if v := d.Get("security_groups"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)

			var g ec2.SecurityGroup
			if runOpts.SubnetId != "" {
				g.Id = str
			} else {
				g.Name = str
			}

			runOpts.SecurityGroups = append(runOpts.SecurityGroups, g)
		}
	}

	if v := d.Get("block_device"); v != nil {
		vs := v.(*schema.Set).List()
		if len(vs) > 0 {
			runOpts.BlockDevices = make([]ec2.BlockDeviceMapping, len(vs))
			for i, v := range vs {
				bd := v.(map[string]interface{})
				runOpts.BlockDevices[i].DeviceName = bd["device_name"].(string)
				runOpts.BlockDevices[i].SnapshotId = bd["snapshot_id"].(string)
				runOpts.BlockDevices[i].VolumeType = bd["volume_type"].(string)
				runOpts.BlockDevices[i].VolumeSize = int64(bd["volume_size"].(int))
				runOpts.BlockDevices[i].DeleteOnTermination = bd["delete_on_termination"].(bool)
				runOpts.BlockDevices[i].Encrypted = bd["encrypted"].(bool)
			}
		}
	}

	// Create the instance
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return fmt.Errorf("Error launching source instance: %s", err)
	}

	instance := &runResp.Instances[0]
	log.Printf("[INFO] Instance ID: %s", instance.InstanceId)

	// Store the resulting ID so we can look this up later
	d.SetId(instance.InstanceId)

	// Wait for the instance to become running so we can get some attributes
	// that aren't available until later.
	log.Printf(
		"[DEBUG] Waiting for instance (%s) to become running",
		instance.InstanceId)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending"},
		Target:     "running",
		Refresh:    InstanceStateRefreshFunc(ec2conn, instance.InstanceId),
		Timeout:    10 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	instanceRaw, err := stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to become ready: %s",
			instance.InstanceId, err)
	}

	instance = instanceRaw.(*ec2.Instance)

	// Initialize the connection info
	d.SetConnInfo(map[string]string{
		"type": "ssh",
		"host": instance.PublicIpAddress,
	})

	// Set our attributes
	if err := resourceAwsInstanceRead(d, meta); err != nil {
		return err
	}

	// Update if we need to
	return resourceAwsInstanceUpdate(d, meta)
}

func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	modify := false
	opts := new(ec2.ModifyInstance)

	if v, ok := d.GetOk("source_dest_check"); ok {
		opts.SourceDestCheck = v.(bool)
		opts.SetSourceDestCheck = true
		modify = true
	}

	if modify {
		log.Printf("[INFO] Modifing instance %s: %#v", d.Id(), opts)
		if _, err := ec2conn.ModifyInstance(d.Id(), opts); err != nil {
			return err
		}

		// TODO(mitchellh): wait for the attributes we modified to
		// persist the change...
	}

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

	return nil
}

func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	log.Printf("[INFO] Terminating instance: %s", d.Id())
	if _, err := ec2conn.TerminateInstances([]string{d.Id()}); err != nil {
		return fmt.Errorf("Error terminating instance: %s", err)
	}

	log.Printf(
		"[DEBUG] Waiting for instance (%s) to become terminated",
		d.Id())

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending", "running", "shutting-down", "stopped", "stopping"},
		Target:     "terminated",
		Refresh:    InstanceStateRefreshFunc(ec2conn, d.Id()),
		Timeout:    10 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err := stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to terminate: %s",
			d.Id(), err)
	}

	d.SetId("")
	return nil
}

func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	resp, err := ec2conn.Instances([]string{d.Id()}, ec2.NewFilter())
	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.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
			d.SetId("")
			return nil
		}

		// Some other error, report it
		return err
	}

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

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

	// If the instance is terminated, then it is gone
	if instance.State.Name == "terminated" {
		d.SetId("")
		return nil
	}

	d.Set("availability_zone", instance.AvailZone)
	d.Set("key_name", instance.KeyName)
	d.Set("public_dns", instance.DNSName)
	d.Set("public_ip", instance.PublicIpAddress)
	d.Set("private_dns", instance.PrivateDNSName)
	d.Set("private_ip", instance.PrivateIpAddress)
	d.Set("subnet_id", instance.SubnetId)
	d.Set("ebs_optimized", instance.EbsOptimized)
	d.Set("tags", tagsToMap(instance.Tags))

	// Determine whether we're referring to security groups with
	// IDs or names. We use a heuristic to figure this out. By default,
	// we use IDs if we're in a VPC. However, if we previously had an
	// all-name list of security groups, we use names. Or, if we had any
	// IDs, we use IDs.
	useID := instance.SubnetId != ""
	if v := d.Get("security_groups"); v != nil {
		match := false
		for _, v := range v.(*schema.Set).List() {
			if strings.HasPrefix(v.(string), "sg-") {
				match = true
				break
			}
		}

		useID = match
	}

	// Build up the security groups
	sgs := make([]string, len(instance.SecurityGroups))
	for i, sg := range instance.SecurityGroups {
		if useID {
			sgs[i] = sg.Id
		} else {
			sgs[i] = sg.Name
		}
	}
	d.Set("security_groups", sgs)

	volIDs := make([]string, len(instance.BlockDevices))
	bdByVolID := make(map[string]ec2.BlockDevice)
	for i, bd := range instance.BlockDevices {
		volIDs[i] = bd.VolumeId
		bdByVolID[bd.VolumeId] = bd
	}

	volResp, err := ec2conn.Volumes(volIDs, ec2.NewFilter())
	if err != nil {
		return err
	}

	bds := make([]map[string]interface{}, len(instance.BlockDevices))
	for i, vol := range volResp.Volumes {
		bds[i] = make(map[string]interface{})
		bds[i]["device_name"] = bdByVolID[vol.VolumeId].DeviceName
		bds[i]["snapshot_id"] = vol.SnapshotId
		bds[i]["volume_type"] = vol.VolumeType
		bds[i]["volume_size"] = vol.Size
		bds[i]["delete_on_termination"] = bdByVolID[vol.VolumeId].DeleteOnTermination
		bds[i]["encrypted"] = vol.Encrypted
	}
	d.Set("block_device", bds)

	return nil
}

// InstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// an EC2 instance.
func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.Instances([]string{instanceID}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on InstanceStateRefresh: %s", err)
				return nil, "", err
			}
		}

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

		i := &resp.Reservations[0].Instances[0]
		return i, i.State.Name, nil
	}
}

func resourceAwsInstanceBlockDevicesHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	buf.WriteString(fmt.Sprintf("%s-", m["device_name"].(string)))
	buf.WriteString(fmt.Sprintf("%s-", m["snapshot_id"].(string)))
	buf.WriteString(fmt.Sprintf("%s-", m["volume_type"].(string)))
	buf.WriteString(fmt.Sprintf("%d-", m["volume_size"].(int)))
	buf.WriteString(fmt.Sprintf("%t-", m["delete_on_termination"].(bool)))
	buf.WriteString(fmt.Sprintf("%t-", m["encrypted"].(bool)))
	return hashcode.String(buf.String())
}
<|endoftext|>


<commit_before>package canary

import (
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/canaryio/canary/pkg/manifest"
	"github.com/canaryio/canary/pkg/sensor"
)

type Canary struct {
	Config     Config
	Manifest   manifest.Manifest
	Publishers []Publisher
	Sensors    []sensor.Sensor
	OutputChan chan sensor.Measurement
	ReloadChan chan manifest.Manifest
}

// New returns a pointer to a new Publsher.
func New(publishers []Publisher) *Canary {
	return &Canary{
		Publishers: publishers,
		OutputChan: make(chan sensor.Measurement),
	}
}

func (c *Canary) publishMeasurements() {
	// publish each incoming measurement
	for m := range c.OutputChan {
		for _, p := range c.Publishers {
			p.Publish(m)
		}
	}
}

func (c *Canary) SignalHandler() {
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT)
	signal.Notify(signalChan, syscall.SIGHUP)
	for s := range signalChan {
		switch s {
		case syscall.SIGINT:
			for _, sensor := range c.Sensors {
				sensor.Stop()
			}
			os.Exit(0)
		case syscall.SIGHUP:
			manifest, err := manifest.Get(c.Config.ManifestURL, c.Config.DefaultSampleInterval)
			if err != nil {
				log.Fatal(err)
			}
			// Split reload logic into reloader() as to allow other things to trigger a manifest reload
			c.ReloadChan <- manifest
		}
	}
}

func (c *Canary) reloader() {
	if c.ReloadChan == nil {
		c.ReloadChan = make(chan manifest.Manifest)
	}

	for m := range c.ReloadChan {
		stoppingSensors := []sensor.Sensor{}
		for _, sensor := range c.Sensors {
			found := false
			for _, newTarget := range m.Targets {
				if newTarget.Hash == sensor.Target.Hash {
					found = true
				}
			}
			if !found {
				sensor.Stop()
				stoppingSensors = append(stoppingSensors, sensor)
			}

		}
		for _, sensor := range stoppingSensors {
			<-sensor.StopNotifyChan
		}

		c.Manifest = m
		if c.Config.RampupSensors {
			c.Manifest.GenerateRampupDelays(c.Config.DefaultSampleInterval)
		}
		// Start new sensors:
		c.startSensors()
	}
}

func (c *Canary) startSensors() {
	oldSensors := c.Sensors
	c.Sensors = []sensor.Sensor{} // reset the slice

	// spinup a sensor for each target
	for index, target := range c.Manifest.Targets {
		found := false
		for _, oldSensor := range oldSensors {
			if oldSensor.Target.Hash == target.Hash {
				found = true
			}
		}
		if found {
			for _, oldSensor := range oldSensors {
				if oldSensor.Target.Hash == target.Hash {
					c.Sensors = append(c.Sensors, oldSensor)
				}
			}
		} else {
			timeout := target.Interval
			if timeout > c.Config.MaxSampleTimeout {
				timeout = c.Config.MaxSampleTimeout
			}

			sensor := sensor.Sensor{
				Target:         target,
				C:              c.OutputChan,
				StopChan:       make(chan int, 1),
				IsStopped:      false,
				StopNotifyChan: make(chan bool),
				IsOK:           false,
				Timeout:        timeout,
			}
			c.Sensors = append(c.Sensors, sensor)

			go sensor.Start(c.Manifest.StartDelays[index])
		}
	}
}

func (c *Canary) StartAutoReload(interval time.Duration) {
	t := time.NewTicker(interval)
	for {
		<-t.C
		manifest, err := manifest.Get(c.Config.ManifestURL, c.Config.DefaultSampleInterval)
		if err != nil {
			log.Fatal(err)
		}
		if manifest.Hash != c.Manifest.Hash {
			c.ReloadChan <- manifest
		}
	}
}

func (c *Canary) Run() {
	// create and start sensors
	c.startSensors()
	// start a go routine for watching config reloads
	go c.reloader()
	// start a go routine for measurement publishing.
	go c.publishMeasurements()
}
<commit_msg>Don't use MaxSampleTimeout if not provided<commit_after>package canary

import (
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/canaryio/canary/pkg/manifest"
	"github.com/canaryio/canary/pkg/sensor"
)

type Canary struct {
	Config     Config
	Manifest   manifest.Manifest
	Publishers []Publisher
	Sensors    []sensor.Sensor
	OutputChan chan sensor.Measurement
	ReloadChan chan manifest.Manifest
}

// New returns a pointer to a new Publsher.
func New(publishers []Publisher) *Canary {
	return &Canary{
		Publishers: publishers,
		OutputChan: make(chan sensor.Measurement),
	}
}

func (c *Canary) publishMeasurements() {
	// publish each incoming measurement
	for m := range c.OutputChan {
		for _, p := range c.Publishers {
			p.Publish(m)
		}
	}
}

func (c *Canary) SignalHandler() {
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT)
	signal.Notify(signalChan, syscall.SIGHUP)
	for s := range signalChan {
		switch s {
		case syscall.SIGINT:
			for _, sensor := range c.Sensors {
				sensor.Stop()
			}
			os.Exit(0)
		case syscall.SIGHUP:
			manifest, err := manifest.Get(c.Config.ManifestURL, c.Config.DefaultSampleInterval)
			if err != nil {
				log.Fatal(err)
			}
			// Split reload logic into reloader() as to allow other things to trigger a manifest reload
			c.ReloadChan <- manifest
		}
	}
}

func (c *Canary) reloader() {
	if c.ReloadChan == nil {
		c.ReloadChan = make(chan manifest.Manifest)
	}

	for m := range c.ReloadChan {
		stoppingSensors := []sensor.Sensor{}
		for _, sensor := range c.Sensors {
			found := false
			for _, newTarget := range m.Targets {
				if newTarget.Hash == sensor.Target.Hash {
					found = true
				}
			}
			if !found {
				sensor.Stop()
				stoppingSensors = append(stoppingSensors, sensor)
			}

		}
		for _, sensor := range stoppingSensors {
			<-sensor.StopNotifyChan
		}

		c.Manifest = m
		if c.Config.RampupSensors {
			c.Manifest.GenerateRampupDelays(c.Config.DefaultSampleInterval)
		}
		// Start new sensors:
		c.startSensors()
	}
}

func (c *Canary) startSensors() {
	oldSensors := c.Sensors
	c.Sensors = []sensor.Sensor{} // reset the slice

	// spinup a sensor for each target
	for index, target := range c.Manifest.Targets {
		found := false
		for _, oldSensor := range oldSensors {
			if oldSensor.Target.Hash == target.Hash {
				found = true
			}
		}
		if found {
			for _, oldSensor := range oldSensors {
				if oldSensor.Target.Hash == target.Hash {
					c.Sensors = append(c.Sensors, oldSensor)
				}
			}
		} else {
			timeout := target.Interval
			if c.Config.MaxSampleTimeout > 0 && timeout > c.Config.MaxSampleTimeout {
				timeout = c.Config.MaxSampleTimeout
			}

			sensor := sensor.Sensor{
				Target:         target,
				C:              c.OutputChan,
				StopChan:       make(chan int, 1),
				IsStopped:      false,
				StopNotifyChan: make(chan bool),
				IsOK:           false,
				Timeout:        timeout,
			}
			c.Sensors = append(c.Sensors, sensor)

			go sensor.Start(c.Manifest.StartDelays[index])
		}
	}
}

func (c *Canary) StartAutoReload(interval time.Duration) {
	t := time.NewTicker(interval)
	for {
		<-t.C
		manifest, err := manifest.Get(c.Config.ManifestURL, c.Config.DefaultSampleInterval)
		if err != nil {
			log.Fatal(err)
		}
		if manifest.Hash != c.Manifest.Hash {
			c.ReloadChan <- manifest
		}
	}
}

func (c *Canary) Run() {
	// create and start sensors
	c.startSensors()
	// start a go routine for watching config reloads
	go c.reloader()
	// start a go routine for measurement publishing.
	go c.publishMeasurements()
}
<|endoftext|>