<commit_before>package aws

import (
	"fmt"
	"log"
	"strconv"
	"time"

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

func resource_aws_instance_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)
	delete(rs.Attributes, "source_dest_check")

	// Create the instance
	runOpts := &ec2.RunInstances{
		ImageId:      rs.Attributes["ami"],
		InstanceType: rs.Attributes["instance_type"],
		SubnetId:     rs.Attributes["subnet_id"],
	}
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return nil, 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
	rs.ID = 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,
	}

	instanceRaw, err := stateConf.WaitForState()

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

	instance = instanceRaw.(*ec2.Instance)

	// Set our attributes
	rs, err = resource_aws_instance_update_state(rs, instance)
	if err != nil {
		return rs, err
	}

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

func resource_aws_instance_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn
	rs := s.MergeDiff(d)

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

	if attr, ok := d.Attributes["source_dest_check"]; ok {
		modify = true
		opts.SourceDestCheck = attr.New != "" && attr.New != "false"
		opts.SetSourceDestCheck = true
		rs.Attributes["source_dest_check"] = strconv.FormatBool(
			opts.SourceDestCheck)
	}

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

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

	return rs, nil
}

func resource_aws_instance_destroy(
	s *terraform.ResourceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

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

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

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

	_, err := stateConf.WaitForState()

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

	return nil
}

func resource_aws_instance_diff(
	s *terraform.ResourceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.ResourceDiff, error) {
	b := &diff.ResourceBuilder{
		Attrs: map[string]diff.AttrType{
			"ami":               diff.AttrTypeCreate,
			"availability_zone": diff.AttrTypeCreate,
			"instance_type":     diff.AttrTypeCreate,
			"subnet_id":         diff.AttrTypeCreate,
			"source_dest_check": diff.AttrTypeUpdate,
		},

		ComputedAttrs: []string{
			"availability_zone",
			"public_dns",
			"public_ip",
			"private_dns",
			"private_ip",
		},
	}

	return b.Diff(s, c)
}

func resource_aws_instance_refresh(
	s *terraform.ResourceState,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	resp, err := ec2conn.Instances([]string{s.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" {
			return nil, nil
		}

		// Some other error, report it
		return s, err
	}

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

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

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

	return resource_aws_instance_update_state(s, instance)
}

func resource_aws_instance_update_state(
	s *terraform.ResourceState,
	instance *ec2.Instance) (*terraform.ResourceState, error) {
	s.Attributes["availability_zone"] = instance.AvailZone
	s.Attributes["public_dns"] = instance.DNSName
	s.Attributes["public_ip"] = instance.PublicIpAddress
	s.Attributes["private_dns"] = instance.PrivateDNSName
	s.Attributes["private_ip"] = instance.PrivateIpAddress
	s.Attributes["subnet_id"] = instance.SubnetId
	s.Dependencies = nil

	if instance.SubnetId != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: instance.SubnetId},
		)
	}

	return s, 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>providers/aws/aws_instance: key_name<commit_after>package aws

import (
	"fmt"
	"log"
	"strconv"
	"time"

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

func resource_aws_instance_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)
	delete(rs.Attributes, "source_dest_check")

	// Create the instance
	runOpts := &ec2.RunInstances{
		ImageId:      rs.Attributes["ami"],
		InstanceType: rs.Attributes["instance_type"],
		KeyName:      rs.Attributes["key_name"],
		SubnetId:     rs.Attributes["subnet_id"],
	}
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return nil, 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
	rs.ID = 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,
	}

	instanceRaw, err := stateConf.WaitForState()

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

	instance = instanceRaw.(*ec2.Instance)

	// Set our attributes
	rs, err = resource_aws_instance_update_state(rs, instance)
	if err != nil {
		return rs, err
	}

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

func resource_aws_instance_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn
	rs := s.MergeDiff(d)

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

	if attr, ok := d.Attributes["source_dest_check"]; ok {
		modify = true
		opts.SourceDestCheck = attr.New != "" && attr.New != "false"
		opts.SetSourceDestCheck = true
		rs.Attributes["source_dest_check"] = strconv.FormatBool(
			opts.SourceDestCheck)
	}

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

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

	return rs, nil
}

func resource_aws_instance_destroy(
	s *terraform.ResourceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

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

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

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

	_, err := stateConf.WaitForState()

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

	return nil
}

func resource_aws_instance_diff(
	s *terraform.ResourceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.ResourceDiff, error) {
	b := &diff.ResourceBuilder{
		Attrs: map[string]diff.AttrType{
			"ami":               diff.AttrTypeCreate,
			"availability_zone": diff.AttrTypeCreate,
			"instance_type":     diff.AttrTypeCreate,
			"key_name":          diff.AttrTypeCreate,
			"subnet_id":         diff.AttrTypeCreate,
			"source_dest_check": diff.AttrTypeUpdate,
		},

		ComputedAttrs: []string{
			"availability_zone",
			"public_dns",
			"public_ip",
			"private_dns",
			"private_ip",
		},
	}

	return b.Diff(s, c)
}

func resource_aws_instance_refresh(
	s *terraform.ResourceState,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	resp, err := ec2conn.Instances([]string{s.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" {
			return nil, nil
		}

		// Some other error, report it
		return s, err
	}

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

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

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

	return resource_aws_instance_update_state(s, instance)
}

func resource_aws_instance_update_state(
	s *terraform.ResourceState,
	instance *ec2.Instance) (*terraform.ResourceState, error) {
	s.Attributes["availability_zone"] = instance.AvailZone
	s.Attributes["key_name"] = instance.KeyName
	s.Attributes["public_dns"] = instance.DNSName
	s.Attributes["public_ip"] = instance.PublicIpAddress
	s.Attributes["private_dns"] = instance.PrivateDNSName
	s.Attributes["private_ip"] = instance.PrivateIpAddress
	s.Attributes["subnet_id"] = instance.SubnetId
	s.Dependencies = nil

	if instance.SubnetId != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: instance.SubnetId},
		)
	}

	return s, 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
	}
}
<|endoftext|>


<commit_before>//  Copyright (c) 2016 Couchbase, 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 moss

import (
	"math/big"

	"github.com/couchbase/moss"

	"github.com/blevesearch/bleve/index/store"
)

type Reader struct {
	store *Store
	ss    moss.Snapshot
}

func (r *Reader) Get(k []byte) (v []byte, err error) {
	v, err = r.ss.Get(k, moss.ReadOptions{})
	if err != nil {
		return nil, err
	}
	if v != nil {
		return append(make([]byte, 0, len(v)), v...), nil
	}
	return nil, nil
}

func (r *Reader) MultiGet(keys [][]byte) ([][]byte, error) {
	return store.MultiGet(r, keys)
}

var bigOne = big.NewInt(1)

func (r *Reader) PrefixIterator(k []byte) store.KVIterator {
	kEnd := big.NewInt(0).Add(big.NewInt(0).SetBytes(k), bigOne).Bytes()

	iter, err := r.ss.StartIterator(k, kEnd, moss.IteratorOptions{})
	if err != nil {
		return nil
	}

	rv := &Iterator{
		store: r.store,
		ss:    r.ss,
		iter:  iter,
		start: k,
		end:   kEnd,
	}

	rv.current()

	return rv
}

func (r *Reader) RangeIterator(start, end []byte) store.KVIterator {
	iter, err := r.ss.StartIterator(start, end, moss.IteratorOptions{})
	if err != nil {
		return nil
	}

	rv := &Iterator{
		store: r.store,
		ss:    r.ss,
		iter:  iter,
		start: start,
		end:   end,
	}

	rv.current()

	return rv
}

func (r *Reader) Close() error {
	return r.ss.Close()
}
<commit_msg>reuse incrementBytes() in moss KV store integration<commit_after>//  Copyright (c) 2016 Couchbase, 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 moss

import (
	"github.com/couchbase/moss"

	"github.com/blevesearch/bleve/index/store"
)

type Reader struct {
	store *Store
	ss    moss.Snapshot
}

func (r *Reader) Get(k []byte) (v []byte, err error) {
	v, err = r.ss.Get(k, moss.ReadOptions{})
	if err != nil {
		return nil, err
	}
	if v != nil {
		return append(make([]byte, 0, len(v)), v...), nil
	}
	return nil, nil
}

func (r *Reader) MultiGet(keys [][]byte) ([][]byte, error) {
	return store.MultiGet(r, keys)
}

func (r *Reader) PrefixIterator(k []byte) store.KVIterator {
	kEnd := incrementBytes(k)

	iter, err := r.ss.StartIterator(k, kEnd, moss.IteratorOptions{})
	if err != nil {
		return nil
	}

	rv := &Iterator{
		store: r.store,
		ss:    r.ss,
		iter:  iter,
		start: k,
		end:   kEnd,
	}

	rv.current()

	return rv
}

func (r *Reader) RangeIterator(start, end []byte) store.KVIterator {
	iter, err := r.ss.StartIterator(start, end, moss.IteratorOptions{})
	if err != nil {
		return nil
	}

	rv := &Iterator{
		store: r.store,
		ss:    r.ss,
		iter:  iter,
		start: start,
		end:   end,
	}

	rv.current()

	return rv
}

func (r *Reader) Close() error {
	return r.ss.Close()
}

func incrementBytes(in []byte) []byte {
	rv := make([]byte, len(in))
	copy(rv, in)
	for i := len(rv) - 1; i >= 0; i-- {
		rv[i] = rv[i] + 1
		if rv[i] != 0 {
			return rv // didn't overflow, so stop
		}
	}
	return nil // overflowed
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"
	"testing"
)

