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

package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log/syslog"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"

	"github.com/tsuru/config"
	"github.com/tsuru/gandalf/db"
	"github.com/tsuru/gandalf/repository"
	"github.com/tsuru/gandalf/user"
	"gopkg.in/mgo.v2/bson"
)

var log *syslog.Writer

func hasWritePermission(u *user.User, r *repository.Repository) (allowed bool) {
	for _, userName := range r.Users {
		if u.Name == userName {
			return true
		}
	}
	return false
}

func hasReadPermission(u *user.User, r *repository.Repository) (allowed bool) {
	if r.IsPublic {
		return true
	}
	for _, userName := range r.Users {
		if u.Name == userName {
			return true
		}
	}
	for _, userName := range r.ReadOnlyUsers {
		if u.Name == userName {
			return true
		}
	}
	return false
}

// Returns the command being executed by ssh.
// When a user runs `$ git push` from his/her machine, the server
// receives a ssh command, identified by this user (by the ssh key).
// The command and it's parameters are available through the SSH_ORIGINAL_COMMAND
// environment variable. In the git push example, it would have the following value:
// SSH_ORIGINAL_COMMAND=git-receive-pack 'foo.git'
// This function is responsible for retrieving the `git-receive-pack` part of SSH_ORIGINAL_COMMAND
func action() string {
	return strings.Split(os.Getenv("SSH_ORIGINAL_COMMAND"), " ")[0]
}

// Get the repository name requested in SSH_ORIGINAL_COMMAND and retrieves
// the related document on the database and returns it.
// This function does two distinct things, parses the SSH_ORIGINAL_COMMAND and
// returns a "validation" error if it doesn't matches the expected format
// and gets the repository from the database based on the info
// obtained by the SSH_ORIGINAL_COMMAND parse.
func requestedRepository() (repository.Repository, error) {
	_, repoName, err := parseGitCommand()
	if err != nil {
		return repository.Repository{}, err
	}
	var repo repository.Repository
	conn, err := db.Conn()
	if err != nil {
		return repository.Repository{}, err
	}
	defer conn.Close()
	if err := conn.Repository().Find(bson.M{"_id": repoName}).One(&repo); err != nil {
		return repository.Repository{}, errors.New("Repository not found")
	}
	return repo, nil
}

// Checks whether a command is a valid git command
// The following format is allowed:
// (git-[a-z-]+) '/?([\w-+@][\w-+.@]*/)?([\w-]+)\.git'
func parseGitCommand() (command, name string, err error) {
	// The following regex validates the git command, which is in the form:
	//    <git-command> [<namespace>/]<name>
	// with namespace being optional. If a namespace is used, we validate it
	// according to the following:
	//  - a namespace is optional
	//  - a namespace contains only alphanumerics, underlines, @´s, -´s, +´s
	//    and periods but it does not start with a period (.)
	//  - one and exactly one slash (/) separates namespace and the actual name
	r, err := regexp.Compile(`(git-[a-z-]+) '/?([\w-+@][\w-+.@]*/)?([\w-]+)\.git'`)
	if err != nil {
		panic(err)
	}
	m := r.FindStringSubmatch(os.Getenv("SSH_ORIGINAL_COMMAND"))
	if len(m) != 4 {
		return "", "", errors.New("You've tried to execute some weird command, I'm deliberately denying you to do that, get over it.")
	}
	return m[1], m[2] + m[3], nil
}

// Executes the SSH_ORIGINAL_COMMAND based on the condition
// defined by the `f` parameter.
// Also receives a custom error message to print to the end user and a
// stdout object, where the SSH_ORIGINAL_COMMAND output is going to be written
func executeAction(f func(*user.User, *repository.Repository) bool, errMsg string, stdout io.Writer) {
	var u user.User
	conn, err := db.Conn()
	if err != nil {
		return
	}
	defer conn.Close()
	if err := conn.User().Find(bson.M{"_id": os.Args[1]}).One(&u); err != nil {
		log.Err("Error obtaining user. Gandalf database is probably in an inconsistent state.")
		fmt.Fprintln(os.Stderr, "Error obtaining user. Gandalf database is probably in an inconsistent state.")
		return
	}
	repo, err := requestedRepository()
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	if f(&u, &repo) {
		// split into a function (maybe executeCmd)
		c, err := formatCommand()
		if err != nil {
			log.Err(err.Error())
			fmt.Fprintln(os.Stderr, err.Error())
		}
		log.Info("Executing " + strings.Join(c, " "))
		cmd := exec.Command(c[0], c[1:]...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = stdout
		baseEnv := os.Environ()
		baseEnv = append(baseEnv, "TSURU_USER="+u.Name)
		cmd.Env = baseEnv
		stderr := &bytes.Buffer{}
		cmd.Stderr = stderr
		err = cmd.Run()
		if err != nil {
			log.Err("Got error while executing original command: " + err.Error())
			log.Err(stderr.String())
			fmt.Fprintln(os.Stderr, "Got error while executing original command: "+err.Error())
			fmt.Fprintln(os.Stderr, stderr.String())
		}
		return
	}
	log.Err("Permission denied.")
	log.Err(errMsg)
	fmt.Fprintln(os.Stderr, "Permission denied.")
	fmt.Fprintln(os.Stderr, errMsg)
}

func formatCommand() ([]string, error) {
	p, err := config.GetString("git:bare:location")
	if err != nil {
		log.Err(err.Error())
		return []string{}, err
	}
	_, repoName, err := parseGitCommand()
	if err != nil {
		log.Err(err.Error())
		return []string{}, err
	}
	repoName += ".git"
	cmdList := strings.Split(os.Getenv("SSH_ORIGINAL_COMMAND"), " ")
	if len(cmdList) != 2 {
		log.Err("Malformed git command")
		return []string{}, fmt.Errorf("Malformed git command")
	}
	cmdList[1] = path.Join(p, repoName)
	return cmdList, nil
}

func main() {
	var err error
	log, err = syslog.New(syslog.LOG_INFO, "gandalf-listener")
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		panic(err.Error())
	}
	err = config.ReadConfigFile("/etc/gandalf.conf")
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	_, _, err = parseGitCommand()
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	a := action()
	if a == "git-receive-pack" {
		executeAction(hasWritePermission, "You don't have access to write in this repository.", os.Stdout)
		return
	}
	if a == "git-upload-pack" {
		executeAction(hasReadPermission, "You don't have access to read this repository.", os.Stdout)
		return
	}
}
<commit_msg>bin: update year in copyright header<commit_after>// Copyright 2015 gandalf authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log/syslog"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"

	"github.com/tsuru/config"
	"github.com/tsuru/gandalf/db"
	"github.com/tsuru/gandalf/repository"
	"github.com/tsuru/gandalf/user"
	"gopkg.in/mgo.v2/bson"
)

var log *syslog.Writer

func hasWritePermission(u *user.User, r *repository.Repository) (allowed bool) {
	for _, userName := range r.Users {
		if u.Name == userName {
			return true
		}
	}
	return false
}

func hasReadPermission(u *user.User, r *repository.Repository) (allowed bool) {
	if r.IsPublic {
		return true
	}
	for _, userName := range r.Users {
		if u.Name == userName {
			return true
		}
	}
	for _, userName := range r.ReadOnlyUsers {
		if u.Name == userName {
			return true
		}
	}
	return false
}

// Returns the command being executed by ssh.
// When a user runs `$ git push` from his/her machine, the server
// receives a ssh command, identified by this user (by the ssh key).
// The command and it's parameters are available through the SSH_ORIGINAL_COMMAND
// environment variable. In the git push example, it would have the following value:
// SSH_ORIGINAL_COMMAND=git-receive-pack 'foo.git'
// This function is responsible for retrieving the `git-receive-pack` part of SSH_ORIGINAL_COMMAND
func action() string {
	return strings.Split(os.Getenv("SSH_ORIGINAL_COMMAND"), " ")[0]
}

// Get the repository name requested in SSH_ORIGINAL_COMMAND and retrieves
// the related document on the database and returns it.
// This function does two distinct things, parses the SSH_ORIGINAL_COMMAND and
// returns a "validation" error if it doesn't matches the expected format
// and gets the repository from the database based on the info
// obtained by the SSH_ORIGINAL_COMMAND parse.
func requestedRepository() (repository.Repository, error) {
	_, repoName, err := parseGitCommand()
	if err != nil {
		return repository.Repository{}, err
	}
	var repo repository.Repository
	conn, err := db.Conn()
	if err != nil {
		return repository.Repository{}, err
	}
	defer conn.Close()
	if err := conn.Repository().Find(bson.M{"_id": repoName}).One(&repo); err != nil {
		return repository.Repository{}, errors.New("Repository not found")
	}
	return repo, nil
}

