<commit_before>package udp

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/vimeo/statsdaemon/common"
	"log"
	"net"
	"strconv"
)

const (
	MaxUdpPacketSize = 65535
)

// ParseLine turns a line into a *Metric (or not) and returns an error if the line was invalid.
// note that *Metric can be nil when the line was valid (if the line was empty)
// input format: key:value|modifier[|@samplerate]
func ParseLine(line []byte) (metric *common.Metric, err error) {
	if len(line) == 0 {
		return nil, nil
	}
	parts := bytes.SplitN(bytes.TrimSpace(line), []byte(":"), 2)
	if len(parts) != 2 {
		return nil, errors.New("bad amount of colons")
	}
	if bytes.Contains(parts[1], []byte(":")) {
		return nil, errors.New("bad amount of colons")
	}
	bucket := parts[0]
	if len(bucket) == 0 {
		return nil, errors.New("key zero len")
	}
	parts = bytes.SplitN(parts[1], []byte("|"), 3)
	if len(parts) < 2 {
		return nil, errors.New("bad amount of pipes")
	}
	modifier := string(parts[1])
	if modifier != "g" && modifier != "c" && modifier != "ms" {
		return nil, errors.New("unsupported metric type")
	}
	sampleRate := float64(1)
	if len(parts) == 3 {
		if parts[2][0] != byte('@') {
			return nil, errors.New("invalid sampling")
		}
		var err error
		sampleRate, err = strconv.ParseFloat(string(parts[2])[1:], 32)
		if err != nil {
			return nil, err
		}
	}
	value, err := strconv.ParseFloat(string(parts[0]), 64)
	if err != nil {
		return nil, err
	}
	metric = &common.Metric{
		Bucket:   string(bucket),
		Value:    value,
		Modifier: modifier,
		Sampling: float32(sampleRate),
	}
	return metric, nil
}

// ParseArchiveLine turns an "archive line" into an *Metric (or not) and returns an error if the line was invalid.
// note that *Metric can be nil when the line was valid (if the line was empty)
// input format: key value ts modifier [samplerate]
func ParseArchiveLine(line []byte) (metric *common.Metric, err error) {
	if len(line) == 0 {
		return nil, nil
	}
	parts := bytes.SplitN(bytes.TrimSpace(line), []byte(" "), 6)
	if len(parts) != 4 && len(parts) != 5 {
		return nil, errors.New("incorrect amount of fields")
	}
	bucket := parts[0]
	value, err := strconv.ParseFloat(string(parts[1]), 64)
	if err != nil {
		return nil, errors.New("couldn't parseFloat value")
	}
	ts, err := strconv.ParseUint(string(parts[2]), 32, 32)
	modifier := string(parts[3])
	if modifier != "g" && modifier != "c" && modifier != "ms" {
		return nil, errors.New("unsupported metric type")
	}
	sampleRate := float64(1)
	if len(parts) == 5 {
		var err error
		sampleRate, err = strconv.ParseFloat(string(parts[4]), 32)
		if err != nil {
			return nil, errors.New("couldn't parseFloat sampling")
		}
	}
	metric = &common.Metric{
		Bucket:   string(bucket),
		Value:    value,
		Modifier: modifier,
		Sampling: float32(sampleRate),
		Time:     uint32(ts),
	}
	return metric, nil
}

// ParseMessage turns byte data into a slice of metric pointers
// note that it creates "invalid line" metrics itself, upon invalid lines,
// which will get passed on and aggregated along with the other metrics
func ParseMessage(data []byte, prefix_internal string, output *common.Output, parse parseLineFunc) (metrics []*common.Metric) {
	for _, line := range bytes.Split(data, []byte("\n")) {
		metric, err := parse(line)
		if err != nil {
			// data will be repurposed by the udpListener
			report_line := make([]byte, len(line), len(line))
			copy(report_line, line)
			output.Invalid_lines.Broadcast <- report_line
			metric = &common.Metric{
				fmt.Sprintf("%starget_type=count.type=invalid_line.unit=Err", prefix_internal),
				float64(1),
				"c",
				float32(1),
				0,
			}
		} else {
			// data will be repurposed by the udpListener
			report_line := make([]byte, len(line), len(line))
			copy(report_line, line)
			output.Valid_lines.Broadcast <- report_line
		}
		if metric != nil {
			metrics = append(metrics, metric)
		}
	}
	return metrics
}

type parseLineFunc func(line []byte) (metric *common.Metric, err error)

func StatsListener(listen_addr, prefix_internal string, output *common.Output) {
	Listener(listen_addr, prefix_internal, output, ParseLine)
}

func ArchiveStatsListener(listen_addr, prefix_internal string, output *common.Output) {
	Listener(listen_addr, prefix_internal, output, ParseArchiveLine)
}

// Listener receives packets from the udp buffer, parses them and feeds both the Metrics channel
// as well as the metricAmounts channel
func Listener(listen_addr, prefix_internal string, output *common.Output, parse parseLineFunc) {
	address, err := net.ResolveUDPAddr("udp", listen_addr)
	if err != nil {
		log.Fatalf("ERROR: Cannot resolve '%s' - %s", listen_addr, err)
	}

	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()
	log.Printf("listening on %s", address)

	message := make([]byte, MaxUdpPacketSize)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range ParseMessage(message[:n], prefix_internal, output, parse) {
			output.Metrics <- p
			output.MetricAmounts <- common.MetricAmount{p.Bucket, p.Sampling}
		}
	}
}
<commit_msg>switch to new ParseLine implementation<commit_after>package udp

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/vimeo/statsdaemon/common"
	"log"
	"net"
	"strconv"
)

const (
	MaxUdpPacketSize = 65535
)

// ParseLine turns a line into a *Metric (or not) and returns an error if the line was invalid.
// note that *Metric can be nil when the line was valid (if the line was empty)
// input format: key:value|modifier[|@samplerate]
func ParseLine(line []byte) (metric *common.Metric, err error) {
	if len(line) == 0 {
		return nil, nil
	}
	parts := bytes.SplitN(bytes.TrimSpace(line), []byte(":"), 2)
	if len(parts) != 2 {
		return nil, errors.New("bad amount of colons")
	}
	if bytes.Contains(parts[1], []byte(":")) {
		return nil, errors.New("bad amount of colons")
	}
	bucket := parts[0]
	if len(bucket) == 0 {
		return nil, errors.New("key zero len")
	}
	parts = bytes.SplitN(parts[1], []byte("|"), 3)
	if len(parts) < 2 {
		return nil, errors.New("bad amount of pipes")
	}
	modifier := string(parts[1])
	if modifier != "g" && modifier != "c" && modifier != "ms" {
		return nil, errors.New("unsupported metric type")
	}
	sampleRate := float64(1)
	if len(parts) == 3 {
		if parts[2][0] != byte('@') {
			return nil, errors.New("invalid sampling")
		}
		var err error
		sampleRate, err = strconv.ParseFloat(string(parts[2])[1:], 32)
		if err != nil {
			return nil, err
		}
	}
	value, err := strconv.ParseFloat(string(parts[0]), 64)
	if err != nil {
		return nil, err
	}
	metric = &common.Metric{
		Bucket:   string(bucket),
		Value:    value,
		Modifier: modifier,
		Sampling: float32(sampleRate),
	}
	return metric, nil
}

// ParseArchiveLine turns an "archive line" into an *Metric (or not) and returns an error if the line was invalid.
// note that *Metric can be nil when the line was valid (if the line was empty)
// input format: key value ts modifier [samplerate]
func ParseArchiveLine(line []byte) (metric *common.Metric, err error) {
	if len(line) == 0 {
		return nil, nil
	}
	parts := bytes.SplitN(bytes.TrimSpace(line), []byte(" "), 6)
	if len(parts) != 4 && len(parts) != 5 {
		return nil, errors.New("incorrect amount of fields")
	}
	bucket := parts[0]
	value, err := strconv.ParseFloat(string(parts[1]), 64)
	if err != nil {
		return nil, errors.New("couldn't parseFloat value")
	}
	ts, err := strconv.ParseUint(string(parts[2]), 32, 32)
	modifier := string(parts[3])
	if modifier != "g" && modifier != "c" && modifier != "ms" {
		return nil, errors.New("unsupported metric type")
	}
	sampleRate := float64(1)
	if len(parts) == 5 {
		var err error
		sampleRate, err = strconv.ParseFloat(string(parts[4]), 32)
		if err != nil {
			return nil, errors.New("couldn't parseFloat sampling")
		}
	}
	metric = &common.Metric{
		Bucket:   string(bucket),
		Value:    value,
		Modifier: modifier,
		Sampling: float32(sampleRate),
		Time:     uint32(ts),
	}
	return metric, nil
}

// ParseMessage turns byte data into a slice of metric pointers
// note that it creates "invalid line" metrics itself, upon invalid lines,
// which will get passed on and aggregated along with the other metrics
func ParseMessage(data []byte, prefix_internal string, output *common.Output, parse parseLineFunc) (metrics []*common.Metric) {
	for _, line := range bytes.Split(data, []byte("\n")) {
		metric, err := parse(line)
		if err != nil {
			// data will be repurposed by the udpListener
			report_line := make([]byte, len(line), len(line))
			copy(report_line, line)
			output.Invalid_lines.Broadcast <- report_line
			metric = &common.Metric{
				fmt.Sprintf("%starget_type=count.type=invalid_line.unit=Err", prefix_internal),
				float64(1),
				"c",
				float32(1),
				0,
			}
		} else {
			// data will be repurposed by the udpListener
			report_line := make([]byte, len(line), len(line))
			copy(report_line, line)
			output.Valid_lines.Broadcast <- report_line
		}
		if metric != nil {
			metrics = append(metrics, metric)
		}
	}
	return metrics
}

type parseLineFunc func(line []byte) (metric *common.Metric, err error)

func StatsListener(listen_addr, prefix_internal string, output *common.Output) {
	Listener(listen_addr, prefix_internal, output, ParseLine2)
}

func ArchiveStatsListener(listen_addr, prefix_internal string, output *common.Output) {
	Listener(listen_addr, prefix_internal, output, ParseArchiveLine)
}