func BenchmarkInsertIntoMap_intkey_newkey(b *testing.B) {
	m := map[int]int{}
	for i := 0; i < b.N; i++ {
		m[i] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_intkey_singlekey(b *testing.B) {
	m := map[int]int{}
	for i := 0; i < b.N; i++ {
		m[0] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_stringkey_singlekey(b *testing.B) {
	m := map[string]int{}
	for i := 0; i < b.N; i++ {
		m["key"] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkMapLookup_1000_first(b *testing.B) {
	m := map[string]int{}
	for i := 0; i < 1000; i++ {
		m[fmt.Sprintf("key_%7d", i)] = i
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = m["key_000000"]
	}
}

func BenchmarkMapLookup_1000_last(b *testing.B) {
	m := map[string]int{}
	for i := 0; i < 1000; i++ {
		m[fmt.Sprintf("key_%7d", i)] = i
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = m["key_000999"]
	}
}

func BenchmarkMapIteration(b *testing.B) {
	m := map[string]int{}

	for i := 0; i < 1000; i++ {
		m[strconv.FormatInt(int64(i), 10)] = i
	}

	b.ResetTimer()
	var sum int
	for i := 0; i < b.N; i++ {
		for _, v := range m {
			sum += v
		}
		_ = sum
	}
}
<commit_msg>Added map insertion benchmarks; reset time after creation of maps<commit_after>package main

import (
	"fmt"
	"strconv"
	"testing"
)

func BenchmarkInsertIntoMap_intkey_newkey(b *testing.B) {
	m := map[int]int{}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m[i] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_intkey_singlekey_prealloc(b *testing.B) {
	m := make(map[int]int, b.N)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m[i] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_intkey_singlekey_prealloc_prepolutated(b *testing.B) {
	m := make(map[int]int, b.N)
	for i := 0; i < b.N; i++ {
		m[i] = i
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m[i] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_intkey_singlekey(b *testing.B) {
	m := map[int]int{}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m[0] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkInsertIntoMap_stringkey_singlekey(b *testing.B) {
	m := map[string]int{}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m["key"] = i
	}
	// fmt.Printf("Length of map: %d\n", len(m))
}

func BenchmarkMapLookup_1000_first(b *testing.B) {
	m := map[string]int{}
	for i := 0; i < 1000; i++ {
		m[fmt.Sprintf("key_%7d", i)] = i
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = m["key_000000"]
	}
}

func BenchmarkMapLookup_1000_last(b *testing.B) {
	m := map[string]int{}
	for i := 0; i < 1000; i++ {
		m[fmt.Sprintf("key_%7d", i)] = i
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = m["key_000999"]
	}
}

func BenchmarkMapIteration(b *testing.B) {
	m := map[string]int{}

	for i := 0; i < 1000; i++ {
		m[strconv.FormatInt(int64(i), 10)] = i
	}

	b.ResetTimer()
	var sum int
	for i := 0; i < b.N; i++ {
		for _, v := range m {
			sum += v
		}
		_ = sum
	}
}
<|endoftext|>


<commit_before>package arn

import (
	"errors"
	"time"
)

// AnimeList ...
type AnimeList struct {
	UserID string           `json:"userId"`
	Items  []*AnimeListItem `json:"items"`
}

// Add adds an anime to the list if it hasn't been added yet.
func (list *AnimeList) Add(id interface{}) error {
	animeID := id.(string)

	if list.Contains(animeID) {
		return errors.New("Anime " + animeID + " has already been added")
	}

	creationDate := time.Now().UTC().Format(time.RFC3339)

	newItem := &AnimeListItem{
		AnimeID: animeID,
		Status:  AnimeListStatusPlanned,
		Created: creationDate,
		Edited:  creationDate,
	}

	list.Items = append(list.Items, newItem)

	return nil
}

// Remove removes the anime ID from the list.
func (list *AnimeList) Remove(id interface{}) bool {
	animeID := id.(string)

	for index, item := range list.Items {
		if item.AnimeID == animeID {
			list.Items = append(list.Items[:index], list.Items[index+1:]...)
			return true
		}
	}

	return false
}

// Contains checks if the list contains the anime ID already.
func (list *AnimeList) Contains(id interface{}) bool {
	animeID := id.(string)

	for _, item := range list.Items {
		if item.AnimeID == animeID {
			return true
		}
	}

	return false
}

// Find returns the list item with the specified anime ID, if available.
func (list *AnimeList) Find(animeID string) *AnimeListItem {
	for _, item := range list.Items {
		if item.AnimeID == animeID {
			return item
		}
	}

	return nil
}

// TransformBody returns an item that is passed to methods like Add, Remove, etc.
func (list *AnimeList) TransformBody(body []byte) interface{} {
	return string(body)
}

// Save saves the anime list in the database.
func (list *AnimeList) Save() error {
	return DB.Set("AnimeList", list.UserID, list)
}

// GetAnimeList ...
func GetAnimeList(userID string) (*AnimeList, error) {
	obj, err := DB.Get("AnimeList", userID)
	return obj.(*AnimeList), err
}
<commit_msg>Added animeList.User()<commit_after>package arn

import (
	"errors"
	"time"
)

// AnimeList ...
type AnimeList struct {
	UserID string           `json:"userId"`
	Items  []*AnimeListItem `json:"items"`

	user *User
}

// Add adds an anime to the list if it hasn't been added yet.
func (list *AnimeList) Add(id interface{}) error {
	animeID := id.(string)

	if list.Contains(animeID) {
		return errors.New("Anime " + animeID + " has already been added")
	}

	creationDate := time.Now().UTC().Format(time.RFC3339)

	newItem := &AnimeListItem{
		AnimeID: animeID,
		Status:  AnimeListStatusPlanned,
		Created: creationDate,
		Edited:  creationDate,
	}

	list.Items = append(list.Items, newItem)

	return nil
}

// Remove removes the anime ID from the list.
func (list *AnimeList) Remove(id interface{}) bool {
	animeID := id.(string)

	for index, item := range list.Items {
		if item.AnimeID == animeID {
			list.Items = append(list.Items[:index], list.Items[index+1:]...)
			return true
		}
	}

	return false
}

// Contains checks if the list contains the anime ID already.
func (list *AnimeList) Contains(id interface{}) bool {
	animeID := id.(string)

	for _, item := range list.Items {
		if item.AnimeID == animeID {
			return true
		}
	}

	return false
}

// Find returns the list item with the specified anime ID, if available.
func (list *AnimeList) Find(animeID string) *AnimeListItem {
	for _, item := range list.Items {
		if item.AnimeID == animeID {
			return item
		}
	}

	return nil
}

// User returns the user this anime list belongs to.
func (list *AnimeList) User() *User {
	if list.user == nil {
		list.user, _ = GetUser(list.UserID)
	}

	return list.user
}

// TransformBody returns an item that is passed to methods like Add, Remove, etc.
func (list *AnimeList) TransformBody(body []byte) interface{} {
	return string(body)
}

// Save saves the anime list in the database.
func (list *AnimeList) Save() error {
	return DB.Set("AnimeList", list.UserID, list)
}

// GetAnimeList ...
func GetAnimeList(userID string) (*AnimeList, error) {
	obj, err := DB.Get("AnimeList", userID)
	return obj.(*AnimeList), err
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package route53

import (
	"bytes"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/golang/glog"
	"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)

// Compile time check for interface adherence
var _ dnsprovider.ResourceRecordChangeset = &ResourceRecordChangeset{}

type ResourceRecordChangeset struct {
	zone   *Zone
	rrsets *ResourceRecordSets

	additions []dnsprovider.ResourceRecordSet
	removals  []dnsprovider.ResourceRecordSet
	upserts   []dnsprovider.ResourceRecordSet
}

func (c *ResourceRecordChangeset) Add(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.additions = append(c.additions, rrset)
	return c
}

func (c *ResourceRecordChangeset) Remove(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.removals = append(c.removals, rrset)
	return c
}

func (c *ResourceRecordChangeset) Upsert(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.upserts = append(c.upserts, rrset)
	return c
}

// buildChange converts a dnsprovider.ResourceRecordSet to a route53.Change request
func buildChange(action string, rrs dnsprovider.ResourceRecordSet) *route53.Change {
	change := &route53.Change{
		Action: aws.String(action),
		ResourceRecordSet: &route53.ResourceRecordSet{
			Name: aws.String(rrs.Name()),
			Type: aws.String(string(rrs.Type())),
			TTL:  aws.Int64(rrs.Ttl()),
		},
	}

	for _, rrdata := range rrs.Rrdatas() {
		rr := &route53.ResourceRecord{
			Value: aws.String(rrdata),
		}
		change.ResourceRecordSet.ResourceRecords = append(change.ResourceRecordSet.ResourceRecords, rr)
	}
	return change
}

func (c *ResourceRecordChangeset) Apply() error {
	hostedZoneID := c.zone.impl.Id

	var changes []*route53.Change

	for _, removal := range c.removals {
		change := buildChange(route53.ChangeActionDelete, removal)
		changes = append(changes, change)
	}

	for _, addition := range c.additions {
		change := buildChange(route53.ChangeActionCreate, addition)
		changes = append(changes, change)
	}

	for _, upsert := range c.upserts {
		change := buildChange(route53.ChangeActionUpsert, upsert)
		changes = append(changes, change)
	}

	if len(changes) == 0 {
		return nil
	}

	if glog.V(8) {
		var sb bytes.Buffer
		for _, change := range changes {
			sb.WriteString(fmt.Sprintf("\t%s %s %s\n", aws.StringValue(change.Action), aws.StringValue(change.ResourceRecordSet.Type), aws.StringValue(change.ResourceRecordSet.Name)))
		}

		glog.V(8).Infof("Route53 Changeset:\n%s", sb.String())
	}

	service := c.zone.zones.interface_.service

	request := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: changes,
		},
		HostedZoneId: hostedZoneID,
	}

	_, err := service.ChangeResourceRecordSets(request)
	if err != nil {
		// Cast err to awserr.Error to get the Code and
		// Message from an error.
		return err
	}
	return nil
}

func (c *ResourceRecordChangeset) IsEmpty() bool {
	return len(c.removals) == 0 && len(c.additions) == 0 && len(c.upserts) == 0
}

// ResourceRecordSets returns the parent ResourceRecordSets
func (c *ResourceRecordChangeset) ResourceRecordSets() dnsprovider.ResourceRecordSets {
	return c.rrsets
}
<commit_msg>Batch route53 requests to stay under the route53 limit<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package route53

import (
	"bytes"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/golang/glog"
	"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)

// Compile time check for interface adherence
var _ dnsprovider.ResourceRecordChangeset = &ResourceRecordChangeset{}

type ResourceRecordChangeset struct {
	zone   *Zone
	rrsets *ResourceRecordSets

	additions []dnsprovider.ResourceRecordSet
	removals  []dnsprovider.ResourceRecordSet
	upserts   []dnsprovider.ResourceRecordSet
}

func (c *ResourceRecordChangeset) Add(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.additions = append(c.additions, rrset)
	return c
}

func (c *ResourceRecordChangeset) Remove(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.removals = append(c.removals, rrset)
	return c
}

func (c *ResourceRecordChangeset) Upsert(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
	c.upserts = append(c.upserts, rrset)
	return c
}

// buildChange converts a dnsprovider.ResourceRecordSet to a route53.Change request
func buildChange(action string, rrs dnsprovider.ResourceRecordSet) *route53.Change {
	change := &route53.Change{
		Action: aws.String(action),
		ResourceRecordSet: &route53.ResourceRecordSet{
			Name: aws.String(rrs.Name()),
			Type: aws.String(string(rrs.Type())),
			TTL:  aws.Int64(rrs.Ttl()),
		},
	}

	for _, rrdata := range rrs.Rrdatas() {
		rr := &route53.ResourceRecord{
			Value: aws.String(rrdata),
		}
		change.ResourceRecordSet.ResourceRecords = append(change.ResourceRecordSet.ResourceRecords, rr)
	}
	return change
}

func (c *ResourceRecordChangeset) Apply() error {
	hostedZoneID := c.zone.impl.Id

	removals := make(map[string]*route53.Change)
	for _, removal := range c.removals {
		removals[string(removal.Type())+"::"+removal.Name()] = buildChange(route53.ChangeActionDelete, removal)
	}

	additions := make(map[string]*route53.Change)
	for _, addition := range c.additions {
		additions[string(addition.Type())+"::"+addition.Name()] = buildChange(route53.ChangeActionCreate, addition)
	}

	upserts := make(map[string]*route53.Change)
	for _, upsert := range c.upserts {
		upserts[string(upsert.Type())+"::"+upsert.Name()] = buildChange(route53.ChangeActionUpsert, upsert)
	}

	doneKeys := make(map[string]bool)

	keys := make(map[string]bool)
	for k := range removals {
		keys[k] = true
	}
	for k := range additions {
		keys[k] = true
	}
	for k := range upserts {
		keys[k] = true
	}

	for {
		// Limit batch size
		maxBatchSize := 900

		var batch []*route53.Change
		// We group the changes so that changes with the same key are in the same batch
		for k := range keys {
			if doneKeys[k] {
				continue
			}

			if len(batch)+3 >= maxBatchSize {
				break
			}

			if change := removals[k]; change != nil {
				batch = append(batch, change)
			}
			if change := additions[k]; change != nil {
				batch = append(batch, change)
			}
			if change := upserts[k]; change != nil {
				batch = append(batch, change)
			}
			doneKeys[k] = true
		}

		if len(batch) == 0 {
			// Nothing left to do
			break
		}

		if glog.V(8) {
			var sb bytes.Buffer
			for _, change := range batch {
				sb.WriteString(fmt.Sprintf("\t%s %s %s\n", aws.StringValue(change.Action), aws.StringValue(change.ResourceRecordSet.Type), aws.StringValue(change.ResourceRecordSet.Name)))
			}

			glog.V(8).Infof("Route53 Changeset:\n%s", sb.String())
		}

		service := c.zone.zones.interface_.service

		request := &route53.ChangeResourceRecordSetsInput{
			ChangeBatch: &route53.ChangeBatch{
				Changes: batch,
			},
			HostedZoneId: hostedZoneID,
		}

		// The aws-sdk-go does backoff for PriorRequestNotComplete
		_, err := service.ChangeResourceRecordSets(request)
		if err != nil {
			// Cast err to awserr.Error to get the Code and
			// Message from an error.
			return err
		}
	}

	return nil
}

func (c *ResourceRecordChangeset) IsEmpty() bool {
	return len(c.removals) == 0 && len(c.additions) == 0 && len(c.upserts) == 0
}

// ResourceRecordSets returns the parent ResourceRecordSets
func (c *ResourceRecordChangeset) ResourceRecordSets() dnsprovider.ResourceRecordSets {
	return c.rrsets
}
<|endoftext|>


<commit_before>// ATM - Automatic TempUrl Maker
// A builder of Swift TempURLs
// Copyright (c) 2015 Stuart Glenn
// All rights reserved
// Use of this source code is goverened by a BSD 3-clause license,
// see included LICENSE file for details
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os/user"

	_ "github.com/go-sql-driver/mysql"

	"github.com/glennsb/atm"
	"github.com/howeyc/gopass"
	"github.com/labstack/echo"
	mw "github.com/labstack/echo/middleware"
)

const (
	HOST     = "https://o3.omrf.org"
	DURATION = int64(300)
)

var (
	Key              string
	Database         string
	Database_host    string
	Database_user    string
	Database_pass    string
	Database_port    int
	Default_duration int64
	Object_host      string
	ds               *atm.Datastore
)

func init() {
	current_user, _ := user.Current()
	Database_user = current_user.Username
	parseFlags()

	fmt.Printf("%s@%s/%s password: ", Database_user, Database_host, Database)
	Database_pass = string(gopass.GetPasswd())
}

func parseFlags() {
	flag.StringVar(&Database, "database", "atm", "Database name")
	flag.StringVar(&Database_host, "database-host", "localhost", "Database server hostname")
	flag.IntVar(&Database_port, "database-port", 3306, "Database server port")
	flag.StringVar(&Database_user, "database-user", Database_user, "Username for database")
	flag.Int64Var(&Default_duration, "duration", DURATION, "Default lifetime of tempurl")
	flag.StringVar(&Object_host, "host", HOST, "Swift host prefix")

	flag.Parse()
}

func main() {
	var err error
	ds, err = atm.NewDatastore("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s",
		Database_user, Database_pass, Database_host,
		Database_port, Database))
	if nil != err {
		log.Fatal(err)
	}
	Database_pass = ""
	defer ds.Close()

	e := echo.New()

	// Middleware
	e.Use(mw.Logger())
	e.Use(mw.Recover())

	e.Post("/urls", createUrl)
	e.Put("/keys/:name", setKey)
	e.Run(":8080")
}

type keyRequest struct {
	Key string `json:key`
}

func setKey(c *echo.Context) error {
	k := &keyRequest{}
	if err := c.Bind(k); nil != err {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg(err.Error()))
	}
	a, err := ds.Account(c.Param("name"))
	if nil != err || a.Id == "" {
		return c.JSON(http.StatusGone, atm.ErrMsg(http.StatusText(http.StatusNotFound)))
	}
	ds.AddSigningKeyForAccount(k.Key, a.Id)
	return c.JSON(http.StatusOK, a)
}

func createUrl(c *echo.Context) error {
	o := &atm.UrlRequest{Host: Object_host, Duration: Default_duration}
	if err := c.Bind(o); nil != err {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg(err.Error()))
	}

	if !o.Valid() {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg("Missing account, container, object, or method"))
	}

	duration := int64(0)
	var err error
	o.Key, duration, err = ds.KeyForRequest(o, "a8c0dbfa-45d8-49a9-a7e2-194dee1a78c2")
	if nil != err {
		log.Printf("keyForRequest: %v, %s. Error: %s", o, "", err.Error())
		return c.JSON(http.StatusInternalServerError, atm.ErrMsg("Trouble checking authorization"))
	}
	if "" == o.Key {
		return c.JSON(http.StatusForbidden, atm.ErrMsg("Not authorized for this resource"))
	}
	if duration > 0 && duration > o.Duration {
		o.Duration = duration
	}

	u := &atm.Tmpurl{
		Url:  o.SignedUrl(),
		Path: o.Path(),
	}

	c.Response().Header().Set("Location", u.Url)
	return c.JSON(http.StatusCreated, u)
}
<commit_msg>Remove hard coded testing requestor id<commit_after>// ATM - Automatic TempUrl Maker
// A builder of Swift TempURLs
// Copyright (c) 2015 Stuart Glenn
// All rights reserved
// Use of this source code is goverened by a BSD 3-clause license,
// see included LICENSE file for details
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os/user"

	_ "github.com/go-sql-driver/mysql"

	"github.com/glennsb/atm"
	"github.com/howeyc/gopass"
	"github.com/labstack/echo"
	mw "github.com/labstack/echo/middleware"
)

const (
	HOST     = "https://o3.omrf.org"
	DURATION = int64(300)
)

var (
	Key              string
	Database         string
	Database_host    string
	Database_user    string
	Database_pass    string
	Database_port    int
	Default_duration int64
	Object_host      string
	ds               *atm.Datastore
)

func init() {
	current_user, _ := user.Current()
	Database_user = current_user.Username
	parseFlags()

	fmt.Printf("%s@%s/%s password: ", Database_user, Database_host, Database)
	Database_pass = string(gopass.GetPasswd())
}

func parseFlags() {
	flag.StringVar(&Database, "database", "atm", "Database name")
	flag.StringVar(&Database_host, "database-host", "localhost", "Database server hostname")
	flag.IntVar(&Database_port, "database-port", 3306, "Database server port")
	flag.StringVar(&Database_user, "database-user", Database_user, "Username for database")
	flag.Int64Var(&Default_duration, "duration", DURATION, "Default lifetime of tempurl")
	flag.StringVar(&Object_host, "host", HOST, "Swift host prefix")

	flag.Parse()
}

func main() {
	var err error
	ds, err = atm.NewDatastore("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s",
		Database_user, Database_pass, Database_host,
		Database_port, Database))
	if nil != err {
		log.Fatal(err)
	}
	Database_pass = ""
	defer ds.Close()

	e := echo.New()

	// Middleware
	e.Use(mw.Logger())
	e.Use(mw.Recover())

	e.Post("/urls", createUrl)
	e.Put("/keys/:name", setKey)
	e.Run(":8080")
}

type keyRequest struct {
	Key string `json:key`
}

func setKey(c *echo.Context) error {
	k := &keyRequest{}
	if err := c.Bind(k); nil != err {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg(err.Error()))
	}
	a, err := ds.Account(c.Param("name"))
	if nil != err || a.Id == "" {
		return c.JSON(http.StatusGone, atm.ErrMsg(http.StatusText(http.StatusNotFound)))
	}
	ds.AddSigningKeyForAccount(k.Key, a.Id)
	return c.JSON(http.StatusOK, a)
}

func createUrl(c *echo.Context) error {
	o := &atm.UrlRequest{Host: Object_host, Duration: Default_duration}
	if err := c.Bind(o); nil != err {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg(err.Error()))
	}

	if !o.Valid() {
		return c.JSON(http.StatusBadRequest, atm.ErrMsg("Missing account, container, object, or method"))
	}

	duration := int64(0)
	var err error
	o.Key, duration, err = ds.KeyForRequest(o, c.Request().Header.Get("authorization"))
	if nil != err {
		log.Printf("keyForRequest: %v, %s. Error: %s", o, "", err.Error())
		return c.JSON(http.StatusInternalServerError, atm.ErrMsg("Trouble checking authorization"))
	}
	if "" == o.Key {
		return c.JSON(http.StatusForbidden, atm.ErrMsg("Not authorized for this resource"))
	}
	if duration > 0 && duration > o.Duration {
		o.Duration = duration
	}

	u := &atm.Tmpurl{
		Url:  o.SignedUrl(),
		Path: o.Path(),
	}

	c.Response().Header().Set("Location", u.Url)
	return c.JSON(http.StatusCreated, u)
}
<|endoftext|>


<commit_before>package docker

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"

	"github.com/hashicorp/go-version"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type DockerDriver struct {
	Ui  packer.Ui
	Ctx *interpolate.Context

	l sync.Mutex
}

func (d *DockerDriver) DeleteImage(id string) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "rmi", id)
	cmd.Stderr = &stderr

	log.Printf("Deleting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error deleting image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Commit(id string, author string, changes []string, message string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer

	args := []string{"commit"}
	if author != "" {
		args = append(args, "--author", author)
	}
	for _, change := range changes {
		args = append(args, "--change", change)
	}
	if message != "" {
		args = append(args, "--message", message)
	}
	args = append(args, id)

	log.Printf("Committing container with args: %v", args)
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error committing container: %s\nStderr: %s",
			err, stderr.String())
		return "", err
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Export(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "export", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting container: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Import(path string, repo string) (string, error) {
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", "import", "-", repo)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return "", err
	}

	// There should be only one artifact of the Docker builder
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	if err := cmd.Start(); err != nil {
		return "", err
	}

	go func() {
		defer stdin.Close()
		io.Copy(stdin, file)
	}()

	if err := cmd.Wait(); err != nil {
		return "", fmt.Errorf("Error importing container: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) IPAddress(id string) (string, error) {
	var stderr, stdout bytes.Buffer
	cmd := exec.Command(
		"docker",
		"inspect",
		"--format",
		"{{ .NetworkSettings.IPAddress }}",
		id)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Login(repo, user, pass string) error {
	d.l.Lock()

	version_running, err := d.Version()
	if err != nil {
		d.l.Unlock()
		return err
	}

	// Version 17.07.0 of Docker adds support for the new
	// `--password-stdin` option which can be used to offer
	// password via the standard input, rather than passing
	// the password and/or token using a command line switch.
	constraint, err := version.NewConstraint(">= 17.07.0")
	if err != nil {
		d.l.Unlock()
		return err
	}

	cmd := exec.Command("docker")
	cmd.Args = append(cmd.Args, "login")

	if user != "" {
		cmd.Args = append(cmd.Args, "-u", user)
	}

	if pass != "" {
		if constraint.Check(version_running) {
			cmd.Args = append(cmd.Args, "--password-stdin")

			stdin, err := cmd.StdinPipe()
			if err != nil {
				d.l.Unlock()
				return err
			}
			io.WriteString(stdin, pass)
			stdin.Close()
		} else {
			cmd.Args = append(cmd.Args, "-p", pass)
		}
	}

	if repo != "" {
		cmd.Args = append(cmd.Args, repo)
	}

	err = runAndStream(cmd, d.Ui)
	if err != nil {
		d.l.Unlock()
		return err
	}

	return nil
}

func (d *DockerDriver) Logout(repo string) error {
	args := []string{"logout"}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	d.l.Unlock()
	return err
}

func (d *DockerDriver) Pull(image string) error {
	cmd := exec.Command("docker", "pull", image)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) Push(name string) error {
	cmd := exec.Command("docker", "push", name)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) SaveImage(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "save", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
	// Build up the template data
	var tplData startContainerTemplate
	tplData.Image = config.Image
	ctx := *d.Ctx
	ctx.Data = &tplData

	// Args that we're going to pass to Docker
	args := []string{"run"}
	if config.Privileged {
		args = append(args, "--privileged")
	}
	for host, guest := range config.Volumes {
		if runtime.GOOS == "windows" {
			// docker-toolbox can't handle the normal C:\filepath format in CLI
			host = strings.Replace(host, "\\", "/", -1)
			host = strings.Replace(host, "C:/", "/c/", 1)
		}
		args = append(args, "-v", fmt.Sprintf("%s:%s", host, guest))
	}
	for _, v := range config.RunCommand {
		v, err := interpolate.Render(v, &ctx)
		if err != nil {
			return "", err
		}

		args = append(args, v)
	}
	d.Ui.Message(fmt.Sprintf(
		"Run command: docker %s", strings.Join(args, " ")))

	// Start the container
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	log.Printf("Starting container with args: %v", args)
	if err := cmd.Start(); err != nil {
		return "", err
	}

	log.Println("Waiting for container to finish starting")
	if err := cmd.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			err = fmt.Errorf("Docker exited with a non-zero exit status.\nStderr: %s",
				stderr.String())
		}

		return "", err
	}

	// Capture the container ID, which is alone on stdout
	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) StopContainer(id string) error {
	if err := exec.Command("docker", "kill", id).Run(); err != nil {
		return err
	}

	return exec.Command("docker", "rm", id).Run()
}

func (d *DockerDriver) TagImage(id string, repo string, force bool) error {
	args := []string{"tag"}

	// detect running docker version before tagging
	// flag `force` for docker tagging was removed after Docker 1.12.0
	// to keep its backward compatibility, we are not going to remove `force`
	// option, but to ignore it when Docker version >= 1.12.0
	//
	// for more detail, please refer to the following links:
	// - https://docs.docker.com/engine/deprecated/#/f-flag-on-docker-tag
	// - https://github.com/docker/docker/pull/23090
	version_running, err := d.Version()
	if err != nil {
		return err
	}

	version_deprecated, err := version.NewVersion("1.12.0")
	if err != nil {
		// should never reach this line
		return err
	}

	if force {
		if version_running.LessThan(version_deprecated) {
			args = append(args, "-f")
		} else {
			// do nothing if Docker version >= 1.12.0
			log.Printf("[WARN] option: \"force\" will be ignored here")
			log.Printf("since it was removed after Docker 1.12.0 released")
		}
	}
	args = append(args, id, repo)

	var stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stderr = &stderr

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

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error tagging image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Verify() error {
	if _, err := exec.LookPath("docker"); err != nil {
		return err
	}

	return nil
}

func (d *DockerDriver) Version() (*version.Version, error) {
	output, err := exec.Command("docker", "-v").Output()
	if err != nil {
		return nil, err
	}

	match := regexp.MustCompile(version.VersionRegexpRaw).FindSubmatch(output)
	if match == nil {
		return nil, fmt.Errorf("unknown version: %s", output)
	}

	return version.NewVersion(string(match[0]))
}
<commit_msg>Add changes var to docker driver import func.<commit_after>package docker

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"

	"github.com/hashicorp/go-version"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type DockerDriver struct {
	Ui  packer.Ui
	Ctx *interpolate.Context

	l sync.Mutex
}

func (d *DockerDriver) DeleteImage(id string) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "rmi", id)
	cmd.Stderr = &stderr

	log.Printf("Deleting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error deleting image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Commit(id string, author string, changes []string, message string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer

	args := []string{"commit"}
	if author != "" {
		args = append(args, "--author", author)
	}
	for _, change := range changes {
		args = append(args, "--change", change)
	}
	if message != "" {
		args = append(args, "--message", message)
	}
	args = append(args, id)

	log.Printf("Committing container with args: %v", args)
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error committing container: %s\nStderr: %s",
			err, stderr.String())
		return "", err
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Export(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "export", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting container: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Import(path string, changes []string, repo string) (string, error) {
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	stdin, err := cmd.StdinPipe()

  if err != nil {
		return "", err
	}

	args := []string{"import"}

  for _, change := range changes {
    args = append(args, "--change", change)
  }

  args = append(args, "-")
	args = append(args, repo)
  cmd := exec.Command("docker", args...)

	// There should be only one artifact of the Docker builder
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

  log.Printf("Importing container with args: %v", args)

	if err := cmd.Start(); err != nil {
		return "", err
	}

	go func() {
		defer stdin.Close()
		io.Copy(stdin, file)
	}()

	if err := cmd.Wait(); err != nil {
		return "", fmt.Errorf("Error importing container: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) IPAddress(id string) (string, error) {
	var stderr, stdout bytes.Buffer
	cmd := exec.Command(
		"docker",
		"inspect",
		"--format",
		"{{ .NetworkSettings.IPAddress }}",
		id)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Login(repo, user, pass string) error {
	d.l.Lock()

	version_running, err := d.Version()
	if err != nil {
		d.l.Unlock()
		return err
	}

	// Version 17.07.0 of Docker adds support for the new
	// `--password-stdin` option which can be used to offer
	// password via the standard input, rather than passing
	// the password and/or token using a command line switch.
	constraint, err := version.NewConstraint(">= 17.07.0")
	if err != nil {
		d.l.Unlock()
		return err
	}

	cmd := exec.Command("docker")
	cmd.Args = append(cmd.Args, "login")

	if user != "" {
		cmd.Args = append(cmd.Args, "-u", user)
	}

	if pass != "" {
		if constraint.Check(version_running) {
			cmd.Args = append(cmd.Args, "--password-stdin")

			stdin, err := cmd.StdinPipe()
			if err != nil {
				d.l.Unlock()
				return err
			}
			io.WriteString(stdin, pass)
			stdin.Close()
		} else {
			cmd.Args = append(cmd.Args, "-p", pass)
		}
	}

	if repo != "" {
		cmd.Args = append(cmd.Args, repo)
	}

	err = runAndStream(cmd, d.Ui)
	if err != nil {
		d.l.Unlock()
		return err
	}

	return nil
}

func (d *DockerDriver) Logout(repo string) error {
	args := []string{"logout"}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	d.l.Unlock()
	return err
}

func (d *DockerDriver) Pull(image string) error {
	cmd := exec.Command("docker", "pull", image)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) Push(name string) error {
	cmd := exec.Command("docker", "push", name)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) SaveImage(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "save", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
	// Build up the template data
	var tplData startContainerTemplate
	tplData.Image = config.Image
	ctx := *d.Ctx
	ctx.Data = &tplData

	// Args that we're going to pass to Docker
	args := []string{"run"}
	if config.Privileged {
		args = append(args, "--privileged")
	}
	for host, guest := range config.Volumes {
		if runtime.GOOS == "windows" {
			// docker-toolbox can't handle the normal C:\filepath format in CLI
			host = strings.Replace(host, "\\", "/", -1)
			host = strings.Replace(host, "C:/", "/c/", 1)
		}
		args = append(args, "-v", fmt.Sprintf("%s:%s", host, guest))
	}
	for _, v := range config.RunCommand {
		v, err := interpolate.Render(v, &ctx)
		if err != nil {
			return "", err
		}

		args = append(args, v)
	}
	d.Ui.Message(fmt.Sprintf(
		"Run command: docker %s", strings.Join(args, " ")))

	// Start the container
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	log.Printf("Starting container with args: %v", args)
	if err := cmd.Start(); err != nil {
		return "", err
	}

	log.Println("Waiting for container to finish starting")
	if err := cmd.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			err = fmt.Errorf("Docker exited with a non-zero exit status.\nStderr: %s",
				stderr.String())
		}

		return "", err
	}

	// Capture the container ID, which is alone on stdout
	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) StopContainer(id string) error {
	if err := exec.Command("docker", "kill", id).Run(); err != nil {
		return err
	}

	return exec.Command("docker", "rm", id).Run()
}

func (d *DockerDriver) TagImage(id string, repo string, force bool) error {
	args := []string{"tag"}

	// detect running docker version before tagging
	// flag `force` for docker tagging was removed after Docker 1.12.0
	// to keep its backward compatibility, we are not going to remove `force`
	// option, but to ignore it when Docker version >= 1.12.0
	//
	// for more detail, please refer to the following links:
	// - https://docs.docker.com/engine/deprecated/#/f-flag-on-docker-tag
	// - https://github.com/docker/docker/pull/23090
	version_running, err := d.Version()
	if err != nil {
		return err
	}

	version_deprecated, err := version.NewVersion("1.12.0")
	if err != nil {
		// should never reach this line
		return err
	}

	if force {
		if version_running.LessThan(version_deprecated) {
			args = append(args, "-f")
		} else {
			// do nothing if Docker version >= 1.12.0
			log.Printf("[WARN] option: \"force\" will be ignored here")
			log.Printf("since it was removed after Docker 1.12.0 released")
		}
	}
	args = append(args, id, repo)

	var stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stderr = &stderr

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

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error tagging image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Verify() error {
	if _, err := exec.LookPath("docker"); err != nil {
		return err
	}

	return nil
}

func (d *DockerDriver) Version() (*version.Version, error) {
	output, err := exec.Command("docker", "-v").Output()
	if err != nil {
		return nil, err
	}

	match := regexp.MustCompile(version.VersionRegexpRaw).FindSubmatch(output)
	if match == nil {
		return nil, fmt.Errorf("unknown version: %s", output)
	}

	return version.NewVersion(string(match[0]))
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"runtime"
	"strconv"
	"strings"

	"github.com/mitchellh/multistep"
)

// A driver is able to talk to VMware, control virtual machines, etc.
type Driver interface {
	// Clone clones the VMX and the disk to the destination path. The
	// destination is a path to the VMX file. The disk will be copied
	// to that same directory.
	Clone(dst string, src string) error

	// CompactDisk compacts a virtual disk.
	CompactDisk(string) error

	// CreateDisk creates a virtual disk with the given size.
	CreateDisk(string, string, string) error

	// Checks if the VMX file at the given path is running.
	IsRunning(string) (bool, error)

	// CommHost returns the host address for the VM that is being
	// managed by this driver.
	CommHost(multistep.StateBag) (string, error)

	// Start starts a VM specified by the path to the VMX given.
	Start(string, bool) error

	// Stop stops a VM specified by the path to the VMX given.
	Stop(string) error

	// SuppressMessages modifies the VMX or surrounding directory so that
	// VMware doesn't show any annoying messages.
	SuppressMessages(string) error

	// Get the path to the VMware ISO for the given flavor.
	ToolsIsoPath(string) string

	// Attach the VMware tools ISO
	ToolsInstall() error

	// Get the path to the DHCP leases file for the given device.
	DhcpLeasesPath(string) string

	// Verify checks to make sure that this driver should function
	// properly. This should check that all the files it will use
	// appear to exist and so on. If everything is okay, this doesn't
	// return an error. Otherwise, this returns an error.
	Verify() error
}

// NewDriver returns a new driver implementation for this operating
// system, or an error if the driver couldn't be initialized.
func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) {
	drivers := []Driver{}

	switch runtime.GOOS {
	case "darwin":
		drivers = []Driver{
			&Fusion6Driver{
				Fusion5Driver: Fusion5Driver{
					AppPath:   dconfig.FusionAppPath,
					SSHConfig: config,
				},
			},
			&Fusion5Driver{
				AppPath:   dconfig.FusionAppPath,
				SSHConfig: config,
			},
		}
	case "linux":
		fallthrough
	case "windows":
		drivers = []Driver{
			&Workstation10Driver{
				Workstation9Driver: Workstation9Driver{
					SSHConfig: config,
				},
			},
			&Workstation9Driver{
				SSHConfig: config,
			},
			&Player6Driver{
				Player5Driver: Player5Driver{
					SSHConfig: config,
				},
			},
			&Player5Driver{
				SSHConfig: config,
			},
		}
	default:
		return nil, fmt.Errorf("can't find driver for OS: %s", runtime.GOOS)
	}

	errs := ""
	for _, driver := range drivers {
		err := driver.Verify()
		if err == nil {
			return driver, nil
		}
		errs += "* " + err.Error() + "\n"
	}

	return nil, fmt.Errorf(
		"Unable to initialize any driver for this platform. The errors\n"+
			"from each driver are shown below. Please fix at least one driver\n"+
			"to continue:\n%s", errs)
}

func runAndLog(cmd *exec.Cmd) (string, string, error) {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:])
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		message := stderrString
		if message == "" {
			message = stdoutString
		}

		err = fmt.Errorf("VMware error: %s", message)

		// If "unknown error" is in there, add some additional notes
		re := regexp.MustCompile(`(?i)unknown error`)
		if re.MatchString(message) {
			err = fmt.Errorf(
				"%s\n\n%s", err,
				"Packer detected a VMware 'Unknown Error'. Unfortunately VMware\n"+
					"often has extremely vague error messages such as this and Packer\n"+
					"itself can't do much about that. Please check the vmware.log files\n"+
					"created by VMware when a VM is started (in the directory of the\n"+
					"vmx file), which often contains more detailed error information.")
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	// Replace these for Windows, we only want to deal with Unix
	// style line endings.
	returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1)
	returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1)

	return returnStdout, returnStderr, err
}

func normalizeVersion(version string) (string, error) {
	i, err := strconv.Atoi(version)
	if err != nil {
		return "", fmt.Errorf(
			"VMware version '%s' is not numeric", version)
	}

	return fmt.Sprintf("%02d", i), nil
}

func compareVersions(versionFound string, versionWanted string, product string) error {
	found, err := normalizeVersion(versionFound)
	if err != nil {
		return err
	}

	wanted, err := normalizeVersion(versionWanted)
	if err != nil {
		return err
	}

	if found < wanted {
		return fmt.Errorf(
			"VMware %s version %s, or greater, is required. Found version: %s", product, versionWanted, versionFound)
	}

	return nil
}
<commit_msg>Make vm log output less confusing<commit_after>package common

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"runtime"
	"strconv"
	"strings"

	"github.com/mitchellh/multistep"
)