// Checks whether a command is a valid git command
// The following format is allowed:
// (git-[a-z-]+) '/?([\w-+@][\w-+.@]*/)?([\w-]+)\.git'
func parseGitCommand() (command, name string, err error) {
	// The following regex validates the git command, which is in the form:
	//    <git-command> [<namespace>/]<name>
	// with namespace being optional. If a namespace is used, we validate it
	// according to the following:
	//  - a namespace is optional
	//  - a namespace contains only alphanumerics, underlines, @´s, -´s, +´s
	//    and periods but it does not start with a period (.)
	//  - one and exactly one slash (/) separates namespace and the actual name
	r, err := regexp.Compile(`(git-[a-z-]+) '/?([\w-+@][\w-+.@]*/)?([\w-]+)\.git'`)
	if err != nil {
		panic(err)
	}
	m := r.FindStringSubmatch(os.Getenv("SSH_ORIGINAL_COMMAND"))
	if len(m) != 4 {
		return "", "", errors.New("You've tried to execute some weird command, I'm deliberately denying you to do that, get over it.")
	}
	return m[1], m[2] + m[3], nil
}

// Executes the SSH_ORIGINAL_COMMAND based on the condition
// defined by the `f` parameter.
// Also receives a custom error message to print to the end user and a
// stdout object, where the SSH_ORIGINAL_COMMAND output is going to be written
func executeAction(f func(*user.User, *repository.Repository) bool, errMsg string, stdout io.Writer) {
	var u user.User
	conn, err := db.Conn()
	if err != nil {
		return
	}
	defer conn.Close()
	if err := conn.User().Find(bson.M{"_id": os.Args[1]}).One(&u); err != nil {
		log.Err("Error obtaining user. Gandalf database is probably in an inconsistent state.")
		fmt.Fprintln(os.Stderr, "Error obtaining user. Gandalf database is probably in an inconsistent state.")
		return
	}
	repo, err := requestedRepository()
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	if f(&u, &repo) {
		// split into a function (maybe executeCmd)
		c, err := formatCommand()
		if err != nil {
			log.Err(err.Error())
			fmt.Fprintln(os.Stderr, err.Error())
		}
		log.Info("Executing " + strings.Join(c, " "))
		cmd := exec.Command(c[0], c[1:]...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = stdout
		baseEnv := os.Environ()
		baseEnv = append(baseEnv, "TSURU_USER="+u.Name)
		cmd.Env = baseEnv
		stderr := &bytes.Buffer{}
		cmd.Stderr = stderr
		err = cmd.Run()
		if err != nil {
			log.Err("Got error while executing original command: " + err.Error())
			log.Err(stderr.String())
			fmt.Fprintln(os.Stderr, "Got error while executing original command: "+err.Error())
			fmt.Fprintln(os.Stderr, stderr.String())
		}
		return
	}
	log.Err("Permission denied.")
	log.Err(errMsg)
	fmt.Fprintln(os.Stderr, "Permission denied.")
	fmt.Fprintln(os.Stderr, errMsg)
}

func formatCommand() ([]string, error) {
	p, err := config.GetString("git:bare:location")
	if err != nil {
		log.Err(err.Error())
		return []string{}, err
	}
	_, repoName, err := parseGitCommand()
	if err != nil {
		log.Err(err.Error())
		return []string{}, err
	}
	repoName += ".git"
	cmdList := strings.Split(os.Getenv("SSH_ORIGINAL_COMMAND"), " ")
	if len(cmdList) != 2 {
		log.Err("Malformed git command")
		return []string{}, fmt.Errorf("Malformed git command")
	}
	cmdList[1] = path.Join(p, repoName)
	return cmdList, nil
}

func main() {
	var err error
	log, err = syslog.New(syslog.LOG_INFO, "gandalf-listener")
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		panic(err.Error())
	}
	err = config.ReadConfigFile("/etc/gandalf.conf")
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	_, _, err = parseGitCommand()
	if err != nil {
		log.Err(err.Error())
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	a := action()
	if a == "git-receive-pack" {
		executeAction(hasWritePermission, "You don't have access to write in this repository.", os.Stdout)
		return
	}
	if a == "git-upload-pack" {
		executeAction(hasReadPermission, "You don't have access to read this repository.", os.Stdout)
		return
	}
}
<|endoftext|>


<commit_before>package index

import (
	"github.com/balzaczyy/golucene/store"
)

type BytesStore struct {
	*store.DataOutput
	blocks    [][]byte
	blockSize uint32
	blockBits uint32
	blockMask uint32
	current   []byte
	nextWrite uint32
}

func newBytesStore(blockBits uint32) *BytesStore {
	blockSize := uint32(1) << blockBits
	self := &BytesStore{blockBits: blockBits,
		blockSize: blockSize,
		blockMask: blockSize - 1,
		nextWrite: blockSize}
	self.DataOutput = &store.DataOutput{
		WriteByte: func(b byte) error {
			if self.nextWrite == self.blockSize {
				self.current = make([]byte, self.blockSize)
				self.blocks = append(self.blocks, self.current)
				self.nextWrite = 0
			}
			self.current[self.nextWrite] = b
			self.nextWrite++
			return nil
		},
		WriteBytes: func(buf []byte) error {
			var offset uint32 = 0
			length := uint32(len(buf))
			for length > 0 {
				chunk := self.blockSize - self.nextWrite
				if length <= chunk {
					copy(self.current[self.nextWrite:], buf[offset:offset+length])
					self.nextWrite += length
					break
				} else {
					if chunk > 0 {
						copy(self.current[self.nextWrite:], buf[offset:offset+chunk])
						offset += chunk
						length -= chunk
					}
					self.current = make([]byte, self.blockSize)
					self.blocks = append(self.blocks, self.current)
					self.nextWrite = 0
				}
			}
			return nil
		}}
	return self
}

func (bs *BytesStore) forwardReader() *BytesReader {
	if len(bs.blocks) == 1 {
		return newForwardBytesReader(bs.blocks[0])
	}
	self := &ByteStoreForwardReader{
		nextRead: bs.blocks,
		skipBytes: func(count int32) {
			self.setPosition(self.getPosition() + int64(count))
		},
		getPosition: func() int64 {
			return (int64(self.nextBuffer)-1)*bs.blockSize + self.nextRead
		},
		setPosition: func(pos int64) {
			bufferIndex := pos >> bs.blockBits
			self.nextBuffer = bufferIndex + 1
			self.current = bs.blocks[bufferIndex]
			self.nextRead = pos & bs.blockMask
			// assert self.getPosition() == pos
		},
		reversed: func() bool {
			return false
		}}
	self.DataInput = &store.DataInput{
		ReadByte: func() byte {
			if self.nextRead == bs.blockSize {
				self.current = bs.blocks[self.nextBuffer]
				self.nextBuffer++
				self.nextRead = 0
			}
			ans := self.current[self.nextRead]
			self.nextRead++
			return ans
		}, ReadBytes: func(buf []byte) (n int, err error) {
			var offset uint32 = 0
			length := uint32(len(buf))
			for length > 0 {
				chunkLeft := bs.blockSize - self.nextRead
				if length <= chunkLeft {
					copy(buf[offset:], self.current[self.nextRead:self.nextRead+length])
					self.nextRead += length
					break
				} else {
					if chunkLeft > 0 {
						copy(buf[offset:], self.current[self.nextRead:self.nextRead+chunkLeft])
						offset += chunkLeft
						length -= chunkLeft
					}
					self.current = bs.blocks[self.nextBuffer]
					self.nextBuffer++
					self.nextRead = 0
				}
			}
			return len(buf), nil
		}}
}

type ByteStoreForwardReader struct {
	*BytesReader
	current    []byte
	nextBuffer uint32
	nextRead   uint32
}
<commit_msg>add newForwardBytesReader()<commit_after>package index

import (
	"github.com/balzaczyy/golucene/store"
)

type BytesStore struct {
	*store.DataOutput
	blocks    [][]byte
	blockSize uint32
	blockBits uint32
	blockMask uint32
	current   []byte
	nextWrite uint32
}

func newBytesStore(blockBits uint32) *BytesStore {
	blockSize := uint32(1) << blockBits
	self := &BytesStore{blockBits: blockBits,
		blockSize: blockSize,
		blockMask: blockSize - 1,
		nextWrite: blockSize}
	self.DataOutput = &store.DataOutput{
		WriteByte: func(b byte) error {
			if self.nextWrite == self.blockSize {
				self.current = make([]byte, self.blockSize)
				self.blocks = append(self.blocks, self.current)
				self.nextWrite = 0
			}
			self.current[self.nextWrite] = b
			self.nextWrite++
			return nil
		},
		WriteBytes: func(buf []byte) error {
			var offset uint32 = 0
			length := uint32(len(buf))
			for length > 0 {
				chunk := self.blockSize - self.nextWrite
				if length <= chunk {
					copy(self.current[self.nextWrite:], buf[offset:offset+length])
					self.nextWrite += length
					break
				} else {
					if chunk > 0 {
						copy(self.current[self.nextWrite:], buf[offset:offset+chunk])
						offset += chunk
						length -= chunk
					}
					self.current = make([]byte, self.blockSize)
					self.blocks = append(self.blocks, self.current)
					self.nextWrite = 0
				}
			}
			return nil
		}}
	return self
}

func (bs *BytesStore) forwardReader() *BytesReader {
	if len(bs.blocks) == 1 {
		return newForwardBytesReader(bs.blocks[0])
	}
	self := &ByteStoreForwardReader{
		nextRead: bs.blockSize,
		skipBytes: func(count int32) {
			self.setPosition(self.getPosition() + int64(count))
		},
		getPosition: func() int64 {
			return (int64(self.nextBuffer)-1)*bs.blockSize + self.nextRead
		},
		setPosition: func(pos int64) {
			bufferIndex := pos >> bs.blockBits
			self.nextBuffer = bufferIndex + 1
			self.current = bs.blocks[bufferIndex]
			self.nextRead = pos & bs.blockMask
			// assert self.getPosition() == pos
		},
		reversed: func() bool {
			return false
		}}
	self.DataInput = &store.DataInput{
		ReadByte: func() byte {
			if self.nextRead == bs.blockSize {
				self.current = bs.blocks[self.nextBuffer]
				self.nextBuffer++
				self.nextRead = 0
			}
			ans := self.current[self.nextRead]
			self.nextRead++
			return ans
		}, ReadBytes: func(buf []byte) (n int, err error) {
			var offset uint32 = 0
			length := uint32(len(buf))
			for length > 0 {
				chunkLeft := bs.blockSize - self.nextRead
				if length <= chunkLeft {
					copy(buf[offset:], self.current[self.nextRead:self.nextRead+length])
					self.nextRead += length
					break
				} else {
					if chunkLeft > 0 {
						copy(buf[offset:], self.current[self.nextRead:self.nextRead+chunkLeft])
						offset += chunkLeft
						length -= chunkLeft
					}
					self.current = bs.blocks[self.nextBuffer]
					self.nextBuffer++
					self.nextRead = 0
				}
			}
			return len(buf), nil
		}}
	return self
}

type ByteStoreForwardReader struct {
	*BytesReader
	current    []byte
	nextBuffer uint32
	nextRead   uint32
}

type ForwardBytesReader struct {
	*BytesReader
	bytes []byte
	pos   int32
}

func newForwardBytesReader(bytes []byte) *BytesReader {
	self := &ForwardBytesReader{
		skipBytes: func(count int32) {
			self.pos += count
		}, getPosition: func() int64 {
			return int64(self.pos)
		}, setPosition: func(pos int64) {
			self.pos = int32(pos)
		}, reversed: func() bool {
			return false
		}}
	self.DataInput = &store.DataInput{
		ReadByte: func() byte {
			self.pos++
			return self.bytes[self.pos-1]
		}, ReadBytes: func(buf []byte) (n int, err error) {
			copy(bytes[self.pos:], buf)
			self.pos += len(buf)
			return len(buf), nil
		}}
	return self
}
<|endoftext|>


<commit_before>package sets

import (
	"testing"
)

func TestIntSet(t *testing.T) {
	x := IntSet{}
	x.Add(1)
	x.Add(2)
	x.Add(1)
	if !x.Contains(1) {
		t.Errorf("Should have had 1")
	}
	if x.Contains(3) {
		t.Errorf("Should not have had 3")
	}
	x.Remove(2)
	if x.Contains(2) {
		t.Errorf("Should not have had 2")
	}
	y := x.Copy()
	if len(y) != 1 {
		t.Errorf("Should have had 1 element")
	}
	if !y.Contains(1) {
		t.Errorf("Should have had 1")
	}
}
<commit_msg>Add test coverage for string output<commit_after>package sets

import (
	"testing"
)

func TestIntSet(t *testing.T) {
	x := IntSet{}
	x.Add(1)
	x.Add(2)
	x.Add(1)
	if !x.Contains(1) {
		t.Errorf("Should have had 1")
	}
	if x.Contains(3) {
		t.Errorf("Should not have had 3")
	}
	x.Remove(2)
	if x.Contains(2) {
		t.Errorf("Should not have had 2")
	}
	y := x.Copy()
	if len(y) != 1 {
		t.Errorf("Should have had 1 element")
	}
	if !y.Contains(1) {
		t.Errorf("Should have had 1")
	}
	yString := y.String()
	if "[1]" != yString {
		t.Errorf("output was wrong: %v", yString)
	}
	y.Add(5)
	yString = y.String()
	if "[1 5]" != yString && "[5 1]" != yString {
		t.Errorf("output was wrong: %v", yString)
	}
	z := IntSet{}
	zString := z.String()
	if "[]" != zString {
		t.Errorf("output was wrong: %v", zString)
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
	"time"

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

func TestAccAWSLaunchConfiguration_basic(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationNoNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.bar", "terraform-"),
				),
			},
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationPrefixNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.baz", "baz-"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "image_id", "ami-21f78e11"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "instance_type", "m1.small"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "associate_public_ip_address", "true"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", ""),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithSpotPriceConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", "0.01"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withVpcClassicLink(t *testing.T) {
	var vpc ec2.Vpc
	var group ec2.SecurityGroup
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig_withVpcClassicLink,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.foo", &conf),
					testAccCheckVpcExists("aws_vpc.foo", &vpc),
					testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withIAMProfile(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig_withIAMProfile,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationWithEncryption(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		} else if blockDevices["/dev/sda1"].Ebs.Encrypted != nil {
			return fmt.Errorf("root device should not include value for Encrypted")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		} else if !*blockDevices["/dev/sdb"].Ebs.Encrypted {
			return fmt.Errorf("block device isn't encrypted as expected: /dev/sdb")
		}

		return nil
	}
}