// Listener receives packets from the udp buffer, parses them and feeds both the Metrics channel
// as well as the metricAmounts channel
func Listener(listen_addr, prefix_internal string, output *common.Output, parse parseLineFunc) {
	address, err := net.ResolveUDPAddr("udp", listen_addr)
	if err != nil {
		log.Fatalf("ERROR: Cannot resolve '%s' - %s", listen_addr, err)
	}

	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()
	log.Printf("listening on %s", address)

	message := make([]byte, MaxUdpPacketSize)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range ParseMessage(message[:n], prefix_internal, output, parse) {
			output.Metrics <- p
			output.MetricAmounts <- common.MetricAmount{p.Bucket, p.Sampling}
		}
	}
}
<|endoftext|>


<commit_before>package aws

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

	"github.com/hashicorp/terraform/flatmap"
	"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")

	// Figure out user data
	userData := ""
	if attr, ok := d.Attributes["user_data"]; ok {
		userData = attr.NewExtra.(string)
	}

	// Build the creation struct
	runOpts := &ec2.RunInstances{
		ImageId:      rs.Attributes["ami"],
		InstanceType: rs.Attributes["instance_type"],
		KeyName:      rs.Attributes["key_name"],
		SubnetId:     rs.Attributes["subnet_id"],
		UserData:     []byte(userData),
	}
	if raw := flatmap.Expand(rs.Attributes, "security_groups"); raw != nil {
		if sgs, ok := raw.([]interface{}); ok {
			for _, sg := range sgs {
				str, ok := sg.(string)
				if !ok {
					continue
				}

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

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

	// Create the instance
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return 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)

	// Initialize the connection info
	rs.ConnInfo["type"] = "ssh"
	rs.ConnInfo["host"] = instance.PublicIpAddress

	// 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,
			"security_groups":   diff.AttrTypeCreate,
			"subnet_id":         diff.AttrTypeCreate,
			"source_dest_check": diff.AttrTypeUpdate,
			"user_data":         diff.AttrTypeCreate,
		},

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

		PreProcess: map[string]diff.PreProcessFunc{
			"user_data": func(v string) string {
				hash := sha1.Sum([]byte(v))
				return hex.EncodeToString(hash[:])
			},
		},
	}

	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

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

		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: sg.Id},
		)
	}
	flatmap.Map(s.Attributes).Merge(flatmap.Flatten(map[string]interface{}{
		"security_groups": sgs,
	}))

	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>provider/aws: Less aggressive API rate<commit_after>package aws

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

	"github.com/hashicorp/terraform/flatmap"
	"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")

	// Figure out user data
	userData := ""
	if attr, ok := d.Attributes["user_data"]; ok {
		userData = attr.NewExtra.(string)
	}

	// Build the creation struct
	runOpts := &ec2.RunInstances{
		ImageId:      rs.Attributes["ami"],
		InstanceType: rs.Attributes["instance_type"],
		KeyName:      rs.Attributes["key_name"],
		SubnetId:     rs.Attributes["subnet_id"],
		UserData:     []byte(userData),
	}
	if raw := flatmap.Expand(rs.Attributes, "security_groups"); raw != nil {
		if sgs, ok := raw.([]interface{}); ok {
			for _, sg := range sgs {
				str, ok := sg.(string)
				if !ok {
					continue
				}

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

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

	// Create the instance
	log.Printf("[DEBUG] Run configuration: %#v", runOpts)
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		return 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,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	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)

	// Initialize the connection info
	rs.ConnInfo["type"] = "ssh"
	rs.ConnInfo["host"] = instance.PublicIpAddress

	// 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,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err := stateConf.WaitForState()

	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to terminate: %s",
			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,
			"security_groups":   diff.AttrTypeCreate,
			"subnet_id":         diff.AttrTypeCreate,
			"source_dest_check": diff.AttrTypeUpdate,
			"user_data":         diff.AttrTypeCreate,
		},

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

		PreProcess: map[string]diff.PreProcessFunc{
			"user_data": func(v string) string {
				hash := sha1.Sum([]byte(v))
				return hex.EncodeToString(hash[:])
			},
		},
	}

	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

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

		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: sg.Id},
		)
	}
	flatmap.Map(s.Attributes).Merge(flatmap.Flatten(map[string]interface{}{
		"security_groups": sgs,
	}))

	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>package resources

import (
	"errors"
	"fmt"

	"k8s.io/client-go/pkg/api/v1"

	"github.com/Machiel/slugify"
	"github.com/generationtux/brizo/database"
	"github.com/generationtux/brizo/kube"
	"github.com/jinzhu/gorm"
	"github.com/pborman/uuid"
)

// Environment as defined by Brizo.
type Environment struct {
	database.Model
	UUID          string      `gorm:"not null;unique_index" sql:"type:varchar(36)" json:"uuid"`
	Name          string      `gorm:"not null" json:"name"`
	Slug          string      `gorm:"not null" json:"slug"`
	ApplicationID uint64      `json:"application_id,string"`
	Application   Application `json:"application,array"`
	Versions      []Version   `json:"versions,array"`
}

// BeforeCreate is a hook that runs before inserting a new record into the
// database
func (environment *Environment) BeforeCreate() (err error) {
	if environment.UUID == "" {
		environment.UUID = uuid.New()
	}
	if environment.Slug == "" {
		environment.Slug = slugify.Slugify(environment.Name)
	}
	return
}

// AllEnvironments will return all of the Environments
func AllEnvironments(db *gorm.DB) ([]Environment, error) {
	var environments []Environment
	result := db.Find(&environments)

	return environments, result.Error
}

// CreateEnvironment will add a new Environment to Brizo
func CreateEnvironment(db *gorm.DB, client kube.APIInterface, environment *Environment, application *Application) (bool, error) {
	result := db.Create(&environment)
	service := environmentServiceDefinition(environment, application)
	err := client.CreateService(service)
	if err != nil {
		// @TODO need a better way to handle some of this upstream
		DeleteEnvironment(db, environment.Name)
		return false, err
	}

	return result.RowsAffected == 1, result.Error
}

func environmentServiceDefinition(environment *Environment, application *Application) *v1.Service {
	name := fmt.Sprintf(
		"%v-%v",
		application.Slug,
		environment.Slug,
	)
	return &v1.Service{
		ObjectMeta: v1.ObjectMeta{
			Name:      name,
			Namespace: "brizo",
			Labels: map[string]string{
				"brizoManaged": "true",
				"appUUID":      application.UUID,
				"envUUID":      environment.UUID,
			},
		},
		//@TODO allow for multiple ports creations
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{
				v1.ServicePort{
					Protocol: v1.ProtocolTCP,
					Port:     int32(80),
				},
			},
		},
	}
}

// UpdateEnvironment will update an existing Environment
func UpdateEnvironment(db *gorm.DB, environment *Environment) (bool, error) {
	environment.Slug = slugify.Slugify(environment.Name)
	result := db.Model(environment).Where("uuid = ?", environment.UUID).
		UpdateColumns(environment)

	return result.RowsAffected == 1, result.Error
}

// UpdateEnvironmentService will update an existing Environment's service in K8s
func UpdateEnvironmentService(db *gorm.DB, client kube.APIInterface, environment *Environment, ports []ContainerPort) (bool, error) {
	var svcPorts = make([]v1.ServicePort, len(ports))
	var protocol = v1.ProtocolTCP

	// build svcPorts (service ports)
	for index, element := range ports {
		if element.Protocol == "UDP" {
			protocol = v1.ProtocolUDP
		}

		// Name is required because k8s requires each port have a name for
		// services with multiple ports
		var sp = v1.ServicePort{
			Name:     slugify.Slugify(fmt.Sprintf("%v-%v", element.Protocol, element.Port)),
			Protocol: protocol,
			Port:     int32(element.Port),
		}

		svcPorts[index] = sp
	}

	// k8s requires that services with multiple ports that each port have a name
	name := fmt.Sprintf(
		"%v-%v",
		environment.Application.Slug,
		environment.Slug,
	)

	service, err := client.GetService("brizo", name)

	if err != nil {
		return false, err
	}

	service.Spec.Ports = svcPorts

	err = client.UpdateService(service)

	if err != nil {
		return false, err
	}

	return true, err
}

// GetEnvironment will get an existing Environment by id
func GetEnvironment(db *gorm.DB, id string) (*Environment, error) {
	environment := new(Environment)
	if err := db.Preload("Application").Where("uuid = ?", id).First(&environment).Error; err != nil {
		return environment, err
	}

	if environment.ID == 0 {
		return new(Environment), errors.New("not-found")
	}

	return environment, nil
}

// DeleteEnvironment will delete an existing Environment by name
func DeleteEnvironment(db *gorm.DB, name string) (bool, error) {
	result := db.Delete(Environment{}, "name = ?", name)

	return result.RowsAffected == 1, result.Error
}
<commit_msg>removed unnecessary comment<commit_after>package resources

import (
	"errors"
	"fmt"

	"k8s.io/client-go/pkg/api/v1"

	"github.com/Machiel/slugify"
	"github.com/generationtux/brizo/database"
	"github.com/generationtux/brizo/kube"
	"github.com/jinzhu/gorm"
	"github.com/pborman/uuid"
)

// Environment as defined by Brizo.
type Environment struct {
	database.Model
	UUID          string      `gorm:"not null;unique_index" sql:"type:varchar(36)" json:"uuid"`
	Name          string      `gorm:"not null" json:"name"`
	Slug          string      `gorm:"not null" json:"slug"`
	ApplicationID uint64      `json:"application_id,string"`
	Application   Application `json:"application,array"`
	Versions      []Version   `json:"versions,array"`
}

// BeforeCreate is a hook that runs before inserting a new record into the
// database
func (environment *Environment) BeforeCreate() (err error) {
	if environment.UUID == "" {
		environment.UUID = uuid.New()
	}
	if environment.Slug == "" {
		environment.Slug = slugify.Slugify(environment.Name)
	}
	return
}