// A driver is able to talk to VMware, control virtual machines, etc.
type Driver interface {
	// Clone clones the VMX and the disk to the destination path. The
	// destination is a path to the VMX file. The disk will be copied
	// to that same directory.
	Clone(dst string, src string) error

	// CompactDisk compacts a virtual disk.
	CompactDisk(string) error

	// CreateDisk creates a virtual disk with the given size.
	CreateDisk(string, string, string) error

	// Checks if the VMX file at the given path is running.
	IsRunning(string) (bool, error)

	// CommHost returns the host address for the VM that is being
	// managed by this driver.
	CommHost(multistep.StateBag) (string, error)

	// Start starts a VM specified by the path to the VMX given.
	Start(string, bool) error

	// Stop stops a VM specified by the path to the VMX given.
	Stop(string) error

	// SuppressMessages modifies the VMX or surrounding directory so that
	// VMware doesn't show any annoying messages.
	SuppressMessages(string) error

	// Get the path to the VMware ISO for the given flavor.
	ToolsIsoPath(string) string

	// Attach the VMware tools ISO
	ToolsInstall() error

	// Get the path to the DHCP leases file for the given device.
	DhcpLeasesPath(string) string

	// Verify checks to make sure that this driver should function
	// properly. This should check that all the files it will use
	// appear to exist and so on. If everything is okay, this doesn't
	// return an error. Otherwise, this returns an error.
	Verify() error
}