func TestAccAWSLaunchConfiguration_withEncryption(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithEncryption,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),

					testAccCheckAWSLaunchConfigurationWithEncryption(&conf),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
	resource, prefix string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		r, ok := s.RootModule().Resources[resource]
		if !ok {
			return fmt.Errorf("Resource not found")
		}
		name, ok := r.Primary.Attributes["name"]
		if !ok {
			return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes)
		}
		if !strings.HasPrefix(name, prefix) {
			return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix)
		}
		return nil
	}
}

func testAccCheckAWSLaunchConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

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

		describe, err := conn.DescribeLaunchConfigurations(
			&autoscaling.DescribeLaunchConfigurationsInput{
				LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.LaunchConfigurations) != 0 &&
				*describe.LaunchConfigurations[0].LaunchConfigurationName == rs.Primary.ID {
				return fmt.Errorf("Launch Configuration still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if providerErr.Code() != "InvalidLaunchConfiguration.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckAWSLaunchConfigurationAttributes(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.ImageId != "ami-21f78e11" {
			return fmt.Errorf("Bad image_id: %s", *conf.ImageId)
		}

		if !strings.HasPrefix(*conf.LaunchConfigurationName, "terraform-") {
			return fmt.Errorf("Bad name: %s", *conf.LaunchConfigurationName)
		}

		if *conf.InstanceType != "m1.small" {
			return fmt.Errorf("Bad instance_type: %s", *conf.InstanceType)
		}

		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		// Check if the third block device exists.
		if _, ok := blockDevices["/dev/sdc"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdc")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		return nil
	}
}

func testAccCheckAWSLaunchConfigurationExists(n string, res *autoscaling.LaunchConfiguration) 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 Launch Configuration ID is set")
		}

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

		describeOpts := autoscaling.DescribeLaunchConfigurationsInput{
			LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
		}
		describe, err := conn.DescribeLaunchConfigurations(&describeOpts)

		if err != nil {
			return err
		}

		if len(describe.LaunchConfigurations) != 1 ||
			*describe.LaunchConfigurations[0].LaunchConfigurationName != rs.Primary.ID {
			return fmt.Errorf("Launch Configuration Group not found")
		}

		*res = *describe.LaunchConfigurations[0]

		return nil
	}
}

var testAccAWSLaunchConfigurationConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "m1.small"
  user_data = "foobar-user-data"
  associate_public_ip_address = true

	root_block_device {
		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
	}
	ebs_block_device {
		device_name = "/dev/sdc"
		volume_size = 10
		volume_type = "io1"
		iops = 100
	}
	ephemeral_block_device {
		device_name = "/dev/sde"
		virtual_name = "ephemeral0"
	}
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

var testAccAWSLaunchConfigurationWithSpotPriceConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "t1.micro"
  spot_price = "0.01"
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

const testAccAWSLaunchConfigurationNoNameConfig = `
resource "aws_launch_configuration" "bar" {
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationPrefixNameConfig = `
resource "aws_launch_configuration" "baz" {
   name_prefix = "baz-"
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationWithEncryption = `
resource "aws_launch_configuration" "baz" {
   image_id = "ami-5189a661"
   instance_type = "t2.micro"
   associate_public_ip_address = false

   	root_block_device {
   		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
		encrypted = true
	}
}
`
const testAccAWSLaunchConfigurationConfig_withVpcClassicLink = `
resource "aws_vpc" "foo" {
   cidr_block = "10.0.0.0/16"
   enable_classiclink = true
}

resource "aws_security_group" "foo" {
  name = "foo"
  vpc_id = "${aws_vpc.foo.id}"
}

resource "aws_launch_configuration" "foo" {
   name = "TestAccAWSLaunchConfiguration_withVpcClassicLink"
   image_id = "ami-2d39803a"
   instance_type = "t1.micro"

   vpc_classic_link_id = "${aws_vpc.foo.id}"
   vpc_classic_link_security_groups = ["${aws_security_group.foo.id}"]
}
`

const testAccAWSLaunchConfigurationConfig_withIAMProfile = `
resource "aws_iam_role" "role" {
	name  = "TestAccAWSLaunchConfiguration-withIAMProfile"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_instance_profile" "profile" {
	name  = "TestAccAWSLaunchConfiguration-withIAMProfile"
	roles = ["${aws_iam_role.role.name}"]
}

resource "aws_launch_configuration" "bar" {
	image_id             = "ami-5189a661"
	instance_type        = "t2.nano"
	iam_instance_profile = "${aws_iam_instance_profile.profile.name}"
}
`
<commit_msg>provider/aws: Fix the AMI ID in the  test for VPC Classic Link<commit_after>package aws

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
	"time"

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

func TestAccAWSLaunchConfiguration_basic(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationNoNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.bar", "terraform-"),
				),
			},
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationPrefixNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.baz", "baz-"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "image_id", "ami-21f78e11"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "instance_type", "m1.small"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "associate_public_ip_address", "true"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", ""),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithSpotPriceConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", "0.01"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withVpcClassicLink(t *testing.T) {
	var vpc ec2.Vpc
	var group ec2.SecurityGroup
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig_withVpcClassicLink,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.foo", &conf),
					testAccCheckVpcExists("aws_vpc.foo", &vpc),
					testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withIAMProfile(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig_withIAMProfile,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationWithEncryption(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		} else if blockDevices["/dev/sda1"].Ebs.Encrypted != nil {
			return fmt.Errorf("root device should not include value for Encrypted")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		} else if !*blockDevices["/dev/sdb"].Ebs.Encrypted {
			return fmt.Errorf("block device isn't encrypted as expected: /dev/sdb")
		}

		return nil
	}
}

func TestAccAWSLaunchConfiguration_withEncryption(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithEncryption,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),

					testAccCheckAWSLaunchConfigurationWithEncryption(&conf),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
	resource, prefix string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		r, ok := s.RootModule().Resources[resource]
		if !ok {
			return fmt.Errorf("Resource not found")
		}
		name, ok := r.Primary.Attributes["name"]
		if !ok {
			return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes)
		}
		if !strings.HasPrefix(name, prefix) {
			return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix)
		}
		return nil
	}
}

func testAccCheckAWSLaunchConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

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

		describe, err := conn.DescribeLaunchConfigurations(
			&autoscaling.DescribeLaunchConfigurationsInput{
				LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.LaunchConfigurations) != 0 &&
				*describe.LaunchConfigurations[0].LaunchConfigurationName == rs.Primary.ID {
				return fmt.Errorf("Launch Configuration still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if providerErr.Code() != "InvalidLaunchConfiguration.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckAWSLaunchConfigurationAttributes(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.ImageId != "ami-21f78e11" {
			return fmt.Errorf("Bad image_id: %s", *conf.ImageId)
		}

		if !strings.HasPrefix(*conf.LaunchConfigurationName, "terraform-") {
			return fmt.Errorf("Bad name: %s", *conf.LaunchConfigurationName)
		}

		if *conf.InstanceType != "m1.small" {
			return fmt.Errorf("Bad instance_type: %s", *conf.InstanceType)
		}

		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		// Check if the third block device exists.
		if _, ok := blockDevices["/dev/sdc"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdc")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		return nil
	}
}

func testAccCheckAWSLaunchConfigurationExists(n string, res *autoscaling.LaunchConfiguration) 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 Launch Configuration ID is set")
		}

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

		describeOpts := autoscaling.DescribeLaunchConfigurationsInput{
			LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
		}
		describe, err := conn.DescribeLaunchConfigurations(&describeOpts)

		if err != nil {
			return err
		}

		if len(describe.LaunchConfigurations) != 1 ||
			*describe.LaunchConfigurations[0].LaunchConfigurationName != rs.Primary.ID {
			return fmt.Errorf("Launch Configuration Group not found")
		}

		*res = *describe.LaunchConfigurations[0]

		return nil
	}
}

var testAccAWSLaunchConfigurationConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "m1.small"
  user_data = "foobar-user-data"
  associate_public_ip_address = true

	root_block_device {
		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
	}
	ebs_block_device {
		device_name = "/dev/sdc"
		volume_size = 10
		volume_type = "io1"
		iops = 100
	}
	ephemeral_block_device {
		device_name = "/dev/sde"
		virtual_name = "ephemeral0"
	}
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

var testAccAWSLaunchConfigurationWithSpotPriceConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "t1.micro"
  spot_price = "0.01"
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

const testAccAWSLaunchConfigurationNoNameConfig = `
resource "aws_launch_configuration" "bar" {
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationPrefixNameConfig = `
resource "aws_launch_configuration" "baz" {
   name_prefix = "baz-"
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationWithEncryption = `
resource "aws_launch_configuration" "baz" {
   image_id = "ami-5189a661"
   instance_type = "t2.micro"
   associate_public_ip_address = false

   	root_block_device {
   		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
		encrypted = true
	}
}
`
const testAccAWSLaunchConfigurationConfig_withVpcClassicLink = `
resource "aws_vpc" "foo" {
   cidr_block = "10.0.0.0/16"
   enable_classiclink = true
}

resource "aws_security_group" "foo" {
  name = "foo"
  vpc_id = "${aws_vpc.foo.id}"
}

resource "aws_launch_configuration" "foo" {
   name = "TestAccAWSLaunchConfiguration_withVpcClassicLink"
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"

   vpc_classic_link_id = "${aws_vpc.foo.id}"
   vpc_classic_link_security_groups = ["${aws_security_group.foo.id}"]
}
`

const testAccAWSLaunchConfigurationConfig_withIAMProfile = `
resource "aws_iam_role" "role" {
	name  = "TestAccAWSLaunchConfiguration-withIAMProfile"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_instance_profile" "profile" {
	name  = "TestAccAWSLaunchConfiguration-withIAMProfile"
	roles = ["${aws_iam_role.role.name}"]
}

resource "aws_launch_configuration" "bar" {
	image_id             = "ami-5189a661"
	instance_type        = "t2.nano"
	iam_instance_profile = "${aws_iam_instance_profile.profile.name}"
}
`
<|endoftext|>


<commit_before>package bitrise

import (
	"os"
	"os/exec"
	"strings"

	log "github.com/Sirupsen/logrus"
)

// ------------------
// --- Stepman

// RunStepmanSetup ...
func RunStepmanSetup(collection string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--debug", "--loglevel", logLevel, "--collection", collection, "setup"}
	return RunCommand("stepman", args...)
}

// RunStepmanActivate ...
func RunStepmanActivate(collection, stepID, stepVersion, dir string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--debug", "--loglevel", logLevel, "--collection", collection, "activate", "--id", stepID, "--version", stepVersion, "--path", dir}
	return RunCommand("stepman", args...)
}

// ------------------
// --- Envman

// RunEnvmanInit ...
func RunEnvmanInit() error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "init"}
	return RunCommand("envman", args...)
}