// AllEnvironments will return all of the Environments
func AllEnvironments(db *gorm.DB) ([]Environment, error) {
	var environments []Environment
	result := db.Find(&environments)

	return environments, result.Error
}

// CreateEnvironment will add a new Environment to Brizo
func CreateEnvironment(db *gorm.DB, client kube.APIInterface, environment *Environment, application *Application) (bool, error) {
	result := db.Create(&environment)
	service := environmentServiceDefinition(environment, application)
	err := client.CreateService(service)
	if err != nil {
		// @TODO need a better way to handle some of this upstream
		DeleteEnvironment(db, environment.Name)
		return false, err
	}

	return result.RowsAffected == 1, result.Error
}

func environmentServiceDefinition(environment *Environment, application *Application) *v1.Service {
	name := fmt.Sprintf(
		"%v-%v",
		application.Slug,
		environment.Slug,
	)
	return &v1.Service{
		ObjectMeta: v1.ObjectMeta{
			Name:      name,
			Namespace: "brizo",
			Labels: map[string]string{
				"brizoManaged": "true",
				"appUUID":      application.UUID,
				"envUUID":      environment.UUID,
			},
		},
		//@TODO allow for multiple ports creations
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{
				v1.ServicePort{
					Protocol: v1.ProtocolTCP,
					Port:     int32(80),
				},
			},
		},
	}
}

// UpdateEnvironment will update an existing Environment
func UpdateEnvironment(db *gorm.DB, environment *Environment) (bool, error) {
	environment.Slug = slugify.Slugify(environment.Name)
	result := db.Model(environment).Where("uuid = ?", environment.UUID).
		UpdateColumns(environment)

	return result.RowsAffected == 1, result.Error
}

// UpdateEnvironmentService will update an existing Environment's service in K8s
func UpdateEnvironmentService(db *gorm.DB, client kube.APIInterface, environment *Environment, ports []ContainerPort) (bool, error) {
	var svcPorts = make([]v1.ServicePort, len(ports))
	var protocol = v1.ProtocolTCP

	// build svcPorts (service ports)
	for index, element := range ports {
		if element.Protocol == "UDP" {
			protocol = v1.ProtocolUDP
		}

		// Name is required because k8s requires each port have a name for
		// services with multiple ports
		var sp = v1.ServicePort{
			Name:     slugify.Slugify(fmt.Sprintf("%v-%v", element.Protocol, element.Port)),
			Protocol: protocol,
			Port:     int32(element.Port),
		}

		svcPorts[index] = sp
	}

	name := fmt.Sprintf(
		"%v-%v",
		environment.Application.Slug,
		environment.Slug,
	)

	service, err := client.GetService("brizo", name)

	if err != nil {
		return false, err
	}

	service.Spec.Ports = svcPorts

	err = client.UpdateService(service)

	if err != nil {
		return false, err
	}

	return true, err
}

// GetEnvironment will get an existing Environment by id
func GetEnvironment(db *gorm.DB, id string) (*Environment, error) {
	environment := new(Environment)
	if err := db.Preload("Application").Where("uuid = ?", id).First(&environment).Error; err != nil {
		return environment, err
	}

	if environment.ID == 0 {
		return new(Environment), errors.New("not-found")
	}

	return environment, nil
}

// DeleteEnvironment will delete an existing Environment by name
func DeleteEnvironment(db *gorm.DB, name string) (bool, error) {
	result := db.Delete(Environment{}, "name = ?", name)

	return result.RowsAffected == 1, result.Error
}
<|endoftext|>


<commit_before>package vcs

//go:generate protoc -I../../../.. -I../../../../github.com/gogo/protobuf/protobuf -I. --gogo_out=. vcs.proto
<commit_msg>Make go generate directives work on more setups.<commit_after>package vcs

//go:generate gopathexec protoc -I$GOPATH/src -I$GOPATH/src/github.com/gogo/protobuf/protobuf -I. --gogo_out=. vcs.proto
<|endoftext|>


<commit_before>package printer

import (
	"fmt"
	"github.com/briandowns/spinner"
	"github.com/quintilesims/layer0/common/models"
	"github.com/quintilesims/layer0/common/types"
	"github.com/ryanuber/columnize"
	"os"
	"strings"
	"time"
)

const TIME_FORMAT = "2006-01-02 15:04:05"

type TextPrinter struct {
	spinner *spinner.Spinner
}

func (t *TextPrinter) StartSpinner(prefix string) {
	if t.spinner != nil {
		t.spinner.Stop()
	}

	t.spinner = spinner.New(spinner.CharSets[26], 1*time.Second)
	t.spinner.Prefix = prefix
	t.spinner.Start()
}

func (t *TextPrinter) StopSpinner() {
	if t.spinner != nil {
		t.spinner.Stop()
		fmt.Println()
	}
}

func (t *TextPrinter) Printf(format string, tokens ...interface{}) {
	t.StopSpinner()
	fmt.Printf(format, tokens...)
}

func (t *TextPrinter) Fatalf(code int64, format string, tokens ...interface{}) {
	t.Printf(format, tokens...)
	fmt.Println()
	os.Exit(1)
}