// NewDriver returns a new driver implementation for this operating
// system, or an error if the driver couldn't be initialized.
func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) {
	drivers := []Driver{}

	switch runtime.GOOS {
	case "darwin":
		drivers = []Driver{
			&Fusion6Driver{
				Fusion5Driver: Fusion5Driver{
					AppPath:   dconfig.FusionAppPath,
					SSHConfig: config,
				},
			},
			&Fusion5Driver{
				AppPath:   dconfig.FusionAppPath,
				SSHConfig: config,
			},
		}
	case "linux":
		fallthrough
	case "windows":
		drivers = []Driver{
			&Workstation10Driver{
				Workstation9Driver: Workstation9Driver{
					SSHConfig: config,
				},
			},
			&Workstation9Driver{
				SSHConfig: config,
			},
			&Player6Driver{
				Player5Driver: Player5Driver{
					SSHConfig: config,
				},
			},
			&Player5Driver{
				SSHConfig: config,
			},
		}
	default:
		return nil, fmt.Errorf("can't find driver for OS: %s", runtime.GOOS)
	}

	errs := ""
	for _, driver := range drivers {
		err := driver.Verify()
		if err == nil {
			return driver, nil
		}
		errs += "* " + err.Error() + "\n"
	}

	return nil, fmt.Errorf(
		"Unable to initialize any driver for this platform. The errors\n"+
			"from each driver are shown below. Please fix at least one driver\n"+
			"to continue:\n%s", errs)
}