// RunEnvmanAdd ...
func RunEnvmanAdd(key, value string, expand bool) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "add", "--key", key}
	if !expand {
		args = []string{"--loglevel", logLevel, "add", "--key", key, "--no-expand"}
	}

	envman := exec.Command("envman", args...)
	envman.Stdin = strings.NewReader(value)
	envman.Stdout = os.Stdout
	envman.Stderr = os.Stderr
	return envman.Run()
}

// RunEnvmanRunInDir ...
func RunEnvmanRunInDir(dir string, cmd []string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "run"}
	args = append(args, cmd...)
	return RunCommandInDir(dir, "envman", args...)
}

// RunEnvmanRun ...
func RunEnvmanRun(cmd []string) error {
	return RunEnvmanRunInDir("", cmd)
}

// RunEnvmanEnvstoreTest ...
func RunEnvmanEnvstoreTest(pth string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "--path", pth, "print"}
	cmd := exec.Command("envman", args...)
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

// ------------------
// --- Common

// RunCopy ...
func RunCopy(src, dst string) error {
	cpCmd := exec.Command("cp", src, dst)
	return cpCmd.Run()
}

// RunCommand ...
func RunCommand(name string, args ...string) error {
	return RunCommandInDir("", name, args...)
}

// RunCommandInDir ...
func RunCommandInDir(dir, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if dir != "" {
		cmd.Dir = dir
	}
	return cmd.Run()
}
<commit_msg>copy fix<commit_after>package bitrise

import (
	"os"
	"os/exec"
	"strings"

	log "github.com/Sirupsen/logrus"
)

// ------------------
// --- Stepman

// RunStepmanSetup ...
func RunStepmanSetup(collection string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--debug", "--loglevel", logLevel, "--collection", collection, "setup"}
	return RunCommand("stepman", args...)
}

// RunStepmanActivate ...
func RunStepmanActivate(collection, stepID, stepVersion, dir string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--debug", "--loglevel", logLevel, "--collection", collection, "activate", "--id", stepID, "--version", stepVersion, "--path", dir}
	return RunCommand("stepman", args...)
}

// ------------------
// --- Envman

// RunEnvmanInit ...
func RunEnvmanInit() error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "init"}
	return RunCommand("envman", args...)
}

// RunEnvmanAdd ...
func RunEnvmanAdd(key, value string, expand bool) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "add", "--key", key}
	if !expand {
		args = []string{"--loglevel", logLevel, "add", "--key", key, "--no-expand"}
	}

	envman := exec.Command("envman", args...)
	envman.Stdin = strings.NewReader(value)
	envman.Stdout = os.Stdout
	envman.Stderr = os.Stderr
	return envman.Run()
}

// RunEnvmanRunInDir ...
func RunEnvmanRunInDir(dir string, cmd []string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "run"}
	args = append(args, cmd...)
	return RunCommandInDir(dir, "envman", args...)
}

// RunEnvmanRun ...
func RunEnvmanRun(cmd []string) error {
	return RunEnvmanRunInDir("", cmd)
}

// RunEnvmanEnvstoreTest ...
func RunEnvmanEnvstoreTest(pth string) error {
	logLevel := log.GetLevel().String()
	args := []string{"--loglevel", logLevel, "--path", pth, "print"}
	cmd := exec.Command("envman", args...)
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

// ------------------
// --- Common

// RunCopy ...
func RunCopy(src, dst string) error {
	args := []string{src, dst}
	return RunCommand("cp", args...)
}

// RunCommand ...
func RunCommand(name string, args ...string) error {
	return RunCommandInDir("", name, args...)
}

// RunCommandInDir ...
func RunCommandInDir(dir, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if dir != "" {
		cmd.Dir = dir
	}
	return cmd.Run()
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Shivaram Lingamneni <slingamn@cs.stanford.edu>
// released under the MIT license

package irc

import (
	"net"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/oragono/oragono/irc/languages"
	"github.com/oragono/oragono/irc/modes"
)

func (server *Server) Config() (config *Config) {
	return (*Config)(atomic.LoadPointer(&server.config))
}

func (server *Server) SetConfig(config *Config) {
	atomic.StorePointer(&server.config, unsafe.Pointer(config))
}

func (server *Server) ChannelRegistrationEnabled() bool {
	return server.Config().Channels.Registration.Enabled
}

func (server *Server) AccountConfig() *AccountConfig {
	return &server.Config().Accounts
}

func (server *Server) GetOperator(name string) (oper *Oper) {
	name, err := CasefoldName(name)
	if err != nil {
		return
	}
	return server.Config().operators[name]
}

func (server *Server) Languages() (lm *languages.Manager) {
	return server.Config().languageManager
}

func (client *Client) Sessions() (sessions []*Session) {
	client.stateMutex.RLock()
	sessions = client.sessions
	client.stateMutex.RUnlock()
	return
}

func (client *Client) GetSessionByResumeID(resumeID string) (result *Session) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()

	for _, session := range client.sessions {
		if session.resumeID == resumeID {
			return session
		}
	}
	return
}

type SessionData struct {
	ctime    time.Time
	atime    time.Time
	ip       net.IP
	hostname string
	certfp   string
}

func (client *Client) AllSessionData(currentSession *Session) (data []SessionData, currentIndex int) {
	currentIndex = -1
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()

	data = make([]SessionData, len(client.sessions))
	for i, session := range client.sessions {
		if session == currentSession {
			currentIndex = i
		}
		data[i] = SessionData{
			atime:    session.lastActive,
			ctime:    session.ctime,
			hostname: session.rawHostname,
			certfp:   session.certfp,
		}
		if session.proxiedIP != nil {
			data[i].ip = session.proxiedIP
		} else {
			data[i].ip = session.realIP
		}
	}
	return
}

func (client *Client) AddSession(session *Session) (success bool, numSessions int, lastSeen time.Time) {
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()

	// client may be dying and ineligible to receive another session
	if client.destroyed {
		return
	}
	// success, attach the new session to the client
	session.client = client
	newSessions := make([]*Session, len(client.sessions)+1)
	copy(newSessions, client.sessions)
	newSessions[len(newSessions)-1] = session
	if client.accountSettings.AutoreplayMissed {
		lastSeen = client.lastSeen
	}
	client.sessions = newSessions
	return true, len(client.sessions), lastSeen
}

func (client *Client) removeSession(session *Session) (success bool, length int) {
	if len(client.sessions) == 0 {
		return
	}
	sessions := make([]*Session, 0, len(client.sessions)-1)
	for _, currentSession := range client.sessions {
		if session == currentSession {
			success = true
		} else {
			sessions = append(sessions, currentSession)
		}
	}
	client.sessions = sessions
	length = len(sessions)
	return
}

func (session *Session) SetResumeID(resumeID string) {
	session.client.stateMutex.Lock()
	session.resumeID = resumeID
	session.client.stateMutex.Unlock()
}

func (client *Client) Nick() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nick
}

func (client *Client) NickMaskString() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickMaskString
}

func (client *Client) NickCasefolded() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickCasefolded
}

func (client *Client) NickMaskCasefolded() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickMaskCasefolded
}

func (client *Client) Username() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.username
}

func (client *Client) Hostname() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.hostname
}

func (client *Client) Away() (result bool) {
	client.stateMutex.Lock()
	result = client.away
	client.stateMutex.Unlock()
	return
}

func (client *Client) SetAway(away bool, awayMessage string) (changed bool) {
	client.stateMutex.Lock()
	changed = away != client.away
	client.away = away
	client.awayMessage = awayMessage
	client.stateMutex.Unlock()
	return
}