func (t *TextPrinter) PrintDeploys(deploys ...*models.Deploy) error {
	rows := []string{"DEPLOY ID | DEPLOY NAME | VERSION"}
	for _, d := range deploys {
		row := fmt.Sprintf("%s | %s |  %s",
			d.DeployID,
			d.DeployName,
			d.Version)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintDeploySummaries(deploys ...*models.DeploySummary) error {
	rows := []string{"DEPLOY ID | DEPLOY NAME | VERSION"}
	for _, d := range deploys {
		row := fmt.Sprintf("%s | %s |  %s",
			d.DeployID,
			d.DeployName,
			d.Version)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintEnvironments(environments ...*models.Environment) error {
	rows := []string{"ENVIRONMENT ID | ENVIRONMENT NAME | CLUSTER COUNT | INSTANCE SIZE"}
	for _, e := range environments {
		row := fmt.Sprintf("%s | %s | %d | %s",
			e.EnvironmentID,
			e.EnvironmentName,
			e.ClusterCount,
			e.InstanceSize)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintEnvironmentSummaries(environments ...*models.EnvironmentSummary) error {
	rows := []string{"ENVIRONMENT ID | ENVIRONMENT NAME"}
	for _, e := range environments {
		row := fmt.Sprintf("%s | %s",
			e.EnvironmentID,
			e.EnvironmentName)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintJobs(jobs ...*models.Job) error {
	getType := func(j *models.Job) string {
		jobType := types.JobType(j.JobType).String()
		return strings.Title(jobType)
	}

	getStatus := func(j *models.Job) string {
		jobStatus := types.JobStatus(j.JobStatus).String()
		return strings.Title(jobStatus)
	}

	rows := []string{"JOB ID | TASK ID | TYPE | STATUS | CREATED"}
	for _, j := range jobs {
		row := fmt.Sprintf("%s | %s | %s | %s | %s",
			j.JobID,
			j.TaskID,
			getType(j),
			getStatus(j),
			j.TimeCreated.Format(TIME_FORMAT))

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintLoadBalancers(loadBalancers ...*models.LoadBalancer) error {
	getEnvironment := func(l *models.LoadBalancer) string {
		if l.EnvironmentName != "" {
			return l.EnvironmentName
		}

		return l.EnvironmentID
	}

	getService := func(l *models.LoadBalancer) string {
		if l.ServiceName == "" {
			return l.ServiceName
		}

		return l.ServiceID
	}

	getPort := func(l *models.LoadBalancer, i int) string {
		if len(l.Ports) < i-1 {
			return ""
		}

		p := l.Ports[i]
		return fmt.Sprintf("%d:%d/%s", p.HostPort, p.ContainerPort, strings.ToUpper(p.Protocol))
	}

	rows := []string{"LOADBALANCER ID | LOADBALANCER NAME | ENVIRONMENT | SERVICE | PORTS | PUBLIC | URL "}
	for _, l := range loadBalancers {
		row := fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s",
			l.LoadBalancerID,
			l.LoadBalancerName,
			getEnvironment(l),
			getService(l),
			getPort(l, 0),
			l.IsPublic,
			l.URL)

		rows = append(rows, row)

		// add the extra port rows
		for i := 1; i < len(l.Ports); i++ {
			row := fmt.Sprintf(" | | | | %s | |", getPort(l, i))
			rows = append(rows, row)
		}
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintLogs(logs ...*models.LogFile) error {
	for _, l := range logs {
		fmt.Println(l.Name)
		for i := 0; i < len(l.Name); i++ {
			fmt.Printf("-")
		}

		fmt.Println()
		for _, line := range l.Lines {
			fmt.Println(line)
		}
		fmt.Println()
	}

	return nil
}

func (t *TextPrinter) PrintServices(services ...*models.Service) error {
	getEnvironment := func(s *models.Service) string {
		if s.EnvironmentName != "" {
			return s.EnvironmentName
		}

		return s.EnvironmentID
	}

	getLoadBalancer := func(s *models.Service) string {
		if s.LoadBalancerName == "" {
			return s.LoadBalancerName
		}

		return s.LoadBalancerID
	}

	getDeployment := func(s *models.Service, i int) string {
		if len(s.Deployments) < i-1 {
			return ""
		}

		deployment := s.Deployments[i]
		display := strings.Replace(deployment.DeployID, ".", ":", 1)
		if deployment.DeployName != "" && deployment.DeployVersion != "" {
			display = fmt.Sprintf("%s:%s", deployment.DeployName, deployment.DeployVersion)
		}

		if deployment.RunningCount != deployment.DesiredCount {
			display = fmt.Sprintf("%s*", display)
		}

		return display
	}

	getScale := func(s *models.Service) string {
		scale := fmt.Sprintf("%d/%d", s.RunningCount, s.DesiredCount)
		if s.PendingCount != 0 {
			scale = fmt.Sprintf("%s (%d)", scale, s.PendingCount)
		}

		return scale
	}

	rows := []string{"SERVICE ID | SERVICE NAME | ENVIRONMENT | LOADBALANCER | DEPLOYMENTS | SCALE "}
	for _, s := range services {
		row := fmt.Sprintf("%s | %s | %s | %s | %s | %s",
			s.ServiceID,
			s.ServiceName,
			getEnvironment(s),
			getLoadBalancer(s),
			getDeployment(s, 0),
			getScale(s))

		rows = append(rows, row)

		// add the extra deployment rows
		for i := 1; i < len(s.Deployments); i++ {
			row := fmt.Sprintf(" | | | %s", getDeployment(s, i))
			rows = append(rows, row)
		}
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintTasks(tasks ...*models.Task) error {
	getEnvironment := func(t *models.Task) string {
		if t.EnvironmentName != "" {
			return t.EnvironmentName
		}

		return t.EnvironmentID
	}

	getScale := func(t *models.Task) string {
		scale := fmt.Sprintf("%d/%d", t.RunningCount, t.DesiredCount)
		if t.PendingCount != 0 {
			scale = fmt.Sprintf("%s (%d)", scale, t.PendingCount)
		}

		return scale
	}

	getDeploy := func(t *models.Task) string {
		if t.DeployName != "" && t.DeployVersion != "" {
			return fmt.Sprintf("%s:%s", t.DeployName, t.DeployVersion)
		}

		return strings.Replace(t.DeployID, ".", ":", 1)
	}

	rows := []string{"TASK ID | TASK NAME | ENVIRONMENT | DEPLOY | SCALE "}
	for _, t := range tasks {
		row := fmt.Sprintf("%s | %s | %s | %s | %s",
			t.TaskID,
			t.TaskName,
			getEnvironment(t),
			getDeploy(t),
			getScale(t))

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}
<commit_msg>put one-liner in environment printing<commit_after>package printer

import (
	"fmt"
	"github.com/briandowns/spinner"
	"github.com/quintilesims/layer0/common/models"
	"github.com/quintilesims/layer0/common/types"
	"github.com/ryanuber/columnize"
	"os"
	"strings"
	"time"
)

const TIME_FORMAT = "2006-01-02 15:04:05"

type TextPrinter struct {
	spinner *spinner.Spinner
}

func (t *TextPrinter) StartSpinner(prefix string) {
	if t.spinner != nil {
		t.spinner.Stop()
	}

	t.spinner = spinner.New(spinner.CharSets[26], 1*time.Second)
	t.spinner.Prefix = prefix
	t.spinner.Start()
}

func (t *TextPrinter) StopSpinner() {
	if t.spinner != nil {
		t.spinner.Stop()
		fmt.Println()
	}
}

func (t *TextPrinter) Printf(format string, tokens ...interface{}) {
	t.StopSpinner()
	fmt.Printf(format, tokens...)
}

func (t *TextPrinter) Fatalf(code int64, format string, tokens ...interface{}) {
	t.Printf(format, tokens...)
	fmt.Println()
	os.Exit(1)
}

func (t *TextPrinter) PrintDeploys(deploys ...*models.Deploy) error {
	rows := []string{"DEPLOY ID | DEPLOY NAME | VERSION"}
	for _, d := range deploys {
		row := fmt.Sprintf("%s | %s |  %s",
			d.DeployID,
			d.DeployName,
			d.Version)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintDeploySummaries(deploys ...*models.DeploySummary) error {
	rows := []string{"DEPLOY ID | DEPLOY NAME | VERSION"}
	for _, d := range deploys {
		row := fmt.Sprintf("%s | %s |  %s",
			d.DeployID,
			d.DeployName,
			d.Version)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintEnvironments(environments ...*models.Environment) error {
	rows := []string{"ENVIRONMENT ID | ENVIRONMENT NAME | CLUSTER COUNT | INSTANCE SIZE"}
	for _, e := range environments {
		row := fmt.Sprintf("%s | %s | %d | %s",
			e.EnvironmentID,
			e.EnvironmentName,
			e.ClusterCount,
			e.InstanceSize)

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintEnvironmentSummaries(environments ...*models.EnvironmentSummary) error {
	rows := []string{"ENVIRONMENT ID | ENVIRONMENT NAME"}
	for _, e := range environments {
		row := fmt.Sprintf("%s | %s", e.EnvironmentID, e.EnvironmentName)
		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintJobs(jobs ...*models.Job) error {
	getType := func(j *models.Job) string {
		jobType := types.JobType(j.JobType).String()
		return strings.Title(jobType)
	}

	getStatus := func(j *models.Job) string {
		jobStatus := types.JobStatus(j.JobStatus).String()
		return strings.Title(jobStatus)
	}

	rows := []string{"JOB ID | TASK ID | TYPE | STATUS | CREATED"}
	for _, j := range jobs {
		row := fmt.Sprintf("%s | %s | %s | %s | %s",
			j.JobID,
			j.TaskID,
			getType(j),
			getStatus(j),
			j.TimeCreated.Format(TIME_FORMAT))

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintLoadBalancers(loadBalancers ...*models.LoadBalancer) error {
	getEnvironment := func(l *models.LoadBalancer) string {
		if l.EnvironmentName != "" {
			return l.EnvironmentName
		}

		return l.EnvironmentID
	}

	getService := func(l *models.LoadBalancer) string {
		if l.ServiceName == "" {
			return l.ServiceName
		}

		return l.ServiceID
	}

	getPort := func(l *models.LoadBalancer, i int) string {
		if len(l.Ports) < i-1 {
			return ""
		}

		p := l.Ports[i]
		return fmt.Sprintf("%d:%d/%s", p.HostPort, p.ContainerPort, strings.ToUpper(p.Protocol))
	}

	rows := []string{"LOADBALANCER ID | LOADBALANCER NAME | ENVIRONMENT | SERVICE | PORTS | PUBLIC | URL "}
	for _, l := range loadBalancers {
		row := fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s",
			l.LoadBalancerID,
			l.LoadBalancerName,
			getEnvironment(l),
			getService(l),
			getPort(l, 0),
			l.IsPublic,
			l.URL)

		rows = append(rows, row)

		// add the extra port rows
		for i := 1; i < len(l.Ports); i++ {
			row := fmt.Sprintf(" | | | | %s | |", getPort(l, i))
			rows = append(rows, row)
		}
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintLogs(logs ...*models.LogFile) error {
	for _, l := range logs {
		fmt.Println(l.Name)
		for i := 0; i < len(l.Name); i++ {
			fmt.Printf("-")
		}

		fmt.Println()
		for _, line := range l.Lines {
			fmt.Println(line)
		}
		fmt.Println()
	}

	return nil
}

func (t *TextPrinter) PrintServices(services ...*models.Service) error {
	getEnvironment := func(s *models.Service) string {
		if s.EnvironmentName != "" {
			return s.EnvironmentName
		}

		return s.EnvironmentID
	}

	getLoadBalancer := func(s *models.Service) string {
		if s.LoadBalancerName == "" {
			return s.LoadBalancerName
		}

		return s.LoadBalancerID
	}

	getDeployment := func(s *models.Service, i int) string {
		if len(s.Deployments) < i-1 {
			return ""
		}

		deployment := s.Deployments[i]
		display := strings.Replace(deployment.DeployID, ".", ":", 1)
		if deployment.DeployName != "" && deployment.DeployVersion != "" {
			display = fmt.Sprintf("%s:%s", deployment.DeployName, deployment.DeployVersion)
		}

		if deployment.RunningCount != deployment.DesiredCount {
			display = fmt.Sprintf("%s*", display)
		}

		return display
	}

	getScale := func(s *models.Service) string {
		scale := fmt.Sprintf("%d/%d", s.RunningCount, s.DesiredCount)
		if s.PendingCount != 0 {
			scale = fmt.Sprintf("%s (%d)", scale, s.PendingCount)
		}

		return scale
	}

	rows := []string{"SERVICE ID | SERVICE NAME | ENVIRONMENT | LOADBALANCER | DEPLOYMENTS | SCALE "}
	for _, s := range services {
		row := fmt.Sprintf("%s | %s | %s | %s | %s | %s",
			s.ServiceID,
			s.ServiceName,
			getEnvironment(s),
			getLoadBalancer(s),
			getDeployment(s, 0),
			getScale(s))

		rows = append(rows, row)

		// add the extra deployment rows
		for i := 1; i < len(s.Deployments); i++ {
			row := fmt.Sprintf(" | | | %s", getDeployment(s, i))
			rows = append(rows, row)
		}
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}

func (t *TextPrinter) PrintTasks(tasks ...*models.Task) error {
	getEnvironment := func(t *models.Task) string {
		if t.EnvironmentName != "" {
			return t.EnvironmentName
		}

		return t.EnvironmentID
	}

	getScale := func(t *models.Task) string {
		scale := fmt.Sprintf("%d/%d", t.RunningCount, t.DesiredCount)
		if t.PendingCount != 0 {
			scale = fmt.Sprintf("%s (%d)", scale, t.PendingCount)
		}

		return scale
	}

	getDeploy := func(t *models.Task) string {
		if t.DeployName != "" && t.DeployVersion != "" {
			return fmt.Sprintf("%s:%s", t.DeployName, t.DeployVersion)
		}

		return strings.Replace(t.DeployID, ".", ":", 1)
	}

	rows := []string{"TASK ID | TASK NAME | ENVIRONMENT | DEPLOY | SCALE "}
	for _, t := range tasks {
		row := fmt.Sprintf("%s | %s | %s | %s | %s",
			t.TaskID,
			t.TaskName,
			getEnvironment(t),
			getDeploy(t),
			getScale(t))

		rows = append(rows, row)
	}

	fmt.Println(columnize.SimpleFormat(rows))
	return nil
}
<|endoftext|>


<commit_before>// Package bourbon is a package for rapidly developing JSON web services.
//
//   b := bourbon.New()
//   b.Get("/", func() bourbon.Encodeable {
//     var resource struct {
//       Name string
//     }
//
//     return resource
//   })
//
//   bourbon.Run(b)
package bourbon

import "os"

type bourbon struct {
	parent	Bourbon
	prefix     string
	routes     []Route
	middleware []Handler
	children   []Bourbon
}

var (
	defaultPort        string = os.Getenv("PORT")
	defaultRouter      Router = &router{routes: make(map[string][]Route)}
	defaultServer      Server = new(server)
	defaultCreateRoute        = createRoute
)

// New allocates a new Bourbon.
func New() Bourbon {
	b := new(bourbon)
	b.Use(ContentTypeHandler)
	b.Use(DecodeHandler)

	return b
}

// Run combines all Bourbons into a Server and runs the server. Use Run with one
// or more Bourbons to keep the API modular and composable.
func Run(bourbons ...Bourbon) {
}

// SetRouter accepts a struct that implements that Router interface and replaces
// Bourbon's default router.
func SetRouter(rt Router) {
	defaultRouter = rt
}

// SetServer accepts a struct that implements that Server interface and replaces
// Bourbon's default Server.
func SetServer(s Server) {
	defaultServer = s
}

// SetPort accepts a port as a string and overrides the default port "5000". The
// default port can also be overwritten by setting the environment variable PORT
// to the desired value.
func SetPort(p string) {
	defaultPort = p
}

func (b *bourbon) SetParent(parent Bourbon) {
	b.parent = parent
}

func (b *bourbon) Parent() Bourbon {
	return b.parent
}

func (b *bourbon) Children() []Bourbon {
	return b.children
}

func (b *bourbon) Mount(child Bourbon) {
	child.SetParent(b)
	b.children = append(b.children, child)
}

func (b *bourbon) SetPrefix(prefix string) {
	b.prefix = prefix
}

func (b *bourbon) Prefix() string {
	return b.prefix
}

func (b *bourbon) Routes() []Route {
	return b.routes
}

func (b *bourbon) Middleware() []Handler {
	if b.Parent() == nil {
		return b.middleware
	}

	return append(b.Parent().Middleware(), b.middleware)
}

func (b *bourbon) Use(middleware ...Handler) {
	b.middleware = append(b.middleware, middleware...)
}

func (b *bourbon) Get(pattern string, fn Handler) {
	b.addRoute("GET", pattern, fn)
}

func (b *bourbon) Put(pattern string, fn Handler) {
	b.addRoute("PUT", pattern, fn)
}

func (b *bourbon) Post(pattern string, fn Handler) {
	b.addRoute("POST", pattern, fn)
}

func (b *bourbon) Head(pattern string, fn Handler) {
	b.addRoute("HEAD", pattern, fn)
}

func (b *bourbon) Patch(pattern string, fn Handler) {
	b.addRoute("PATCH", pattern, fn)
}

func (b *bourbon) Delete(pattern string, fn Handler) {
	b.addRoute("DELETE", pattern, fn)
}

func (b *bourbon) Run() {
	appendRoute(defaultServer.Router(), b)
	defaultServer.Run()
}

func (b *bourbon) addRoute(method, pattern string, fn Handler) {
	r := defaultCreateRoute(method, pattern, fn)
	r.SetParent(b)
	b.routes = append(b.routes, r)
}

func appendRoute(r Router, b Bourbon) {
	r.Add(b.Routes()...)

	for _, child := range b.Children() {
		appendRoute(r, child)
	}
}
<commit_msg>remove package level Run function and update docs<commit_after>// Package bourbon is a package for rapidly developing JSON web services.
//
//   b := bourbon.New()
//   b.Get("/", func() bourbon.Encodeable {
//     var resource struct {
//       Name string
//     }
//
//     return resource
//   })
//
//   b.Run(b)
package bourbon

import "os"

type bourbon struct {
	parent	Bourbon
	prefix     string
	routes     []Route
	middleware []Handler
	children   []Bourbon
}

var (
	defaultPort        string = os.Getenv("PORT")
	defaultRouter      Router = &router{routes: make(map[string][]Route)}
	defaultServer      Server = new(server)
	defaultCreateRoute        = createRoute
)

// New allocates a new Bourbon.
func New() Bourbon {
	b := new(bourbon)
	b.Use(ContentTypeHandler)
	b.Use(DecodeHandler)

	return b
}

// SetRouter accepts a struct that implements that Router interface and replaces
// Bourbon's default router.
func SetRouter(rt Router) {
	defaultRouter = rt
}

// SetServer accepts a struct that implements that Server interface and replaces
// Bourbon's default Server.
func SetServer(s Server) {
	defaultServer = s
}

// SetPort accepts a port as a string and overrides the default port "5000". The
// default port can also be overwritten by setting the environment variable PORT
// to the desired value.
func SetPort(p string) {
	defaultPort = p
}

func (b *bourbon) SetParent(parent Bourbon) {
	b.parent = parent
}

func (b *bourbon) Parent() Bourbon {
	return b.parent
}

func (b *bourbon) Children() []Bourbon {
	return b.children
}

func (b *bourbon) Mount(child Bourbon) {
	child.SetParent(b)
	b.children = append(b.children, child)
}

func (b *bourbon) SetPrefix(prefix string) {
	b.prefix = prefix
}

func (b *bourbon) Prefix() string {
	return b.prefix
}

func (b *bourbon) Routes() []Route {
	return b.routes
}

func (b *bourbon) Middleware() []Handler {
	if b.Parent() == nil {
		return b.middleware
	}

	return append(b.Parent().Middleware(), b.middleware)
}

func (b *bourbon) Use(middleware ...Handler) {
	b.middleware = append(b.middleware, middleware...)
}

func (b *bourbon) Get(pattern string, fn Handler) {
	b.addRoute("GET", pattern, fn)
}

func (b *bourbon) Put(pattern string, fn Handler) {
	b.addRoute("PUT", pattern, fn)
}

func (b *bourbon) Post(pattern string, fn Handler) {
	b.addRoute("POST", pattern, fn)
}

func (b *bourbon) Head(pattern string, fn Handler) {
	b.addRoute("HEAD", pattern, fn)
}

func (b *bourbon) Patch(pattern string, fn Handler) {
	b.addRoute("PATCH", pattern, fn)
}

func (b *bourbon) Delete(pattern string, fn Handler) {
	b.addRoute("DELETE", pattern, fn)
}

func (b *bourbon) Run() {
	appendRoute(defaultServer.Router(), b)
	defaultServer.Run()
}

func (b *bourbon) addRoute(method, pattern string, fn Handler) {
	r := defaultCreateRoute(method, pattern, fn)
	r.SetParent(b)
	b.routes = append(b.routes, r)
}

func appendRoute(r Router, b Bourbon) {
	r.Add(b.Routes()...)

	for _, child := range b.Children() {
		appendRoute(r, child)
	}
}
<|endoftext|>


<commit_before>package main

const VERSION = "2.0.0"
<commit_msg>version bump v2.0.1<commit_after>package main

const VERSION = "2.0.1"
<|endoftext|>


<commit_before>package main

const Version = "0.13.0"
<commit_msg>bump to v0.14.0-dev<commit_after>package main

const Version = "0.14.0-dev"
<|endoftext|>


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

import (
	"fmt"
	"log"
	"os/exec"
)

const (
    version = "0.0.1"
)

var cmdVersion = &Command{
	UsageLine: "version",
	Short:     "show the lbgo and Go version",
	Long: `
show the lbgo and Go version

bee version
    lbgo  :0.0.1
    Go    :go version go1.5 darwin/amd64

`,
}

func init() {
	cmdVersion.Run = versionCmd
}

func versionCmd(cmd *Command, args []string) int {
	fmt.Println("lbgo   :" + version)
	goversion, err := exec.Command("go", "version").Output()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Go    :" + string(goversion))
	return 0
}
<commit_msg>format output<commit_after>// Copyright 2015 mint.zhao.chiu@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package main

import (
	"fmt"
	"log"
	"os/exec"
)

const (
    version = "0.0.1"
)

var cmdVersion = &Command{
	UsageLine: "version",
	Short:     "show the lbgo and Go version",
	Long: `
show the lbgo and Go version

bee version
    lbgo  :0.0.1
    Go    :go version go1.5 darwin/amd64

`,
}

func init() {
	cmdVersion.Run = versionCmd
}

func versionCmd(cmd *Command, args []string) int {
	fmt.Println("lbgo  :" + version)
	goversion, err := exec.Command("go", "version").Output()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Go    :" + string(goversion))
	return 0
}
<|endoftext|>


<commit_before>package main

var version = "0.2.2"
<commit_msg>bump version<commit_after>package main

var version = "0.2.3"
<|endoftext|>


<commit_before>//
// Copyright © 2016 Guy M. Allard
//
// 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 stompngo

/*
	Provide package version information.  A nod to the concept of semver.

	Example:
		fmt.Println("current stompngo version", stompngo.Version())

*/

import (
	"fmt"
)

var (
	pref = "v" // Prefix

	major = "1" // Major

	minor = "0" // Minor

	//patch = "4" // Patch

	patch = "4.plvl.007" // Patch
)

func Version() string {
	return fmt.Sprintf("%s%s.%s.%s", pref, major, minor, patch)
}
<commit_msg>Version bump.<commit_after>//
// Copyright © 2016 Guy M. Allard
//
// 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 stompngo

/*
	Provide package version information.  A nod to the concept of semver.

	Example:
		fmt.Println("current stompngo version", stompngo.Version())

*/

import (
	"fmt"
)

var (
	pref = "v" // Prefix

	major = "1" // Major

	minor = "0" // Minor

	patch = "5" // Patch

	//patch = "5.plvl.001" // Patch
)

func Version() string {
	return fmt.Sprintf("%s%s.%s.%s", pref, major, minor, patch)
}
<|endoftext|>


<commit_before>package main

const Version = "0.1.11"
<commit_msg>feat(version): bump<commit_after>package main

const Version = "0.1.12"
<|endoftext|>


<commit_before>//

// tcp echo client/server for go lang runtime findrunnable example

package main

import (
	"encoding/binary"
	"fmt"
	"net"
	"sync/atomic"
	"time"
)

// state machine for echo server/client
const (
	STATE_INIT_SEQ int = iota
	STATE_READ_RESET
	STATE_WRITE_RESET
	STATE_WRITE_SEQ
	STATE_READ_SEQ
)

// uint64 size is 8
const IDENTIFY_SIZE int = 8

//
type Echo struct {
	isclient     bool
	title        string
	seq          *uint64
	connected    *int64
	disconnected *int64
	request      *int64
	response     *int64
	closing      bool
}

//
func NewEcho(isclient bool) *Echo {
	var seq uint64
	var connected, disconnected, request, response int64
	var title string
	if isclient {
		title = "tcp echo client"
	} else {
		title = "tcp echo server"
	}
	p := &Echo{
		title:        title,
		isclient:     isclient,
		seq:          &seq,
		connected:    &connected,
		disconnected: &disconnected,
		request:      &request,
		response:     &response,
	}
	go p.stat(10)
	return p
}

// stat
func (p *Echo) stat(interval int) {
	tk := time.NewTicker(time.Duration(interval) * time.Second)
	defer tk.Stop()
	var connected, disconnected, request, response int64
	var preconnected, predisconnected, prerequest, preresponse int64
	prets := time.Now()
	timesecond := int64(time.Second)
	for p.closing == false {
		connected = atomic.LoadInt64(p.connected)
		disconnected = atomic.LoadInt64(p.disconnected)
		request = atomic.LoadInt64(p.request)
		response = atomic.LoadInt64(p.response)
		if connected != preconnected || disconnected != predisconnected || request != prerequest || response != preresponse {
			esp := time.Now().Sub(prets)
			fmt.Printf(" --- %s status(%v) --- \n", p.title, esp)
			fmt.Printf("connected:\t%d,\t%d\n", connected, (connected-preconnected)*timesecond/int64(esp))
			fmt.Printf("disconnected:\t%d,\t%d\n", disconnected, (disconnected-predisconnected)*timesecond/int64(esp))
			fmt.Printf("request:\t%d,\t%d\n", request, (request-prerequest)*timesecond/int64(esp))
			fmt.Printf("response:\t%d,\t%d\n", response, (connected-preresponse)*timesecond/int64(esp))
			fmt.Printf(" --- --- \n")
		}
		preconnected = connected
		predisconnected = disconnected
		prerequest = request
		preresponse = response
		prets = time.Now()
		<-tk.C
	}
}

// OnConnected
func (p *Echo) OnConnected(link *net.TCPConn) error {
	atomic.AddInt64(p.connected, 1)
	defer atomic.AddInt64(p.disconnected, 1)
	if p.isclient {
		return p.client(link)
	}
	return p.server(link)
}

// client send seq and read+verify response
func (p *Echo) client(link *net.TCPConn) error {
	var err error
	var seq, vseq uint64
	var state int
	var totalByteIn, byteIn, totalByteOut, byteOut int

	var echobuf = make([]byte, IDENTIFY_SIZE)

	state = STATE_INIT_SEQ

	for p.closing == false {
		switch state {
		case STATE_INIT_SEQ:
			// seq start from 2, step by 2
			seq = atomic.AddUint64(p.seq, 2)
			vseq = seq + 1
			binary.BigEndian.PutUint64(echobuf, seq)
			state = STATE_WRITE_RESET
			fallthrough
		case STATE_WRITE_RESET:
			byteOut = 0
			totalByteOut = 0
			fallthrough
		case STATE_WRITE_SEQ:
			byteOut, err = link.Write(echobuf[totalByteOut:])
			if err != nil {
				return err
			}
			totalByteOut += byteOut
			if totalByteOut < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.request, 1)
			state = STATE_READ_RESET
			fallthrough
		case STATE_READ_RESET:
			byteIn = 0
			totalByteIn = 0
			fallthrough
		case STATE_READ_SEQ:
			byteIn, err = link.Read(echobuf[totalByteIn:])
			if err != nil {
				return err
			}
			totalByteIn += byteIn
			if totalByteIn < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.response, 1)
			seq = binary.BigEndian.Uint64(echobuf)
			// client side, check response
			if vseq == seq {
				state = STATE_INIT_SEQ
				// next round
				continue
			} else {
				fmt.Printf("client, %s closed for seq mismatch(%d - %d).\n", link.RemoteAddr().String(), vseq, seq)
				return err
			}
		}
	}
	return err
}

// server
func (p *Echo) server(link *net.TCPConn) error {
	var err error
	var seq uint64
	var state int
	var totalByteIn, byteIn, totalByteOut, byteOut int

	var echobuf = make([]byte, IDENTIFY_SIZE)

	state = STATE_READ_RESET

	for p.closing == false {
		switch state {
		case STATE_READ_RESET:
			byteIn = 0
			totalByteIn = 0
			state = STATE_READ_SEQ
			fallthrough
		case STATE_READ_SEQ:
			byteIn, err = link.Read(echobuf[totalByteIn:])
			if err != nil {
				return err
			}
			totalByteIn += byteIn
			if totalByteIn < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.request, 1)
			seq = binary.BigEndian.Uint64(echobuf)
			if seq < 1 {
				fmt.Printf("server, %s closed for invalid seq(%d).\n", link.RemoteAddr().String(), seq)
				return err
			}
			// server side, seq +1 and send response
			seq++
			binary.BigEndian.PutUint64(echobuf, seq)
			state = STATE_WRITE_RESET
			fallthrough
		case STATE_WRITE_RESET:
			state = STATE_WRITE_SEQ
			byteOut = 0
			totalByteOut = 0
			fallthrough
		case STATE_WRITE_SEQ:
			byteOut, err = link.Write(echobuf[totalByteOut:])
			if err != nil {
				return err
			}
			totalByteOut += byteOut
			if totalByteOut < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.response, 1)
			state = STATE_READ_RESET
			// next round
			continue
		}
	}
	return err
}

// Close all handled connections
func (p *Echo) Close() error {
	p.closing = true
	return nil
}

//

func main() {

}
<commit_msg>mono / duplex = 5<commit_after>//

// tcp echo client/server for go lang runtime findrunnable example

package main

import (
	"encoding/binary"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"sync/atomic"
	"time"

	_ "net/http/pprof"
)

//

func main() {
	var server bool
	var duplex bool
	var help bool
	var hostport, httpprofile string
	var cpus int

	flag.BoolVar(&help, "h", false, "show help")
	flag.BoolVar(&server, "L", false, "run as server, default run as client")
	flag.BoolVar(&duplex, "D", false, "run in duplex mode")
	flag.StringVar(&hostport, "H", "127.0.0.1:5180", "host:port for connect to or listen on")
	flag.StringVar(&httpprofile, "P", "", "host:port for http profile")
	flag.IntVar(&cpus, "C", 0, "running with N CPUs/threads, zero for all cpus")

	flag.Parse()
	if help {
		flag.PrintDefaults()
		os.Exit(1)
	}

	//
	if cpus <= 0 {
		cpus = runtime.NumCPU()
	}
	runtime.GOMAXPROCS(cpus)
	cpus = runtime.GOMAXPROCS(-1)

	p := NewEcho(!server, duplex)

	destAddr, err := net.ResolveTCPAddr("tcp", hostport)
	if err != nil {
		log.Fatalln(err.Error())
	}

	if httpprofile != "" {
		httpProfile(httpprofile)
	}

	var wg sync.WaitGroup

	if server {
		l, err := net.ListenTCP("tcp", destAddr)
		if err != nil {
			log.Fatalln(err.Error())
		}
		for idx := 0; idx < cpus; idx++ {
			// accept
			wg.Add(1)
			go func() {
				defer wg.Done()
				conn, err := l.AcceptTCP()
				if err != nil {
					log.Println(err.Error())
				}
				wg.Add(1)
				go p.server(conn, &wg)
			}()
		}
	} else {
		for idx := 0; idx < cpus; idx++ {
			// dial to
			conn, err := net.DialTCP("tcp", nil, destAddr)
			if err != nil {
				log.Fatalln(err.Error())
			}
			wg.Add(1)
			go p.client(conn, &wg)
		}
	}

	fmt.Printf("%s running on %s, with %d workers, press <CTL+C> to exit ...\n", p.Title(), destAddr.String(), cpus)
	wg.Wait()
	fmt.Printf("all done\n")
}

//
func httpProfile(profileurl string) {
	binpath, _ := filepath.Abs(os.Args[0])
	fmt.Printf("\n http profile: [ http://%s/debug/pprof/ ]\n", profileurl)
	fmt.Printf("\n http://%s/debug/pprof/goroutine?debug=1\n\n", profileurl)
	fmt.Printf("\ngo tool pprof %s http://%s/debug/pprof/profile\n\n", binpath, profileurl)
	fmt.Printf("\ngo tool pprof %s http://%s/debug/pprof/heap\n\n", binpath, profileurl)
	go func() {
		if err := http.ListenAndServe(profileurl, nil); err != nil {
			fmt.Printf("http/pprof: %s\n", err.Error())
			os.Exit(1)
		}
	}()
}

//

// state machine for echo server/client
const (
	STATE_INIT_SEQ int = iota
	STATE_READ_RESET
	STATE_WRITE_RESET
	STATE_WRITE_SEQ
	STATE_READ_SEQ
)

// uint64 size is 8
const IDENTIFY_SIZE int = 8

//
type Echo struct {
	isclient bool
	isduplex bool
	title    string
	seq      *uint64
	request  *int64
	response *int64
}

//
func NewEcho(isclient bool, isduplex bool) *Echo {
	var seq uint64
	var request, response int64
	var title string
	if isclient {
		title = "tcp echo client"
	} else {
		title = "tcp echo server"
	}
	if isduplex {
		title = title + ", duplex mode"
	} else {
		title = title + ", mono mode"
	}
	p := &Echo{
		title:    title,
		isclient: isclient,
		isduplex: isduplex,
		seq:      &seq,
		request:  &request,
		response: &response,
	}
	go p.stat(10)
	return p
}

// Title
func (p *Echo) Title() string {
	return p.title
}

// stat
func (p *Echo) stat(interval int) {
	tk := time.NewTicker(time.Duration(interval) * time.Second)
	defer tk.Stop()
	var request, response int64
	var prerequest, preresponse int64
	prets := time.Now()
	timesecond := int64(time.Second)
	for {
		<-tk.C
		request = atomic.LoadInt64(p.request)
		response = atomic.LoadInt64(p.response)
		if request != prerequest || response != preresponse {
			esp := time.Now().Sub(prets)
			fmt.Printf(" --- %s status(%v) --- \n", p.title, esp)
			fmt.Printf("request:\t%d,\t%d\n", request, (request-prerequest)*timesecond/int64(esp))
			fmt.Printf("response:\t%d,\t%d\n", response, (response-preresponse)*timesecond/int64(esp))
			fmt.Printf(" --- --- \n")
		}
		prerequest = request
		preresponse = response
		prets = time.Now()
	}
}

// client send seq and read+verify response
func (p *Echo) client(link *net.TCPConn, wg *sync.WaitGroup) error {
	defer wg.Done()
	var err error
	var seq, vseq uint64
	var state int
	var totalByteIn, byteIn, totalByteOut, byteOut int

	var echobuf = make([]byte, IDENTIFY_SIZE)

	state = STATE_INIT_SEQ

	for {
		switch state {
		case STATE_INIT_SEQ:
			// seq start from 2, step by 2
			seq = atomic.AddUint64(p.seq, 2)
			vseq = seq + 1
			binary.BigEndian.PutUint64(echobuf, seq)
			state = STATE_WRITE_RESET
			fallthrough
		case STATE_WRITE_RESET:
			byteOut = 0
			totalByteOut = 0
			fallthrough
		case STATE_WRITE_SEQ:
			byteOut, err = link.Write(echobuf[totalByteOut:])
			if err != nil {
				return err
			}
			totalByteOut += byteOut
			if totalByteOut < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.request, 1)
			if p.isduplex == false {
				state = STATE_INIT_SEQ
				continue
			}
			state = STATE_READ_RESET
			fallthrough
		case STATE_READ_RESET:
			byteIn = 0
			totalByteIn = 0
			fallthrough
		case STATE_READ_SEQ:
			byteIn, err = link.Read(echobuf[totalByteIn:])
			if err != nil {
				return err
			}
			totalByteIn += byteIn
			if totalByteIn < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.response, 1)
			seq = binary.BigEndian.Uint64(echobuf)
			// client side, check response
			if vseq == seq {
				state = STATE_INIT_SEQ
				// next round
				continue
			} else {
				fmt.Printf("client, %s closed for seq mismatch(%d - %d).\n", link.RemoteAddr().String(), vseq, seq)
				return err
			}
		}
	}
	return err
}

// server
func (p *Echo) server(link *net.TCPConn, wg *sync.WaitGroup) error {
	defer wg.Done()
	var err error
	var seq uint64
	var state int
	var totalByteIn, byteIn, totalByteOut, byteOut int

	var echobuf = make([]byte, IDENTIFY_SIZE)

	state = STATE_READ_RESET

	for {
		switch state {
		case STATE_READ_RESET:
			byteIn = 0
			totalByteIn = 0
			state = STATE_READ_SEQ
			fallthrough
		case STATE_READ_SEQ:
			byteIn, err = link.Read(echobuf[totalByteIn:])
			if err != nil {
				return err
			}
			totalByteIn += byteIn
			if totalByteIn < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.request, 1)
			seq = binary.BigEndian.Uint64(echobuf)
			if seq < 1 {
				fmt.Printf("server, %s closed for invalid seq(%d).\n", link.RemoteAddr().String(), seq)
				return err
			}
			if p.isduplex == false {
				state = STATE_READ_RESET
				continue
			}
			// server side, seq +1 and send response
			seq++
			binary.BigEndian.PutUint64(echobuf, seq)
			state = STATE_WRITE_RESET
			fallthrough
		case STATE_WRITE_RESET:
			state = STATE_WRITE_SEQ
			byteOut = 0
			totalByteOut = 0
			fallthrough
		case STATE_WRITE_SEQ:
			byteOut, err = link.Write(echobuf[totalByteOut:])
			if err != nil {
				return err
			}
			totalByteOut += byteOut
			if totalByteOut < IDENTIFY_SIZE {
				continue
			}
			atomic.AddInt64(p.response, 1)
			state = STATE_READ_RESET
			// next round
			continue
		}
	}
	return err
}

//
//
//
//
<|endoftext|>


<commit_before>package main

import "fmt"

var (
	Version   = "unset"
	Revision  = "unset"
	Branch    = "unset"
	BuildUser = "unset"
	BuildDate = "unset"
)

func versionStr() string {
	return fmt.Sprintf("%s-%s (from %s, built by %s on %s)", Version, Revision, Branch, BuildUser, BuildDate)
}
<commit_msg>Add metric for build_info<commit_after>package main

import (
	"fmt"
	"runtime"

	"github.com/prometheus/client_golang/prometheus"
)

var (
	Version   = "unset"
	Revision  = "unset"
	Branch    = "unset"
	BuildUser = "unset"
	BuildDate = "unset"
	GoVersion = runtime.Version()
)

var (
	buildInfo = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "build_info",
			Help: "A metric with a constant '1' value labeled by version, revision, branch and goversion from which exporter_exporter was built.",
		},
		[]string{"version", "revision", "branch", "goversion"},
	)
)

func init() {
	prometheus.MustRegister(buildInfo)
	buildInfo.WithLabelValues(Version, Revision, Branch, GoVersion).Set(1)
}

func versionStr() string {
	return fmt.Sprintf("%s-%s (from %s, built by %s on %s)", Version, Revision, Branch, BuildUser, BuildDate)
}
<|endoftext|>


<commit_before>package dsapid

const (
	AppName    string = "Dataset Image Server"
	AppVersion string = "0.6.5"
)
<commit_msg>bump version<commit_after>package dsapid

const (
	AppName    string = "Dataset Image Server"
	AppVersion string = "0.6.6"
)
<|endoftext|>


<commit_before>package swag

// Version of swag.
const Version = "v1.7.8"
<commit_msg>chore: release v1.7.9<commit_after>package swag

// Version of swag.
const Version = "v1.7.9"
<|endoftext|>


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

package main

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

package main

const Version = "0.4.0+git"
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
)

var GitCommit string

const Name = "vault-ssh-helper"
const Version = "0.1.2"
const VersionPrerelease = ""

// formattedVersion returns a formatted version string which includes the git
// commit and development information.
func formattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s v%s", Name, Version)

	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}
	return versionString.String()
}
<commit_msg>version++<commit_after>package main

import (
	"bytes"
	"fmt"
)

var GitCommit string

const Name = "vault-ssh-helper"
const Version = "0.1.3"
const VersionPrerelease = ""

// formattedVersion returns a formatted version string which includes the git
// commit and development information.
func formattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s v%s", Name, Version)

	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}
	return versionString.String()
}
<|endoftext|>


<commit_before>package deploy

const Version = "0.0.3"
<commit_msg>bump version to 0.0.4<commit_after>package deploy

const Version = "0.0.4"
<|endoftext|>


<commit_before>package l10n

import (
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path"
	"strings"

	"github.com/qor/qor"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

var Global = "en-US"

type l10nInterface interface {
	IsGlobal() bool
	SetLocale(locale string)
}

type Locale struct {
	LanguageCode string `sql:"size:6" gorm:"primary_key"`
}

func (l Locale) IsGlobal() bool {
	return l.LanguageCode == Global
}

func (l *Locale) SetLocale(locale string) {
	l.LanguageCode = locale
}

type availableLocalesInterface interface {
	AvailableLocales() []string
}

type viewableLocalesInterface interface {
	ViewableLocales() []string
}

type editableLocalesInterface interface {
	EditableLocales() []string
}

func getAvailableLocales(req *http.Request, currentUser qor.CurrentUser) []string {
	if user, ok := currentUser.(viewableLocalesInterface); ok {
		return user.ViewableLocales()
	}

	if user, ok := currentUser.(availableLocalesInterface); ok {
		return user.AvailableLocales()
	}
	return []string{}
}

func getEditableLocales(req *http.Request, currentUser qor.CurrentUser) []string {
	if user, ok := currentUser.(editableLocalesInterface); ok {
		return user.EditableLocales()
	}

	if user, ok := currentUser.(availableLocalesInterface); ok {
		return user.AvailableLocales()
	}
	return []string{}
}

func getLocaleFromContext(context *qor.Context) string {
	if locale := utils.GetLocale(context); locale != "" {
		return locale
	}

	return Global
}

var injected bool

func (l *Locale) InjectQorAdmin(res *admin.Resource) {
	Admin := res.GetAdmin()
	res.UseTheme("l10n")

	if res.Config.Permission == nil {
		res.Config.Permission = roles.NewPermission()
	}
	res.Config.Permission.Allow(roles.CRUD, "locale_admin").Allow(roles.Read, "locale_reader")

	if res.GetMeta("Localization") == nil {
		res.Meta(&admin.Meta{Name: "Localization", Valuer: func(value interface{}, ctx *qor.Context) interface{} {
			db := ctx.GetDB()
			context := Admin.NewContext(ctx.Writer, ctx.Request)

			var languageCodes []string
			scope := db.NewScope(value)
			db.New().Set("l10n:mode", "unscoped").Model(value).Where(fmt.Sprintf("%v = ?", scope.PrimaryKey()), scope.PrimaryKeyValue()).Pluck("language_code", &languageCodes)

			var results string
			availableLocales := getAvailableLocales(ctx.Request, ctx.CurrentUser)
			primaryKey := context.GetDB().NewScope(value).PrimaryKeyValue()
		OUT:
			for _, locale := range availableLocales {
				url, _ := utils.PatchURL(path.Join(ctx.Request.URL.Path, fmt.Sprintf("%v", primaryKey)), "locale", locale)
				for _, localized := range languageCodes {
					if locale == localized {
						results += fmt.Sprintf("%s ", url, context.T(locale))
						continue OUT
					}
				}
				results += fmt.Sprintf("%s ", url, context.T(locale))
			}
			return template.HTML(results)
		}})

		attrs := res.IndexAttrs()
		var hasLocalization bool
		for _, attr := range attrs {
			if attr == "Localization" {
				hasLocalization = true
				break
			}
		}

		if hasLocalization {
			res.IndexAttrs(append(res.IndexAttrs(), "-LanguageCode")...)
		} else {
			res.IndexAttrs(append(res.IndexAttrs(), "-LanguageCode", "Localization")...)
		}
		res.ShowAttrs(append(res.ShowAttrs(), "-LanguageCode", "-Localization")...)
		res.EditAttrs(append(res.EditAttrs(), "-LanguageCode", "-Localization")...)
		res.NewAttrs(append(res.NewAttrs(), "-LanguageCode", "-Localization")...)
	}

	// Set meta permissions
	for _, field := range Admin.Config.DB.NewScope(res.Value).Fields() {
		if isSyncField(field.StructField) {
			if meta := res.GetMeta(field.Name); meta != nil {
				permission := meta.Permission
				if permission == nil {
					permission = roles.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")
				} else {
					permission = permission.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")
				}

				meta.Permission = permission
			} else {
				res.Meta(&admin.Meta{Name: field.Name, Permission: roles.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")})
			}
		}
	}

	// Roles
	role := res.Config.Permission.Role
	if _, ok := role.Get("locale_admin"); !ok {
		role.Register("locale_admin", func(req *http.Request, currentUser qor.CurrentUser) bool {
			currentLocale := getLocaleFromContext(&qor.Context{Request: req})
			for _, locale := range getEditableLocales(req, currentUser) {
				if locale == currentLocale {
					return true
				}
			}
			return false
		})
	}

	if _, ok := role.Get("global_admin"); !ok {
		role.Register("global_admin", func(req *http.Request, currentUser qor.CurrentUser) bool {
			return getLocaleFromContext(&qor.Context{Request: req}) == Global
		})
	}

	if _, ok := role.Get("locale_reader"); !ok {
		role.Register("locale_reader", func(req *http.Request, currentUser qor.CurrentUser) bool {
			currentLocale := getLocaleFromContext(&qor.Context{Request: req})
			for _, locale := range getAvailableLocales(req, currentUser) {
				if locale == currentLocale {
					return true
				}
			}
			return false
		})
	}

	// Inject for l10n
	if !injected {
		injected = true
		for _, gopath := range strings.Split(os.Getenv("GOPATH"), ":") {
			admin.RegisterViewPath(path.Join(gopath, "src/github.com/qor/qor/l10n/views"))
		}

		// Middleware
		Admin.GetRouter().Use(func(context *admin.Context, middleware *admin.Middleware) {
			context.SetDB(context.GetDB().Set("l10n:locale", getLocaleFromContext(context.Context)))

			middleware.Next(context)
		})

		// FunMap
		Admin.RegisterFuncMap("current_locale", func(context admin.Context) string {
			return getLocaleFromContext(context.Context)
		})

		Admin.RegisterFuncMap("viewable_locales", func(context admin.Context) []string {
			return getAvailableLocales(context.Request, context.CurrentUser)
		})

		Admin.RegisterFuncMap("editable_locales", func(context admin.Context) []string {
			return getEditableLocales(context.Request, context.CurrentUser)
		})

		Admin.RegisterFuncMap("createable_locales", func(context admin.Context) []string {
			editableLocales := getEditableLocales(context.Request, context.CurrentUser)
			if _, ok := context.Resource.Value.(LocaleCreateableInterface); ok {
				return editableLocales
			} else {
				for _, locale := range editableLocales {
					if locale == Global {
						return []string{Global}
					}
				}
			}
			return []string{}
		})
	}
}
<commit_msg>Update label class name<commit_after>package l10n

import (
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path"
	"strings"

	"github.com/qor/qor"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

var Global = "en-US"

type l10nInterface interface {
	IsGlobal() bool
	SetLocale(locale string)
}

type Locale struct {
	LanguageCode string `sql:"size:6" gorm:"primary_key"`
}

func (l Locale) IsGlobal() bool {
	return l.LanguageCode == Global
}

func (l *Locale) SetLocale(locale string) {
	l.LanguageCode = locale
}

type availableLocalesInterface interface {
	AvailableLocales() []string
}

type viewableLocalesInterface interface {
	ViewableLocales() []string
}

type editableLocalesInterface interface {
	EditableLocales() []string
}

func getAvailableLocales(req *http.Request, currentUser qor.CurrentUser) []string {
	if user, ok := currentUser.(viewableLocalesInterface); ok {
		return user.ViewableLocales()
	}

	if user, ok := currentUser.(availableLocalesInterface); ok {
		return user.AvailableLocales()
	}
	return []string{}
}

func getEditableLocales(req *http.Request, currentUser qor.CurrentUser) []string {
	if user, ok := currentUser.(editableLocalesInterface); ok {
		return user.EditableLocales()
	}

	if user, ok := currentUser.(availableLocalesInterface); ok {
		return user.AvailableLocales()
	}
	return []string{}
}

func getLocaleFromContext(context *qor.Context) string {
	if locale := utils.GetLocale(context); locale != "" {
		return locale
	}

	return Global
}

var injected bool

func (l *Locale) InjectQorAdmin(res *admin.Resource) {
	Admin := res.GetAdmin()
	res.UseTheme("l10n")

	if res.Config.Permission == nil {
		res.Config.Permission = roles.NewPermission()
	}
	res.Config.Permission.Allow(roles.CRUD, "locale_admin").Allow(roles.Read, "locale_reader")

	if res.GetMeta("Localization") == nil {
		res.Meta(&admin.Meta{Name: "Localization", Valuer: func(value interface{}, ctx *qor.Context) interface{} {
			db := ctx.GetDB()
			context := Admin.NewContext(ctx.Writer, ctx.Request)

			var languageCodes []string
			scope := db.NewScope(value)
			db.New().Set("l10n:mode", "unscoped").Model(value).Where(fmt.Sprintf("%v = ?", scope.PrimaryKey()), scope.PrimaryKeyValue()).Pluck("language_code", &languageCodes)

			var results string
			availableLocales := getAvailableLocales(ctx.Request, ctx.CurrentUser)
			primaryKey := context.GetDB().NewScope(value).PrimaryKeyValue()
		OUT:
			for _, locale := range availableLocales {
				url, _ := utils.PatchURL(path.Join(ctx.Request.URL.Path, fmt.Sprintf("%v", primaryKey)), "locale", locale)
				for _, localized := range languageCodes {
					if locale == localized {
						results += fmt.Sprintf("%s ", url, context.T(locale))
						continue OUT
					}
				}
				results += fmt.Sprintf("%s ", url, context.T(locale))
			}
			return template.HTML(results)
		}})

		attrs := res.IndexAttrs()
		var hasLocalization bool
		for _, attr := range attrs {
			if attr == "Localization" {
				hasLocalization = true
				break
			}
		}

		if hasLocalization {
			res.IndexAttrs(append(res.IndexAttrs(), "-LanguageCode")...)
		} else {
			res.IndexAttrs(append(res.IndexAttrs(), "-LanguageCode", "Localization")...)
		}
		res.ShowAttrs(append(res.ShowAttrs(), "-LanguageCode", "-Localization")...)
		res.EditAttrs(append(res.EditAttrs(), "-LanguageCode", "-Localization")...)
		res.NewAttrs(append(res.NewAttrs(), "-LanguageCode", "-Localization")...)
	}

	// Set meta permissions
	for _, field := range Admin.Config.DB.NewScope(res.Value).Fields() {
		if isSyncField(field.StructField) {
			if meta := res.GetMeta(field.Name); meta != nil {
				permission := meta.Permission
				if permission == nil {
					permission = roles.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")
				} else {
					permission = permission.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")
				}

				meta.Permission = permission
			} else {
				res.Meta(&admin.Meta{Name: field.Name, Permission: roles.Allow(roles.CRUD, "global_admin").Allow(roles.Read, "locale_reader")})
			}
		}
	}

	// Roles
	role := res.Config.Permission.Role
	if _, ok := role.Get("locale_admin"); !ok {
		role.Register("locale_admin", func(req *http.Request, currentUser qor.CurrentUser) bool {
			currentLocale := getLocaleFromContext(&qor.Context{Request: req})
			for _, locale := range getEditableLocales(req, currentUser) {
				if locale == currentLocale {
					return true
				}
			}
			return false
		})
	}

	if _, ok := role.Get("global_admin"); !ok {
		role.Register("global_admin", func(req *http.Request, currentUser qor.CurrentUser) bool {
			return getLocaleFromContext(&qor.Context{Request: req}) == Global
		})
	}

	if _, ok := role.Get("locale_reader"); !ok {
		role.Register("locale_reader", func(req *http.Request, currentUser qor.CurrentUser) bool {
			currentLocale := getLocaleFromContext(&qor.Context{Request: req})
			for _, locale := range getAvailableLocales(req, currentUser) {
				if locale == currentLocale {
					return true
				}
			}
			return false
		})
	}

	// Inject for l10n
	if !injected {
		injected = true
		for _, gopath := range strings.Split(os.Getenv("GOPATH"), ":") {
			admin.RegisterViewPath(path.Join(gopath, "src/github.com/qor/qor/l10n/views"))
		}

		// Middleware
		Admin.GetRouter().Use(func(context *admin.Context, middleware *admin.Middleware) {
			context.SetDB(context.GetDB().Set("l10n:locale", getLocaleFromContext(context.Context)))

			middleware.Next(context)
		})

		// FunMap
		Admin.RegisterFuncMap("current_locale", func(context admin.Context) string {
			return getLocaleFromContext(context.Context)
		})

		Admin.RegisterFuncMap("viewable_locales", func(context admin.Context) []string {
			return getAvailableLocales(context.Request, context.CurrentUser)
		})

		Admin.RegisterFuncMap("editable_locales", func(context admin.Context) []string {
			return getEditableLocales(context.Request, context.CurrentUser)
		})

		Admin.RegisterFuncMap("createable_locales", func(context admin.Context) []string {
			editableLocales := getEditableLocales(context.Request, context.CurrentUser)
			if _, ok := context.Resource.Value.(LocaleCreateableInterface); ok {
				return editableLocales
			} else {
				for _, locale := range editableLocales {
					if locale == Global {
						return []string{Global}
					}
				}
			}
			return []string{}
		})
	}
}
<|endoftext|>