func runAndLog(cmd *exec.Cmd) (string, string, error) {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing: %s %s", cmd.Path, strings.Join(cmd.Args[1:], " "))
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		message := stderrString
		if message == "" {
			message = stdoutString
		}

		err = fmt.Errorf("VMware error: %s", message)

		// If "unknown error" is in there, add some additional notes
		re := regexp.MustCompile(`(?i)unknown error`)
		if re.MatchString(message) {
			err = fmt.Errorf(
				"%s\n\n%s", err,
				"Packer detected a VMware 'Unknown Error'. Unfortunately VMware\n"+
					"often has extremely vague error messages such as this and Packer\n"+
					"itself can't do much about that. Please check the vmware.log files\n"+
					"created by VMware when a VM is started (in the directory of the\n"+
					"vmx file), which often contains more detailed error information.")
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	// Replace these for Windows, we only want to deal with Unix
	// style line endings.
	returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1)
	returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1)

	return returnStdout, returnStderr, err
}

func normalizeVersion(version string) (string, error) {
	i, err := strconv.Atoi(version)
	if err != nil {
		return "", fmt.Errorf(
			"VMware version '%s' is not numeric", version)
	}

	return fmt.Sprintf("%02d", i), nil
}

func compareVersions(versionFound string, versionWanted string, product string) error {
	found, err := normalizeVersion(versionFound)
	if err != nil {
		return err
	}

	wanted, err := normalizeVersion(versionWanted)
	if err != nil {
		return err
	}

	if found < wanted {
		return fmt.Errorf(
			"VMware %s version %s, or greater, is required. Found version: %s", product, versionWanted, versionFound)
	}

	return nil
}
<|endoftext|>