func (client *Client) SetExitedSnomaskSent() {
	client.stateMutex.Lock()
	client.exitedSnomaskSent = true
	client.stateMutex.Unlock()
}

func (client *Client) AlwaysOn() (alwaysOn bool) {
	client.stateMutex.Lock()
	alwaysOn = client.alwaysOn
	client.stateMutex.Unlock()
	return
}

// uniqueIdentifiers returns the strings for which the server enforces per-client
// uniqueness/ownership; no two clients can have colliding casefolded nicks or
// skeletons.
func (client *Client) uniqueIdentifiers() (nickCasefolded string, skeleton string) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickCasefolded, client.skeleton
}

func (client *Client) ResumeID() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.resumeID
}

func (client *Client) SetResumeID(id string) {
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()
	client.resumeID = id
}

func (client *Client) Oper() *Oper {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.oper
}

func (client *Client) Registered() bool {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.registered
}

func (client *Client) SetRegistered() {
	// `registered` is only written from the client's own goroutine, but may be
	// read from other goroutines; therefore, the client's own goroutine may read
	// the value without synchronization, but must write it with synchronization,
	// and other goroutines must read it with synchronization
	client.stateMutex.Lock()
	client.registered = true
	client.stateMutex.Unlock()
}

func (client *Client) RawHostname() (result string) {
	client.stateMutex.Lock()
	result = client.rawHostname
	client.stateMutex.Unlock()
	return
}

func (client *Client) AwayMessage() (result string) {
	client.stateMutex.RLock()
	result = client.awayMessage
	client.stateMutex.RUnlock()
	return
}

func (client *Client) SetAwayMessage(message string) {
	client.stateMutex.Lock()
	client.awayMessage = message
	client.stateMutex.Unlock()
}

func (client *Client) Account() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.account
}

func (client *Client) AccountName() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.accountName
}

func (client *Client) Login(account ClientAccount) {
	alwaysOn := persistenceEnabled(client.server.Config().Accounts.Multiclient.AlwaysOn, account.Settings.AlwaysOn)
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()
	client.account = account.NameCasefolded
	client.accountName = account.Name
	client.accountSettings = account.Settings
	// check `registered` to avoid incorrectly marking a temporary (pre-reattach),
	// SASL'ing client as always-on
	if client.registered {
		client.alwaysOn = alwaysOn
	}
	client.accountRegDate = account.RegisteredAt
	return
}

func (client *Client) historyCutoff() (cutoff time.Time) {
	client.stateMutex.Lock()
	if client.account != "" {
		cutoff = client.accountRegDate
	} else {
		cutoff = client.ctime
	}
	client.stateMutex.Unlock()
	return
}

func (client *Client) Logout() {
	client.stateMutex.Lock()
	client.account = ""
	client.accountName = ""
	client.alwaysOn = false
	client.accountRegDate = time.Time{}
	client.accountSettings = AccountSettings{}
	client.stateMutex.Unlock()
}

func (client *Client) AccountSettings() (result AccountSettings) {
	client.stateMutex.RLock()
	result = client.accountSettings
	client.stateMutex.RUnlock()
	return
}

func (client *Client) SetAccountSettings(settings AccountSettings) {
	alwaysOn := persistenceEnabled(client.server.Config().Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
	client.stateMutex.Lock()
	client.accountSettings = settings
	if client.registered {
		client.alwaysOn = alwaysOn
	}
	client.stateMutex.Unlock()
}

func (client *Client) Languages() (languages []string) {
	client.stateMutex.RLock()
	languages = client.languages
	client.stateMutex.RUnlock()
	return languages
}

func (client *Client) SetLanguages(languages []string) {
	client.stateMutex.Lock()
	client.languages = languages
	client.stateMutex.Unlock()
}

func (client *Client) HasMode(mode modes.Mode) bool {
	// client.flags has its own synch
	return client.modes.HasMode(mode)
}

func (client *Client) SetMode(mode modes.Mode, on bool) bool {
	return client.modes.SetMode(mode, on)
}

func (client *Client) SetRealname(realname string) {
	client.stateMutex.Lock()
	client.realname = realname
	client.stateMutex.Unlock()
}

func (client *Client) Channels() (result []*Channel) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	length := len(client.channels)
	result = make([]*Channel, length)
	i := 0
	for channel := range client.channels {
		result[i] = channel
		i++
	}
	return
}

func (client *Client) NumChannels() int {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return len(client.channels)
}

func (client *Client) WhoWas() (result WhoWas) {
	return client.Details().WhoWas
}

func (client *Client) Details() (result ClientDetails) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.detailsNoMutex()
}

func (client *Client) detailsNoMutex() (result ClientDetails) {
	result.nick = client.nick
	result.nickCasefolded = client.nickCasefolded
	result.username = client.username
	result.hostname = client.hostname
	result.realname = client.realname
	result.nickMask = client.nickMaskString
	result.nickMaskCasefolded = client.nickMaskCasefolded
	result.account = client.account
	result.accountName = client.accountName
	return
}

func (channel *Channel) Name() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.name
}

func (channel *Channel) NameCasefolded() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.nameCasefolded
}

func (channel *Channel) Rename(name, nameCasefolded string) {
	channel.stateMutex.Lock()
	channel.name = name
	channel.nameCasefolded = nameCasefolded
	if channel.registeredFounder != "" {
		channel.registeredTime = time.Now().UTC()
	}
	channel.stateMutex.Unlock()
}

func (channel *Channel) Members() (result []*Client) {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.membersCache
}

func (channel *Channel) setUserLimit(limit int) {
	channel.stateMutex.Lock()
	channel.userLimit = limit
	channel.stateMutex.Unlock()
}

func (channel *Channel) setKey(key string) {
	channel.stateMutex.Lock()
	defer channel.stateMutex.Unlock()
	channel.key = key
}

func (channel *Channel) Founder() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.registeredFounder
}

func (channel *Channel) HighestUserMode(client *Client) (result modes.Mode) {
	channel.stateMutex.RLock()
	clientModes := channel.members[client]
	channel.stateMutex.RUnlock()
	return clientModes.HighestChannelUserMode()
}

func (channel *Channel) Settings() (result ChannelSettings) {
	channel.stateMutex.RLock()
	result = channel.settings
	channel.stateMutex.RUnlock()
	return result
}

func (channel *Channel) SetSettings(settings ChannelSettings) {
	channel.stateMutex.Lock()
	channel.settings = settings
	channel.stateMutex.Unlock()
	channel.MarkDirty(IncludeSettings)
}
<commit_msg>mark dirty when a client first becomes always-on<commit_after>// Copyright (c) 2017 Shivaram Lingamneni <slingamn@cs.stanford.edu>
// released under the MIT license

package irc

import (
	"net"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/oragono/oragono/irc/languages"
	"github.com/oragono/oragono/irc/modes"
)

func (server *Server) Config() (config *Config) {
	return (*Config)(atomic.LoadPointer(&server.config))
}

func (server *Server) SetConfig(config *Config) {
	atomic.StorePointer(&server.config, unsafe.Pointer(config))
}

func (server *Server) ChannelRegistrationEnabled() bool {
	return server.Config().Channels.Registration.Enabled
}

func (server *Server) AccountConfig() *AccountConfig {
	return &server.Config().Accounts
}

func (server *Server) GetOperator(name string) (oper *Oper) {
	name, err := CasefoldName(name)
	if err != nil {
		return
	}
	return server.Config().operators[name]
}

func (server *Server) Languages() (lm *languages.Manager) {
	return server.Config().languageManager
}

func (client *Client) Sessions() (sessions []*Session) {
	client.stateMutex.RLock()
	sessions = client.sessions
	client.stateMutex.RUnlock()
	return
}

func (client *Client) GetSessionByResumeID(resumeID string) (result *Session) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()

	for _, session := range client.sessions {
		if session.resumeID == resumeID {
			return session
		}
	}
	return
}

type SessionData struct {
	ctime    time.Time
	atime    time.Time
	ip       net.IP
	hostname string
	certfp   string
}

func (client *Client) AllSessionData(currentSession *Session) (data []SessionData, currentIndex int) {
	currentIndex = -1
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()

	data = make([]SessionData, len(client.sessions))
	for i, session := range client.sessions {
		if session == currentSession {
			currentIndex = i
		}
		data[i] = SessionData{
			atime:    session.lastActive,
			ctime:    session.ctime,
			hostname: session.rawHostname,
			certfp:   session.certfp,
		}
		if session.proxiedIP != nil {
			data[i].ip = session.proxiedIP
		} else {
			data[i].ip = session.realIP
		}
	}
	return
}