<commit_before>//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config

package clone

import (
	"github.com/hashicorp/packer/builder/vsphere/common"
	packerCommon "github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type Config struct {
	packerCommon.PackerConfig `mapstructure:",squash"`
	packerCommon.HTTPConfig   `mapstructure:",squash"`
	packerCommon.CDConfig     `mapstructure:",squash"`

	common.ConnectConfig      `mapstructure:",squash"`
	CloneConfig               `mapstructure:",squash"`
	common.LocationConfig     `mapstructure:",squash"`
	common.HardwareConfig     `mapstructure:",squash"`
	common.ConfigParamsConfig `mapstructure:",squash"`

	common.CDRomConfig       `mapstructure:",squash"`
	common.RemoveCDRomConfig `mapstructure:",squash"`
	common.FloppyConfig      `mapstructure:",squash"`
	common.RunConfig         `mapstructure:",squash"`
	common.BootConfig        `mapstructure:",squash"`
	common.WaitIpConfig      `mapstructure:",squash"`
	Comm                     communicator.Config `mapstructure:",squash"`
	common.ShutdownConfig    `mapstructure:",squash"`

	// Create a snapshot when set to `true`, so the VM can be used as a base
	// for linked clones. Defaults to `false`.
	CreateSnapshot bool `mapstructure:"create_snapshot"`
	// Convert VM to a template. Defaults to `false`.
	ConvertToTemplate bool `mapstructure:"convert_to_template"`
	// Configuration for exporting VM to an ovf file.
	// The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
	Export *common.ExportConfig `mapstructure:"export"`
	// Configuration for importing a VM template or OVF template to a Content Library.
	// The template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
	// The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
	ContentLibraryDestinationConfig *common.ContentLibraryDestinationConfig `mapstructure:"content_library_destination"`
	// Customize the cloned VM to configure host, network, or licensing settings. See the [customization options](#customization).
	CustomizeConfig *CustomizeConfig `mapstructure:"customize"`

	ctx interpolate.Context
}

func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
	err := config.Decode(c, &config.DecodeOpts{
		PluginType:         common.BuilderId,
		Interpolate:        true,
		InterpolateContext: &c.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, err
	}

	warnings := make([]string, 0)
	errs := new(packer.MultiError)

	errs = packer.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.CloneConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)

	errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
	errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
	errs = packer.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)

	shutdownWarnings, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
	warnings = append(warnings, shutdownWarnings...)
	errs = packer.MultiErrorAppend(errs, shutdownErrs...)

	if c.Export != nil {
		errs = packer.MultiErrorAppend(errs, c.Export.Prepare(&c.ctx, &c.LocationConfig, &c.PackerConfig)...)
	}
	if c.ContentLibraryDestinationConfig != nil {
		errs = packer.MultiErrorAppend(errs, c.ContentLibraryDestinationConfig.Prepare(&c.LocationConfig)...)
	}
	if c.CustomizeConfig != nil {
		errs = packer.MultiErrorAppend(errs, c.CustomizeConfig.Prepare()...)
	}

	if len(errs.Errors) > 0 {
		return nil, errs
	}

	return nil, nil
}
<commit_msg>vsphere clone config not yet using warnings, leaving code commented out<commit_after>//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config

package clone

import (
	"github.com/hashicorp/packer/builder/vsphere/common"
	packerCommon "github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type Config struct {
	packerCommon.PackerConfig `mapstructure:",squash"`
	packerCommon.HTTPConfig   `mapstructure:",squash"`
	packerCommon.CDConfig     `mapstructure:",squash"`

	common.ConnectConfig      `mapstructure:",squash"`
	CloneConfig               `mapstructure:",squash"`
	common.LocationConfig     `mapstructure:",squash"`
	common.HardwareConfig     `mapstructure:",squash"`
	common.ConfigParamsConfig `mapstructure:",squash"`

	common.CDRomConfig       `mapstructure:",squash"`
	common.RemoveCDRomConfig `mapstructure:",squash"`
	common.FloppyConfig      `mapstructure:",squash"`
	common.RunConfig         `mapstructure:",squash"`
	common.BootConfig        `mapstructure:",squash"`
	common.WaitIpConfig      `mapstructure:",squash"`
	Comm                     communicator.Config `mapstructure:",squash"`
	common.ShutdownConfig    `mapstructure:",squash"`

	// Create a snapshot when set to `true`, so the VM can be used as a base
	// for linked clones. Defaults to `false`.
	CreateSnapshot bool `mapstructure:"create_snapshot"`
	// Convert VM to a template. Defaults to `false`.
	ConvertToTemplate bool `mapstructure:"convert_to_template"`
	// Configuration for exporting VM to an ovf file.
	// The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
	Export *common.ExportConfig `mapstructure:"export"`
	// Configuration for importing a VM template or OVF template to a Content Library.
	// The template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
	// The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
	ContentLibraryDestinationConfig *common.ContentLibraryDestinationConfig `mapstructure:"content_library_destination"`
	// Customize the cloned VM to configure host, network, or licensing settings. See the [customization options](#customization).
	CustomizeConfig *CustomizeConfig `mapstructure:"customize"`

	ctx interpolate.Context
}