func (client *Client) AddSession(session *Session) (success bool, numSessions int, lastSeen time.Time) {
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()

	// client may be dying and ineligible to receive another session
	if client.destroyed {
		return
	}
	// success, attach the new session to the client
	session.client = client
	newSessions := make([]*Session, len(client.sessions)+1)
	copy(newSessions, client.sessions)
	newSessions[len(newSessions)-1] = session
	if client.accountSettings.AutoreplayMissed {
		lastSeen = client.lastSeen
	}
	client.sessions = newSessions
	return true, len(client.sessions), lastSeen
}

func (client *Client) removeSession(session *Session) (success bool, length int) {
	if len(client.sessions) == 0 {
		return
	}
	sessions := make([]*Session, 0, len(client.sessions)-1)
	for _, currentSession := range client.sessions {
		if session == currentSession {
			success = true
		} else {
			sessions = append(sessions, currentSession)
		}
	}
	client.sessions = sessions
	length = len(sessions)
	return
}

func (session *Session) SetResumeID(resumeID string) {
	session.client.stateMutex.Lock()
	session.resumeID = resumeID
	session.client.stateMutex.Unlock()
}

func (client *Client) Nick() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nick
}

func (client *Client) NickMaskString() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickMaskString
}

func (client *Client) NickCasefolded() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickCasefolded
}

func (client *Client) NickMaskCasefolded() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickMaskCasefolded
}

func (client *Client) Username() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.username
}

func (client *Client) Hostname() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.hostname
}

func (client *Client) Away() (result bool) {
	client.stateMutex.Lock()
	result = client.away
	client.stateMutex.Unlock()
	return
}

func (client *Client) SetAway(away bool, awayMessage string) (changed bool) {
	client.stateMutex.Lock()
	changed = away != client.away
	client.away = away
	client.awayMessage = awayMessage
	client.stateMutex.Unlock()
	return
}

func (client *Client) SetExitedSnomaskSent() {
	client.stateMutex.Lock()
	client.exitedSnomaskSent = true
	client.stateMutex.Unlock()
}

func (client *Client) AlwaysOn() (alwaysOn bool) {
	client.stateMutex.Lock()
	alwaysOn = client.alwaysOn
	client.stateMutex.Unlock()
	return
}

// uniqueIdentifiers returns the strings for which the server enforces per-client
// uniqueness/ownership; no two clients can have colliding casefolded nicks or
// skeletons.
func (client *Client) uniqueIdentifiers() (nickCasefolded string, skeleton string) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.nickCasefolded, client.skeleton
}

func (client *Client) ResumeID() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.resumeID
}

func (client *Client) SetResumeID(id string) {
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()
	client.resumeID = id
}

func (client *Client) Oper() *Oper {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.oper
}

func (client *Client) Registered() bool {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.registered
}

func (client *Client) SetRegistered() {
	// `registered` is only written from the client's own goroutine, but may be
	// read from other goroutines; therefore, the client's own goroutine may read
	// the value without synchronization, but must write it with synchronization,
	// and other goroutines must read it with synchronization
	client.stateMutex.Lock()
	client.registered = true
	client.stateMutex.Unlock()
}

func (client *Client) RawHostname() (result string) {
	client.stateMutex.Lock()
	result = client.rawHostname
	client.stateMutex.Unlock()
	return
}

func (client *Client) AwayMessage() (result string) {
	client.stateMutex.RLock()
	result = client.awayMessage
	client.stateMutex.RUnlock()
	return
}

func (client *Client) SetAwayMessage(message string) {
	client.stateMutex.Lock()
	client.awayMessage = message
	client.stateMutex.Unlock()
}

func (client *Client) Account() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.account
}

func (client *Client) AccountName() string {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.accountName
}

func (client *Client) Login(account ClientAccount) {
	alwaysOn := persistenceEnabled(client.server.Config().Accounts.Multiclient.AlwaysOn, account.Settings.AlwaysOn)
	client.stateMutex.Lock()
	defer client.stateMutex.Unlock()
	client.account = account.NameCasefolded
	client.accountName = account.Name
	client.accountSettings = account.Settings
	// check `registered` to avoid incorrectly marking a temporary (pre-reattach),
	// SASL'ing client as always-on
	if client.registered {
		client.alwaysOn = alwaysOn
	}
	client.accountRegDate = account.RegisteredAt
	return
}

func (client *Client) historyCutoff() (cutoff time.Time) {
	client.stateMutex.Lock()
	if client.account != "" {
		cutoff = client.accountRegDate
	} else {
		cutoff = client.ctime
	}
	client.stateMutex.Unlock()
	return
}

func (client *Client) Logout() {
	client.stateMutex.Lock()
	client.account = ""
	client.accountName = ""
	client.alwaysOn = false
	client.accountRegDate = time.Time{}
	client.accountSettings = AccountSettings{}
	client.stateMutex.Unlock()
}

func (client *Client) AccountSettings() (result AccountSettings) {
	client.stateMutex.RLock()
	result = client.accountSettings
	client.stateMutex.RUnlock()
	return
}

func (client *Client) SetAccountSettings(settings AccountSettings) {
	// we mark dirty if the client is transitioning to always-on
	markDirty := false
	alwaysOn := persistenceEnabled(client.server.Config().Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
	client.stateMutex.Lock()
	client.accountSettings = settings
	if client.registered {
		markDirty = !client.alwaysOn && alwaysOn
		client.alwaysOn = alwaysOn
	}
	client.stateMutex.Unlock()
	if markDirty {
		client.markDirty(IncludeAllAttrs)
	}
}

func (client *Client) Languages() (languages []string) {
	client.stateMutex.RLock()
	languages = client.languages
	client.stateMutex.RUnlock()
	return languages
}

func (client *Client) SetLanguages(languages []string) {
	client.stateMutex.Lock()
	client.languages = languages
	client.stateMutex.Unlock()
}

func (client *Client) HasMode(mode modes.Mode) bool {
	// client.flags has its own synch
	return client.modes.HasMode(mode)
}

func (client *Client) SetMode(mode modes.Mode, on bool) bool {
	return client.modes.SetMode(mode, on)
}

func (client *Client) SetRealname(realname string) {
	client.stateMutex.Lock()
	client.realname = realname
	client.stateMutex.Unlock()
}

func (client *Client) Channels() (result []*Channel) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	length := len(client.channels)
	result = make([]*Channel, length)
	i := 0
	for channel := range client.channels {
		result[i] = channel
		i++
	}
	return
}

func (client *Client) NumChannels() int {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return len(client.channels)
}

func (client *Client) WhoWas() (result WhoWas) {
	return client.Details().WhoWas
}

func (client *Client) Details() (result ClientDetails) {
	client.stateMutex.RLock()
	defer client.stateMutex.RUnlock()
	return client.detailsNoMutex()
}

func (client *Client) detailsNoMutex() (result ClientDetails) {
	result.nick = client.nick
	result.nickCasefolded = client.nickCasefolded
	result.username = client.username
	result.hostname = client.hostname
	result.realname = client.realname
	result.nickMask = client.nickMaskString
	result.nickMaskCasefolded = client.nickMaskCasefolded
	result.account = client.account
	result.accountName = client.accountName
	return
}

func (channel *Channel) Name() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.name
}

func (channel *Channel) NameCasefolded() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.nameCasefolded
}

func (channel *Channel) Rename(name, nameCasefolded string) {
	channel.stateMutex.Lock()
	channel.name = name
	channel.nameCasefolded = nameCasefolded
	if channel.registeredFounder != "" {
		channel.registeredTime = time.Now().UTC()
	}
	channel.stateMutex.Unlock()
}

func (channel *Channel) Members() (result []*Client) {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.membersCache
}

func (channel *Channel) setUserLimit(limit int) {
	channel.stateMutex.Lock()
	channel.userLimit = limit
	channel.stateMutex.Unlock()
}

func (channel *Channel) setKey(key string) {
	channel.stateMutex.Lock()
	defer channel.stateMutex.Unlock()
	channel.key = key
}

func (channel *Channel) Founder() string {
	channel.stateMutex.RLock()
	defer channel.stateMutex.RUnlock()
	return channel.registeredFounder
}

func (channel *Channel) HighestUserMode(client *Client) (result modes.Mode) {
	channel.stateMutex.RLock()
	clientModes := channel.members[client]
	channel.stateMutex.RUnlock()
	return clientModes.HighestChannelUserMode()
}

func (channel *Channel) Settings() (result ChannelSettings) {
	channel.stateMutex.RLock()
	result = channel.settings
	channel.stateMutex.RUnlock()
	return result
}

func (channel *Channel) SetSettings(settings ChannelSettings) {
	channel.stateMutex.Lock()
	channel.settings = settings
	channel.stateMutex.Unlock()
	channel.MarkDirty(IncludeSettings)
}
<|endoftext|>


<commit_before>package bob

import (
	//"errors"
	//"fmt"
	"io"
	//"io/ioutil"
	"os"
	"os/exec"
)

/*
CopyFile copies one file from source to dest.  Copied from
https://gist.github.com/elazarl/5507969 and modified.
*/
func CopyFile(source string, dest string) (err error) {
	sourceFile, err := os.Open(source)
	if err != nil {
		return
	}

	defer sourceFile.Close()

	destFile, err := os.Create(dest)
	if err != nil {
		return
	}
	defer destFile.Close()

	if _, err = io.Copy(destFile, sourceFile); err != nil {
		return
	}

	sourceInfo, err := os.Stat(source)
	if err != nil {
		return err
	}

	if err = os.Chmod(dest, sourceInfo.Mode()); err != nil {
		return
	}

	return destFile.Close()
}

/*
CopyDir recursively copies one dir from source to dest.  Copied from
https://github.com/opesun/copyrecur.
*/
func CopyDir(source string, dest string) (err error) {
	return exec.Command("cp", "-R", source, dest).Run()

	/*
		THE CODE BELOW IS BROKEN - FIX IT!
	*/

	//// get properties of source dir
	//sourceInfo, err := os.Stat(source)
	//if err != nil {
	//return
	//}

	//if !sourceInfo.IsDir() {
	//return errors.New("source is not a directory")
	//}

	//// ensure dest dir does not already exist
	//if _, err = os.Open(dest); !os.IsNotExist(err) {
	//return errors.New("destination already exists")
	//}
	//// create dest dir
	//if err = os.MkdirAll(dest, sourceInfo.Mode()); err != nil {
	//return
	//}

	//files, err := ioutil.ReadDir(source)

	//for _, file := range files {
	//sourceFilePath := fmt.Sprintf("%s/%s", source, file.Name())
	//destFilePath := fmt.Sprintf("%s/%s", dest, file.Name())

	//if file.IsDir() {
	//if err = CopyDir(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//} else {
	//if err = CopyFile(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//}

	//}
	//return
}
<commit_msg>Minor refactoring of the bob_helpers (file/dir copy) functions<commit_after>package bob

import (
	//"errors"
	//"fmt"
	"io"
	//"io/ioutil"
	"os"
	"os/exec"
)

/*
CopyFile copies one file from source to dest.  Copied from
https://gist.github.com/elazarl/5507969 and modified.
*/
func CopyFile(src, dest string) (err error) {
	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	//create dest
	out, err := os.Create(dest)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()

	//copy to dest from source
	if _, err = io.Copy(out, in); err != nil {
		return
	}

	//duplicate source permissions on dest
	si, err := os.Stat(src)
	if err != nil {
		return
	}

	if err = out.Chmod(si.Mode()); err != nil {
		return
	}

	//sync dest to disk
	err = out.Sync()

	return
}

/*
CopyDir recursively copies one dir from source to dest.  Copied from
https://github.com/opesun/copyrecur.
*/
func CopyDir(source string, dest string) (err error) {
	return exec.Command("cp", "-af", source, dest).Run()

	/*
		THE CODE BELOW IS BROKEN - FIX IT!
	*/

	//// get properties of source dir
	//sourceInfo, err := os.Stat(source)
	//if err != nil {
	//return
	//}

	//if !sourceInfo.IsDir() {
	//return errors.New("source is not a directory")
	//}

	//// ensure dest dir does not already exist
	//if _, err = os.Open(dest); !os.IsNotExist(err) {
	//return errors.New("destination already exists")
	//}
	//// create dest dir
	//if err = os.MkdirAll(dest, sourceInfo.Mode()); err != nil {
	//return
	//}

	//files, err := ioutil.ReadDir(source)

	//for _, file := range files {
	//sourceFilePath := fmt.Sprintf("%s/%s", source, file.Name())
	//destFilePath := fmt.Sprintf("%s/%s", dest, file.Name())

	//if file.IsDir() {
	//if err = CopyDir(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//} else {
	//if err = CopyFile(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//}

	//}
	//return
}
<|endoftext|>


<commit_before>package arel

type JoinSource struct{}
<commit_msg>Add BinaryNode to JoinSource<commit_after>package arel

type JoinSource struct {
	BinaryNode
}
<|endoftext|>


<commit_before>package bot

import (
	"strings"

	"github.com/fluffle/goirc/client"
)

// Handler is a callback used by plugins to receive command events.
type Handler func(e *Event)

// Event is given to a command's Handler when a command matched by name.
type Event struct {
	Bot    Bot
	Target string // Channel if public, nick if private.
	Args   string // Command args (excluding command name).
	Line   *client.Line
}

// Handle parses a line, matches with commands and dispatches to handler.
// A command can be triggered
//   - in public on a channel with: /msg #chan !cmd [args]
//     or directly at a bot: /msg #chan bot: cmd [args]
//     works also with a comma: /msg #chan bot, cmd [args]
//   - in private in a query: /msg bot cmd [args]
func (s *Commands) Handle(b Bot, line *client.Line) {
	words := strings.Split(line.Args[1], " ")
	var direct, indirect, private bool
	var target string

	if strings.HasPrefix(line.Args[0], "#") {
		target = line.Args[0]
		switch {
		case strings.HasPrefix(words[0], "!"):
			indirect = true
			words[0] = words[0][1:]

		case words[0] == b.Me().Nick+":" || words[0] == b.Me().Nick+",":
			direct = true
			words = words[1:]
			if len(words) < 1 {
				return
			}

		default:
			return // Not a command.
		}
	} else {
		private = true
		target = line.Nick
	}

	args := strings.Join(words[1:], " ")

	s.Lock()
	defer s.Unlock()

	if c, present := s.cmds[words[0]]; present {
		direct = direct && c.Pub
		indirect = indirect && c.Pub && !c.NoExclamation
		private = private && c.Priv
		if direct || indirect || private {
			go c.Handler(&Event{Bot: b, Line: line, Target: target, Args: args})
		}
	}
}
<commit_msg>Code flow update<commit_after>package bot

import (
	"strings"

	"github.com/fluffle/goirc/client"
)

// Handler is a callback used by plugins to receive command events.
type Handler func(e *Event)

// Event is given to a command's Handler when a command matched by name.
type Event struct {
	Bot    Bot
	Target string // Channel if public, nick if private.
	Args   string // Command args (excluding command name).
	Line   *client.Line
}

// Handle parses a line, matches with commands and dispatches to handler.
// A command can be triggered
//   - in public on a channel with: /msg #chan !cmd [args]
//     or directly at a bot: /msg #chan bot: cmd [args]
//     works also with a comma: /msg #chan bot, cmd [args]
//   - in private in a query: /msg bot cmd [args]
func (s *Commands) Handle(b Bot, line *client.Line) {
	words := strings.Split(line.Args[1], " ")
	var direct, indirect, private bool
	var target string

	if strings.HasPrefix(line.Args[0], "#") {
		target = line.Args[0]
		switch {
		case strings.HasPrefix(words[0], "!"):
			indirect = true
			words[0] = words[0][1:]

		case words[0] == b.Me().Nick+":" || words[0] == b.Me().Nick+",":
			direct = true
			words = words[1:]
			if len(words) < 1 {
				return
			}

		default:
			return // Not a command.
		}
	} else {
		private = true
		target = line.Nick
	}

	args := strings.Join(words[1:], " ")

	s.Lock()
	defer s.Unlock()

	c, present := s.cmds[words[0]]
	if !present {
		return
	}
	direct = direct && c.Pub
	indirect = indirect && c.Pub && !c.NoExclamation
	private = private && c.Priv
	if direct || indirect || private {
		go c.Handler(&Event{Bot: b, Line: line, Target: target, Args: args})
	}
}
<|endoftext|>