func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
	err := config.Decode(c, &config.DecodeOpts{
		PluginType:         common.BuilderId,
		Interpolate:        true,
		InterpolateContext: &c.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, err
	}

	// warnings := make([]string, 0)
	errs := new(packer.MultiError)

	errs = packer.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.CloneConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)

	errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
	errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
	errs = packer.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
	errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)

	_, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
	// shutdownWarnings, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
	// warnings = append(warnings, shutdownWarnings...)
	errs = packer.MultiErrorAppend(errs, shutdownErrs...)

	if c.Export != nil {
		errs = packer.MultiErrorAppend(errs, c.Export.Prepare(&c.ctx, &c.LocationConfig, &c.PackerConfig)...)
	}
	if c.ContentLibraryDestinationConfig != nil {
		errs = packer.MultiErrorAppend(errs, c.ContentLibraryDestinationConfig.Prepare(&c.LocationConfig)...)
	}
	if c.CustomizeConfig != nil {
		errs = packer.MultiErrorAppend(errs, c.CustomizeConfig.Prepare()...)
	}

	if len(errs.Errors) > 0 {
		return nil, errs
	}

	return nil, nil
}
<|endoftext|>


<commit_before>package elasticsearch

import (
	"gopkg.in/olivere/elastic.v3"
)

var (
	// elasticsearch client
	client *elastic.Client
)

// Elasticsearch singleton
type Elasticsearch struct {
}

// Connect to the elastic search server
func (es *Elasticsearch) Connect(url string) error {
	// Create ES client
	var err error
	client, err = elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetSniff(false),
	)
	return err
}

// CreateIndexIfNotExists Creates an index if it doesn't already exists
func (es *Elasticsearch) CreateIndexIfNotExists(esIndex string, esType string, mapping string) {
	// Use the IndexExists service to check if the index exists
	exists, err := client.IndexExists(esIndex).Do()
	if err != nil {
		// Handle error
		panic(err)
	}
	if !exists {
		// Create a new index.
		createIndex, err := client.CreateIndex(esIndex).Do()
		if err != nil {
			// TODO: Handle error
			panic(err)
		}
		if !createIndex.Acknowledged {
			// TODO: Handle not acknowledged
			panic("not acked")
		}

		response, err := client.PutMapping().Index(esIndex).Type(esType).BodyString(mapping).Do()
		if err != nil {
			// TODO: Handle error
			panic(err)
		}
		if response == nil {
			// TODO: Handle error
			panic(err)
		}
	}
}

// Index store a document inside elastic search
func (es *Elasticsearch) Index(esIndex string, esType string, body interface{}) {
	// Add a document to the index
	_, err := client.Index().
		Index(esIndex).
		Type("project").
		BodyJson(body).
		Refresh(true).
		Do()
	if err != nil {
		// TODO: Handle error
		panic(err)
	}
}

// All returns all the documents for a given index
func (es *Elasticsearch) All(esIndex string) []*elastic.SearchHit {
	// Search with a term query
	searchResult, err := client.Search().
		Index(esIndex).
		Do()
	if err != nil {
		// TODO: Handle error
		panic(err)
	}
	return searchResult.Hits.Hits
}

// GetClient returns the native elastic search client
func (es *Elasticsearch) GetClient() *elastic.Client {
	return client
}
<commit_msg>Removing unused Elasticsearch code<commit_after>package elasticsearch

import (
	"gopkg.in/olivere/elastic.v3"
)

var (
	// elasticsearch client
	client *elastic.Client
)

// Elasticsearch singleton
type Elasticsearch struct {
}

// Connect to the elastic search server
func (es *Elasticsearch) Connect(url string) error {
	// Create ES client
	var err error
	client, err = elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetSniff(false),
	)
	return err
}

// GetClient returns the native elastic search client
func (es *Elasticsearch) GetClient() *elastic.Client {
	return client
}
<|endoftext|>


<commit_before>// Copyright © 2016 Phil Pennock.
// All rights reserved, except as granted under license.
// Licensed per file LICENSE.txt

package code

import (
	"errors"
	"strconv"

	"github.com/atotto/clipboard"
	"github.com/spf13/cobra"

	"github.com/philpennock/character/resultset"
	"github.com/philpennock/character/sources"
	"github.com/philpennock/character/unicode"

	"github.com/philpennock/character/commands/root"
)

var flags struct {
	clipboard bool
	livevim   bool
	verbose   bool
}

// FIXME: make dedicated type, embed search info

// ErrUnknownCodepoint means the specified codepoint is not assigned
var ErrUnknownCodepoint = errors.New("unknown character codepoint")

var codeCmd = &cobra.Command{
	Use:   "code [codepoint ...]",
	Short: "shows character with codepoint",
	Run: func(cmd *cobra.Command, args []string) {
		srcs := sources.NewFast()
		if flags.verbose && flags.livevim {
			srcs.LoadLiveVim()
		}
		results := resultset.New(srcs, len(args))

		for _, arg := range args {
			ci, err := findCharInfoByCodepoint(srcs.Unicode, arg)
			if err != nil {
				root.Errored()
				results.AddError(arg, err)
				continue
			}
			results.AddCharInfo(ci)
		}

		if flags.clipboard {
			err := clipboard.WriteAll(results.StringPlain(resultset.PRINT_RUNE))
			if err != nil {
				root.Errored()
				results.AddError("<clipboard>", err)
			}
		}

		if flags.verbose {
			results.PrintTables()
		} else {
			results.PrintPlain(resultset.PRINT_RUNE)
		}
	},
}

func init() {
	codeCmd.Flags().BoolVarP(&flags.clipboard, "clipboard", "c", false, "copy resulting chars to clipboard too")
	codeCmd.Flags().BoolVarP(&flags.livevim, "livevim", "l", false, "load full vim data (for verbose)")
	if resultset.CanTable() {
		codeCmd.Flags().BoolVarP(&flags.verbose, "verbose", "v", false, "show information about the character")
	}
	if clipboard.Unsupported {
		// We don't want to only register the flag if clipboard is supported,
		// because that makes client portability more problematic.  Instead, we
		// just hide it to avoid offering something we can't honour, even
		// though we'll accept the option (and show an error) if given.
		codeCmd.Flags().MarkHidden("clipboard")
	}
	// FIXME: support verbose results without tables
	root.AddCommand(codeCmd)
}

func findCharInfoByCodepoint(u unicode.Unicode, needle string) (unicode.CharInfo, error) {
	n32, err := strconv.ParseInt(needle, 0, 32)
	if err != nil {
		return unicode.CharInfo{}, err
	}
	n := rune(n32)

	if ci, ok := u.ByRune[n]; ok {
		return ci, nil
	}
	return unicode.CharInfo{}, ErrUnknownCodepoint
}
<commit_msg>code: lookup handling hex-encoded UTF-8<commit_after>// Copyright © 2016 Phil Pennock.
// All rights reserved, except as granted under license.
// Licensed per file LICENSE.txt

package code

import (
	"encoding/hex"
	"errors"
	"regexp"
	"strconv"
	"strings"
	"unicode/utf8"

	"github.com/atotto/clipboard"
	"github.com/spf13/cobra"

	"github.com/philpennock/character/resultset"
	"github.com/philpennock/character/sources"
	"github.com/philpennock/character/unicode"

	"github.com/philpennock/character/commands/root"
)

var flags struct {
	clipboard bool
	livevim   bool
	utf8hex   bool
	verbose   bool
}

// FIXME: make dedicated type, embed search info

// ErrUnknownCodepoint means the specified codepoint is not assigned
var ErrUnknownCodepoint = errors.New("unknown character codepoint")

// When decoding, we may encounter problems
type deferredError struct {
	arg string
	err error
}

var codeCmd = &cobra.Command{
	Use:   "code [codepoint ...]",
	Short: "shows character with codepoint",
	Run: func(cmd *cobra.Command, args []string) {
		srcs := sources.NewFast()
		if flags.verbose && flags.livevim {
			srcs.LoadLiveVim()
		}

		// If given utf8hex flag, then we need to pre-munge the parameters
		deferredErrors := make([]deferredError, 0, 20)

		if flags.utf8hex {
			// WAG the capacity
			newargs := make([]string, 0, len(args)*4)
			matchHexPairSeq := regexp.MustCompile(`^(?:%[0-9A-Fa-f]{2})+`)

			for _, arg := range args {
				// If we have %-encoded, then take non-%-preceded entries as literal character
				// If we don't, then assume that we just have hex strings
				if strings.ContainsRune(arg, '%') {
					for len(arg) > 0 {
						nextPercent := strings.IndexByte(arg, '%')
						if nextPercent < 0 {
							for _, c := range arg {
								newargs = append(newargs, strconv.Itoa(int(c)))
							}
							arg = ""
							continue
						}
						if nextPercent > 0 {
							for _, c := range arg[:nextPercent] {
								newargs = append(newargs, strconv.Itoa(int(c)))
							}
							arg = arg[nextPercent:]
							// do not 'continue', handle inline immediately next
						}
						matches := matchHexPairSeq.FindStringSubmatch(arg)
						if matches == nil {
							deferredErrors = append(deferredErrors, deferredError{arg: arg, err: errors.New("malformed %hex seq")})
							arg = ""
							continue
						}
						got := matches[0]
						arg = arg[len(got):]
						got = strings.Replace(got, "%", "", -1)

						toAdd, defErr := codepointsFromHexString(got)
						if toAdd != nil {
							newargs = append(newargs, toAdd...)
						}
						if defErr != nil {
							deferredErrors = append(deferredErrors, *defErr)
							continue
						}
					}
				} else {
					toAdd, defErr := codepointsFromHexString(arg)
					if toAdd != nil {
						newargs = append(newargs, toAdd...)
					}
					if defErr != nil {
						deferredErrors = append(deferredErrors, *defErr)
						continue
					}
				}
			}
			args = newargs
		}

		results := resultset.New(srcs, len(args))
		for _, e := range deferredErrors {
			results.AddError(e.arg, e.err)
		}

		for _, arg := range args {
			ci, err := findCharInfoByCodepoint(srcs.Unicode, arg)
			if err != nil {
				root.Errored()
				results.AddError(arg, err)
				continue
			}
			results.AddCharInfo(ci)
		}

		if flags.clipboard {
			err := clipboard.WriteAll(results.StringPlain(resultset.PRINT_RUNE))
			if err != nil {
				root.Errored()
				results.AddError("<clipboard>", err)
			}
		}

		if flags.verbose {
			results.PrintTables()
		} else {
			results.PrintPlain(resultset.PRINT_RUNE)
		}
	},
}

func init() {
	codeCmd.Flags().BoolVarP(&flags.clipboard, "clipboard", "c", false, "copy resulting chars to clipboard too")
	codeCmd.Flags().BoolVarP(&flags.livevim, "livevim", "l", false, "load full vim data (for verbose)")
	codeCmd.Flags().BoolVarP(&flags.utf8hex, "utf8hex", "H", false, "take UTF-8 Hex-encoded codepoint")
	if resultset.CanTable() {
		codeCmd.Flags().BoolVarP(&flags.verbose, "verbose", "v", false, "show information about the character")
	}
	if clipboard.Unsupported {
		// We don't want to only register the flag if clipboard is supported,
		// because that makes client portability more problematic.  Instead, we
		// just hide it to avoid offering something we can't honour, even
		// though we'll accept the option (and show an error) if given.
		codeCmd.Flags().MarkHidden("clipboard")
	}
	// FIXME: support verbose results without tables
	root.AddCommand(codeCmd)
}

func findCharInfoByCodepoint(u unicode.Unicode, needle string) (unicode.CharInfo, error) {
	n32, err := strconv.ParseInt(needle, 0, 32)
	if err != nil {
		return unicode.CharInfo{}, err
	}
	n := rune(n32)

	if ci, ok := u.ByRune[n]; ok {
		return ci, nil
	}
	return unicode.CharInfo{}, ErrUnknownCodepoint
}

func codepointsFromHexString(hs string) ([]string, *deferredError) {
	seq, err := hex.DecodeString(hs)
	if err != nil {
		return nil, &deferredError{arg: hs, err: err}
	}
	res := make([]string, 0, len(seq))
	errorOffset := 0
	for len(seq) > 0 {
		r, sz := utf8.DecodeRune(seq)
		if r == utf8.RuneError && (sz == 0 || sz == 1) {
			return res, &deferredError{arg: hs[errorOffset*2:], err: errors.New("invalid rune")}
		}
		if sz == 0 {
			return res, &deferredError{arg: hs[errorOffset*2:], err: errors.New("API broken (rune size 0)")}
		}
		seq = seq[sz:]
		errorOffset += sz
		res = append(res, strconv.Itoa(int(r)))
	}
	return res, nil
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/spf13/cobra"
	"github.com/yungsang/tablewriter"
	"github.com/yungsang/talk2docker/api"
	"github.com/yungsang/talk2docker/client"
)

var (
	boolLatest, boolSize bool
)

var cmdPs = &cobra.Command{
	Use:   "ps",
	Short: "List containers",
	Long:  APP_NAME + " ps - List containers",
}

func init() {
	cmdPs.Flags().BoolVarP(&boolAll, "all", "a", false, "Show all containers. Only running containers are shown by default.")
	cmdPs.Flags().BoolVarP(&boolLatest, "latest", "l", false, "Show only the latest created container, include non-running ones.")
	cmdPs.Flags().BoolVarP(&boolQuiet, "quiet", "q", false, "Only display numeric IDs")
	cmdPs.Flags().BoolVarP(&boolSize, "size", "s", false, "Display sizes")
	cmdPs.Flags().BoolVarP(&boolNoHeader, "no-header", "n", false, "Omit the header")

	cmdPs.Run = listContainers
}

func listContainers(ctx *cobra.Command, args []string) {
	docker, err := client.NewDockerClient(configPath, hostName, ctx.Out())
	if err != nil {
		log.Fatal(err)
	}

	limit := 0
	if boolLatest {
		limit = 1
	}

	containers, err := docker.ListContainers(boolAll, boolSize, limit, "", "", nil)
	if err != nil {
		log.Fatal(err)
	}

	if boolQuiet {
		for _, container := range containers {
			ctx.Println(Truncate(container.Id, 12))
		}
		return
	}

	if boolYAML || boolJSON {
		if err := FormatPrint(ctx.Out(), containers); err != nil {
			log.Fatal(err)
		}
		return
	}

	trimNamePrefix := func(ss []string) []string {
		for i, s := range ss {
			ss[i] = strings.TrimPrefix(s, "/")
		}
		return ss
	}

	formatPorts := func(ports []api.Port) string {
		result := []string{}
		for _, p := range ports {
			result = append(result, fmt.Sprintf("%s:%d->%d/%s",
				p.IP, p.PublicPort, p.PrivatePort, p.Type))
		}
		return strings.Join(result, ", ")
	}

	var items [][]string
	for _, container := range containers {
		out := []string{
			Truncate(container.Id, 12),
			strings.Join(trimNamePrefix(container.Names), ", "),
			container.Image,
			Truncate(container.Command, 30),
			FormatDateTime(time.Unix(container.Created, 0)),
			container.Status,
			formatPorts(container.Ports),
		}
		if boolSize {
			out = append(out, FormatFloat(float64(container.SizeRw)/1000000))
		}
		items = append(items, out)
	}

	header := []string{
		"ID",
		"Names",
		"Image",
		"Command",
		"Created at",
		"Status",
		"Ports",
	}
	if boolSize {
		header = append(header, "Size(MB)")
	}

	PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_DEFAULT)
}
<commit_msg>Refactoring<commit_after>package commands

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/spf13/cobra"
	"github.com/yungsang/tablewriter"
	"github.com/yungsang/talk2docker/api"
	"github.com/yungsang/talk2docker/client"
)

var (
	boolLatest, boolSize bool
)

var cmdPs = &cobra.Command{
	Use:   "ps",
	Short: "List containers",
	Long:  APP_NAME + " ps - List containers",
	Run:   listContainers,
}

func init() {
	cmdPs.Flags().BoolVarP(&boolAll, "all", "a", false, "Show all containers. Only running containers are shown by default.")
	cmdPs.Flags().BoolVarP(&boolLatest, "latest", "l", false, "Show only the latest created container, include non-running ones.")
	cmdPs.Flags().BoolVarP(&boolQuiet, "quiet", "q", false, "Only display numeric IDs")
	cmdPs.Flags().BoolVarP(&boolSize, "size", "s", false, "Display sizes")
	cmdPs.Flags().BoolVarP(&boolNoHeader, "no-header", "n", false, "Omit the header")
}

func listContainers(ctx *cobra.Command, args []string) {
	docker, err := client.NewDockerClient(configPath, hostName, ctx.Out())
	if err != nil {
		log.Fatal(err)
	}

	limit := 0
	if boolLatest {
		limit = 1
	}

	containers, err := docker.ListContainers(boolAll, boolSize, limit, "", "", nil)
	if err != nil {
		log.Fatal(err)
	}

	if boolQuiet {
		for _, container := range containers {
			ctx.Println(Truncate(container.Id, 12))
		}
		return
	}

	if boolYAML || boolJSON {
		if err := FormatPrint(ctx.Out(), containers); err != nil {
			log.Fatal(err)
		}
		return
	}

	trimNamePrefix := func(ss []string) []string {
		for i, s := range ss {
			ss[i] = strings.TrimPrefix(s, "/")
		}
		return ss
	}

	formatPorts := func(ports []api.Port) string {
		result := []string{}
		for _, p := range ports {
			result = append(result, fmt.Sprintf("%s:%d->%d/%s",
				p.IP, p.PublicPort, p.PrivatePort, p.Type))
		}
		return strings.Join(result, ", ")
	}

	var items [][]string
	for _, container := range containers {
		out := []string{
			Truncate(container.Id, 12),
			strings.Join(trimNamePrefix(container.Names), ", "),
			container.Image,
			Truncate(container.Command, 30),
			FormatDateTime(time.Unix(container.Created, 0)),
			container.Status,
			formatPorts(container.Ports),
		}
		if boolSize {
			out = append(out, FormatFloat(float64(container.SizeRw)/1000000))
		}
		items = append(items, out)
	}

	header := []string{
		"ID",
		"Names",
		"Image",
		"Command",
		"Created at",
		"Status",
		"Ports",
	}
	if boolSize {
		header = append(header, "Size(MB)")
	}

	PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_DEFAULT)
}
<|endoftext|>