<commit_before>package aws

import (
	"fmt"
	"log"
	"regexp"
	"strconv"

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

func resourceAwsAlb() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAlbCreate,
		Read:   resourceAwsAlbRead,
		Update: resourceAwsAlbUpdate,
		Delete: resourceAwsAlbDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"arn_suffix": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc:  validateElbName,
			},

			"name_prefix": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				ValidateFunc: validateElbName,
			},

			"internal": {
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"security_groups": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Computed: true,
				Optional: true,
				Set:      schema.HashString,
			},

			"subnets": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				ForceNew: true,
				Required: true,
				Set:      schema.HashString,
			},

			"access_logs": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"bucket": {
							Type:     schema.TypeString,
							Required: true,
						},
						"prefix": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"enabled": {
							Type:     schema.TypeBool,
							Optional: true,
							Default:  true,
						},
					},
				},
			},

			"enable_deletion_protection": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"idle_timeout": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  60,
			},

			"vpc_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"zone_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"dns_name": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		name = resource.PrefixedUniqueId(v.(string))
	} else {
		name = resource.PrefixedUniqueId("tf-lb-")
	}
	d.Set("name", name)

	elbOpts := &elbv2.CreateLoadBalancerInput{
		Name: aws.String(name),
		Tags: tagsFromMapELBv2(d.Get("tags").(map[string]interface{})),
	}

	if scheme, ok := d.GetOk("internal"); ok && scheme.(bool) {
		elbOpts.Scheme = aws.String("internal")
	}

	if v, ok := d.GetOk("security_groups"); ok {
		elbOpts.SecurityGroups = expandStringList(v.(*schema.Set).List())
	}

	if v, ok := d.GetOk("subnets"); ok {
		elbOpts.Subnets = expandStringList(v.(*schema.Set).List())
	}

	log.Printf("[DEBUG] ALB create configuration: %#v", elbOpts)

	resp, err := elbconn.CreateLoadBalancer(elbOpts)
	if err != nil {
		return errwrap.Wrapf("Error creating Application Load Balancer: {{err}}", err)
	}

	if len(resp.LoadBalancers) != 1 {
		return fmt.Errorf("No load balancers returned following creation of %s", d.Get("name").(string))
	}

	d.SetId(*resp.LoadBalancers[0].LoadBalancerArn)
	log.Printf("[INFO] ALB ID: %s", d.Id())

	return resourceAwsAlbUpdate(d, meta)
}

func resourceAwsAlbRead(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn
	albArn := d.Id()

	describeAlbOpts := &elbv2.DescribeLoadBalancersInput{
		LoadBalancerArns: []*string{aws.String(albArn)},
	}

	describeResp, err := elbconn.DescribeLoadBalancers(describeAlbOpts)
	if err != nil {
		if isLoadBalancerNotFound(err) {
			// The ALB is gone now, so just remove it from the state
			log.Printf("[WARN] ALB %s not found in AWS, removing from state", d.Id())
			d.SetId("")
			return nil
		}

		return errwrap.Wrapf("Error retrieving ALB: {{err}}", err)
	}
	if len(describeResp.LoadBalancers) != 1 {
		return fmt.Errorf("Unable to find ALB: %#v", describeResp.LoadBalancers)
	}

	return flattenAwsAlbResource(d, meta, describeResp.LoadBalancers[0])
}

func resourceAwsAlbUpdate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn

	if !d.IsNewResource() {
		if err := setElbV2Tags(elbconn, d); err != nil {
			return errwrap.Wrapf("Error Modifying Tags on ALB: {{err}}", err)
		}
	}

	attributes := make([]*elbv2.LoadBalancerAttribute, 0)

	if d.HasChange("access_logs") {
		logs := d.Get("access_logs").([]interface{})
		if len(logs) == 1 {
			log := logs[0].(map[string]interface{})

			attributes = append(attributes,
				&elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.enabled"),
					Value: aws.String(strconv.FormatBool(log["enabled"].(bool))),
				},
				&elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.bucket"),
					Value: aws.String(log["bucket"].(string)),
				})

			if prefix, ok := log["prefix"]; ok {
				attributes = append(attributes, &elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.prefix"),
					Value: aws.String(prefix.(string)),
				})
			}
		} else if len(logs) == 0 {
			attributes = append(attributes, &elbv2.LoadBalancerAttribute{
				Key:   aws.String("access_logs.s3.enabled"),
				Value: aws.String("false"),
			})
		}
	}

	if d.HasChange("enable_deletion_protection") {
		attributes = append(attributes, &elbv2.LoadBalancerAttribute{
			Key:   aws.String("deletion_protection.enabled"),
			Value: aws.String(fmt.Sprintf("%t", d.Get("enable_deletion_protection").(bool))),
		})
	}

	if d.HasChange("idle_timeout") {
		attributes = append(attributes, &elbv2.LoadBalancerAttribute{
			Key:   aws.String("idle_timeout.timeout_seconds"),
			Value: aws.String(fmt.Sprintf("%d", d.Get("idle_timeout").(int))),
		})
	}

	if len(attributes) != 0 {
		input := &elbv2.ModifyLoadBalancerAttributesInput{
			LoadBalancerArn: aws.String(d.Id()),
			Attributes:      attributes,
		}

		log.Printf("[DEBUG] ALB Modify Load Balancer Attributes Request: %#v", input)
		_, err := elbconn.ModifyLoadBalancerAttributes(input)
		if err != nil {
			return fmt.Errorf("Failure configuring ALB attributes: %s", err)
		}
	}

	if d.HasChange("security_groups") {
		sgs := expandStringList(d.Get("security_groups").(*schema.Set).List())

		params := &elbv2.SetSecurityGroupsInput{
			LoadBalancerArn: aws.String(d.Id()),
			SecurityGroups:  sgs,
		}
		_, err := elbconn.SetSecurityGroups(params)
		if err != nil {
			return fmt.Errorf("Failure Setting ALB Security Groups: %s", err)
		}

	}

	return resourceAwsAlbRead(d, meta)
}

func resourceAwsAlbDelete(d *schema.ResourceData, meta interface{}) error {
	albconn := meta.(*AWSClient).elbv2conn

	log.Printf("[INFO] Deleting ALB: %s", d.Id())

	// Destroy the load balancer
	deleteElbOpts := elbv2.DeleteLoadBalancerInput{
		LoadBalancerArn: aws.String(d.Id()),
	}
	if _, err := albconn.DeleteLoadBalancer(&deleteElbOpts); err != nil {
		return fmt.Errorf("Error deleting ALB: %s", err)
	}

	return nil
}

// flattenSubnetsFromAvailabilityZones creates a slice of strings containing the subnet IDs
// for the ALB based on the AvailabilityZones structure returned by the API.
func flattenSubnetsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []string {
	var result []string
	for _, az := range availabilityZones {
		result = append(result, *az.SubnetId)
	}
	return result
}

func albSuffixFromARN(arn *string) string {
	if arn == nil {
		return ""
	}

	if arnComponents := regexp.MustCompile(`arn:.*:loadbalancer/(.*)`).FindAllStringSubmatch(*arn, -1); len(arnComponents) == 1 {
		if len(arnComponents[0]) == 2 {
			return arnComponents[0][1]
		}
	}

	return ""
}

// flattenAwsAlbResource takes a *elbv2.LoadBalancer and populates all respective resource fields.
func flattenAwsAlbResource(d *schema.ResourceData, meta interface{}, alb *elbv2.LoadBalancer) error {
	elbconn := meta.(*AWSClient).elbv2conn

	d.Set("arn", alb.LoadBalancerArn)
	d.Set("arn_suffix", albSuffixFromARN(alb.LoadBalancerArn))
	d.Set("name", alb.LoadBalancerName)
	d.Set("internal", (alb.Scheme != nil && *alb.Scheme == "internal"))
	d.Set("security_groups", flattenStringList(alb.SecurityGroups))
	d.Set("subnets", flattenSubnetsFromAvailabilityZones(alb.AvailabilityZones))
	d.Set("vpc_id", alb.VpcId)
	d.Set("zone_id", alb.CanonicalHostedZoneId)
	d.Set("dns_name", alb.DNSName)

	respTags, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{
		ResourceArns: []*string{alb.LoadBalancerArn},
	})
	if err != nil {
		return errwrap.Wrapf("Error retrieving ALB Tags: {{err}}", err)
	}

	var et []*elbv2.Tag
	if len(respTags.TagDescriptions) > 0 {
		et = respTags.TagDescriptions[0].Tags
	}
	d.Set("tags", tagsToMapELBv2(et))

	attributesResp, err := elbconn.DescribeLoadBalancerAttributes(&elbv2.DescribeLoadBalancerAttributesInput{
		LoadBalancerArn: aws.String(d.Id()),
	})
	if err != nil {
		return errwrap.Wrapf("Error retrieving ALB Attributes: {{err}}", err)
	}

	accessLogMap := map[string]interface{}{}
	for _, attr := range attributesResp.Attributes {
		switch *attr.Key {
		case "access_logs.s3.enabled":
			accessLogMap["enabled"] = *attr.Value
		case "access_logs.s3.bucket":
			accessLogMap["bucket"] = *attr.Value
		case "access_logs.s3.prefix":
			accessLogMap["prefix"] = *attr.Value
		case "idle_timeout.timeout_seconds":
			timeout, err := strconv.Atoi(*attr.Value)
			if err != nil {
				return errwrap.Wrapf("Error parsing ALB timeout: {{err}}", err)
			}
			log.Printf("[DEBUG] Setting ALB Timeout Seconds: %d", timeout)
			d.Set("idle_timeout", timeout)
		case "deletion_protection.enabled":
			protectionEnabled := (*attr.Value) == "true"
			log.Printf("[DEBUG] Setting ALB Deletion Protection Enabled: %t", protectionEnabled)
			d.Set("enable_deletion_protection", protectionEnabled)
		}
	}

	log.Printf("[DEBUG] Setting ALB Access Logs: %#v", accessLogMap)
	if accessLogMap["bucket"] != "" || accessLogMap["prefix"] != "" {
		d.Set("access_logs", []interface{}{accessLogMap})
	} else {
		d.Set("access_logs", []interface{}{})
	}

	return nil
}
<commit_msg>provider/aws: Wait until ALB is provisioned<commit_after>package aws

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

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

func resourceAwsAlb() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAlbCreate,
		Read:   resourceAwsAlbRead,
		Update: resourceAwsAlbUpdate,
		Delete: resourceAwsAlbDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"arn_suffix": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc:  validateElbName,
			},

			"name_prefix": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				ValidateFunc: validateElbName,
			},

			"internal": {
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"security_groups": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Computed: true,
				Optional: true,
				Set:      schema.HashString,
			},

			"subnets": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				ForceNew: true,
				Required: true,
				Set:      schema.HashString,
			},

			"access_logs": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"bucket": {
							Type:     schema.TypeString,
							Required: true,
						},
						"prefix": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"enabled": {
							Type:     schema.TypeBool,
							Optional: true,
							Default:  true,
						},
					},
				},
			},

			"enable_deletion_protection": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"idle_timeout": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  60,
			},

			"vpc_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"zone_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"dns_name": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		name = resource.PrefixedUniqueId(v.(string))
	} else {
		name = resource.PrefixedUniqueId("tf-lb-")
	}
	d.Set("name", name)

	elbOpts := &elbv2.CreateLoadBalancerInput{
		Name: aws.String(name),
		Tags: tagsFromMapELBv2(d.Get("tags").(map[string]interface{})),
	}

	if scheme, ok := d.GetOk("internal"); ok && scheme.(bool) {
		elbOpts.Scheme = aws.String("internal")
	}

	if v, ok := d.GetOk("security_groups"); ok {
		elbOpts.SecurityGroups = expandStringList(v.(*schema.Set).List())
	}

	if v, ok := d.GetOk("subnets"); ok {
		elbOpts.Subnets = expandStringList(v.(*schema.Set).List())
	}

	log.Printf("[DEBUG] ALB create configuration: %#v", elbOpts)

	resp, err := elbconn.CreateLoadBalancer(elbOpts)
	if err != nil {
		return errwrap.Wrapf("Error creating Application Load Balancer: {{err}}", err)
	}

	if len(resp.LoadBalancers) != 1 {
		return fmt.Errorf("No load balancers returned following creation of %s", d.Get("name").(string))
	}

	lb := resp.LoadBalancers[0]
	d.SetId(*lb.LoadBalancerArn)
	log.Printf("[INFO] ALB ID: %s", d.Id())

	stateConf := &resource.StateChangeConf{
		Pending: []string{"active", "provisioning", "failed"},
		Target:  []string{"active"},
		Refresh: func() (interface{}, string, error) {
			describeResp, err := elbconn.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{
				LoadBalancerArns: []*string{lb.LoadBalancerArn},
			})
			if err != nil {
				return nil, "", err
			}

			if len(describeResp.LoadBalancers) != 1 {
				return nil, "", fmt.Errorf("No load balancers returned for %s", *lb.LoadBalancerArn)
			}
			dLb := describeResp.LoadBalancers[0]

			log.Printf("[INFO] ALB state: %s", *dLb.State.Code)

			return describeResp, *dLb.State.Code, nil
		},
		Timeout:    5 * time.Minute,
		MinTimeout: 3 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	return resourceAwsAlbUpdate(d, meta)
}

func resourceAwsAlbRead(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn
	albArn := d.Id()

	describeAlbOpts := &elbv2.DescribeLoadBalancersInput{
		LoadBalancerArns: []*string{aws.String(albArn)},
	}

	describeResp, err := elbconn.DescribeLoadBalancers(describeAlbOpts)
	if err != nil {
		if isLoadBalancerNotFound(err) {
			// The ALB is gone now, so just remove it from the state
			log.Printf("[WARN] ALB %s not found in AWS, removing from state", d.Id())
			d.SetId("")
			return nil
		}

		return errwrap.Wrapf("Error retrieving ALB: {{err}}", err)
	}
	if len(describeResp.LoadBalancers) != 1 {
		return fmt.Errorf("Unable to find ALB: %#v", describeResp.LoadBalancers)
	}

	return flattenAwsAlbResource(d, meta, describeResp.LoadBalancers[0])
}

func resourceAwsAlbUpdate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbv2conn

	if !d.IsNewResource() {
		if err := setElbV2Tags(elbconn, d); err != nil {
			return errwrap.Wrapf("Error Modifying Tags on ALB: {{err}}", err)
		}
	}

	attributes := make([]*elbv2.LoadBalancerAttribute, 0)

	if d.HasChange("access_logs") {
		logs := d.Get("access_logs").([]interface{})
		if len(logs) == 1 {
			log := logs[0].(map[string]interface{})

			attributes = append(attributes,
				&elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.enabled"),
					Value: aws.String(strconv.FormatBool(log["enabled"].(bool))),
				},
				&elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.bucket"),
					Value: aws.String(log["bucket"].(string)),
				})

			if prefix, ok := log["prefix"]; ok {
				attributes = append(attributes, &elbv2.LoadBalancerAttribute{
					Key:   aws.String("access_logs.s3.prefix"),
					Value: aws.String(prefix.(string)),
				})
			}
		} else if len(logs) == 0 {
			attributes = append(attributes, &elbv2.LoadBalancerAttribute{
				Key:   aws.String("access_logs.s3.enabled"),
				Value: aws.String("false"),
			})
		}
	}

	if d.HasChange("enable_deletion_protection") {
		attributes = append(attributes, &elbv2.LoadBalancerAttribute{
			Key:   aws.String("deletion_protection.enabled"),
			Value: aws.String(fmt.Sprintf("%t", d.Get("enable_deletion_protection").(bool))),
		})
	}

	if d.HasChange("idle_timeout") {
		attributes = append(attributes, &elbv2.LoadBalancerAttribute{
			Key:   aws.String("idle_timeout.timeout_seconds"),
			Value: aws.String(fmt.Sprintf("%d", d.Get("idle_timeout").(int))),
		})
	}

	if len(attributes) != 0 {
		input := &elbv2.ModifyLoadBalancerAttributesInput{
			LoadBalancerArn: aws.String(d.Id()),
			Attributes:      attributes,
		}

		log.Printf("[DEBUG] ALB Modify Load Balancer Attributes Request: %#v", input)
		_, err := elbconn.ModifyLoadBalancerAttributes(input)
		if err != nil {
			return fmt.Errorf("Failure configuring ALB attributes: %s", err)
		}
	}

	if d.HasChange("security_groups") {
		sgs := expandStringList(d.Get("security_groups").(*schema.Set).List())

		params := &elbv2.SetSecurityGroupsInput{
			LoadBalancerArn: aws.String(d.Id()),
			SecurityGroups:  sgs,
		}
		_, err := elbconn.SetSecurityGroups(params)
		if err != nil {
			return fmt.Errorf("Failure Setting ALB Security Groups: %s", err)
		}

	}

	return resourceAwsAlbRead(d, meta)
}

func resourceAwsAlbDelete(d *schema.ResourceData, meta interface{}) error {
	albconn := meta.(*AWSClient).elbv2conn

	log.Printf("[INFO] Deleting ALB: %s", d.Id())

	// Destroy the load balancer
	deleteElbOpts := elbv2.DeleteLoadBalancerInput{
		LoadBalancerArn: aws.String(d.Id()),
	}
	if _, err := albconn.DeleteLoadBalancer(&deleteElbOpts); err != nil {
		return fmt.Errorf("Error deleting ALB: %s", err)
	}

	return nil
}

// flattenSubnetsFromAvailabilityZones creates a slice of strings containing the subnet IDs
// for the ALB based on the AvailabilityZones structure returned by the API.
func flattenSubnetsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []string {
	var result []string
	for _, az := range availabilityZones {
		result = append(result, *az.SubnetId)
	}
	return result
}

func albSuffixFromARN(arn *string) string {
	if arn == nil {
		return ""
	}

	if arnComponents := regexp.MustCompile(`arn:.*:loadbalancer/(.*)`).FindAllStringSubmatch(*arn, -1); len(arnComponents) == 1 {
		if len(arnComponents[0]) == 2 {
			return arnComponents[0][1]
		}
	}

	return ""
}

// flattenAwsAlbResource takes a *elbv2.LoadBalancer and populates all respective resource fields.
func flattenAwsAlbResource(d *schema.ResourceData, meta interface{}, alb *elbv2.LoadBalancer) error {
	elbconn := meta.(*AWSClient).elbv2conn

	d.Set("arn", alb.LoadBalancerArn)
	d.Set("arn_suffix", albSuffixFromARN(alb.LoadBalancerArn))
	d.Set("name", alb.LoadBalancerName)
	d.Set("internal", (alb.Scheme != nil && *alb.Scheme == "internal"))
	d.Set("security_groups", flattenStringList(alb.SecurityGroups))
	d.Set("subnets", flattenSubnetsFromAvailabilityZones(alb.AvailabilityZones))
	d.Set("vpc_id", alb.VpcId)
	d.Set("zone_id", alb.CanonicalHostedZoneId)
	d.Set("dns_name", alb.DNSName)

	respTags, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{
		ResourceArns: []*string{alb.LoadBalancerArn},
	})
	if err != nil {
		return errwrap.Wrapf("Error retrieving ALB Tags: {{err}}", err)
	}

	var et []*elbv2.Tag
	if len(respTags.TagDescriptions) > 0 {
		et = respTags.TagDescriptions[0].Tags
	}
	d.Set("tags", tagsToMapELBv2(et))

	attributesResp, err := elbconn.DescribeLoadBalancerAttributes(&elbv2.DescribeLoadBalancerAttributesInput{
		LoadBalancerArn: aws.String(d.Id()),
	})
	if err != nil {
		return errwrap.Wrapf("Error retrieving ALB Attributes: {{err}}", err)
	}

	accessLogMap := map[string]interface{}{}
	for _, attr := range attributesResp.Attributes {
		switch *attr.Key {
		case "access_logs.s3.enabled":
			accessLogMap["enabled"] = *attr.Value
		case "access_logs.s3.bucket":
			accessLogMap["bucket"] = *attr.Value
		case "access_logs.s3.prefix":
			accessLogMap["prefix"] = *attr.Value
		case "idle_timeout.timeout_seconds":
			timeout, err := strconv.Atoi(*attr.Value)
			if err != nil {
				return errwrap.Wrapf("Error parsing ALB timeout: {{err}}", err)
			}
			log.Printf("[DEBUG] Setting ALB Timeout Seconds: %d", timeout)
			d.Set("idle_timeout", timeout)
		case "deletion_protection.enabled":
			protectionEnabled := (*attr.Value) == "true"
			log.Printf("[DEBUG] Setting ALB Deletion Protection Enabled: %t", protectionEnabled)
			d.Set("enable_deletion_protection", protectionEnabled)
		}
	}

	log.Printf("[DEBUG] Setting ALB Access Logs: %#v", accessLogMap)
	if accessLogMap["bucket"] != "" || accessLogMap["prefix"] != "" {
		d.Set("access_logs", []interface{}{accessLogMap})
	} else {
		d.Set("access_logs", []interface{}{})
	}

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	awsGo "github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/gen/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsVpc() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVpcCreate,
		Read:   resourceAwsVpcRead,
		Update: resourceAwsVpcUpdate,
		Delete: resourceAwsVpcDelete,

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

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

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

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

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

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

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

			//			"tags": tagsSchema(),
		},
	}
}

func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).awsEc2conn
	cidr := d.Get("cidr_block").(string)
	instance_tenancy := "default"
	if v := d.Get("instance_tenancy"); v != nil {
		instance_tenancy = v.(string)
	}
	// Create the VPC
	createOpts := &ec2.CreateVPCRequest{
		CIDRBlock:       &cidr,
		InstanceTenancy: &instance_tenancy,
	}
	log.Printf("[DEBUG] VPC create config: %#v", createOpts)
	vpcResp, err := ec2conn.CreateVPC(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating VPC: %s", err)
	}

	// Get the ID and store it
	vpc := vpcResp.VPC
	d.SetId(*vpc.VPCID)
	log.Printf("[INFO] VPC ID: %s", d.Id())

	// Set partial mode and say that we setup the cidr block
	d.Partial(true)
	d.SetPartial("cidr_block")

	// Wait for the VPC to become available
	log.Printf(
		"[DEBUG] Waiting for VPC (%s) to become available",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: VPCStateRefreshFunc(ec2conn, d.Id()),
		Timeout: 10 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for VPC (%s) to become available: %s",
			d.Id(), err)
	}

	// Update our attributes and return
	return resourceAwsVpcUpdate(d, meta)
}

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

	// Refresh the VPC state
	vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if vpcRaw == nil {
		d.SetId("")
		return nil
	}

	// VPC stuff
	vpc := vpcRaw.(*ec2.VPC)
	vpcid := d.Id()
	d.Set("cidr_block", vpc.CIDRBlock)

	// Tags - TBD rmenn
	//d.Set("tags", tagsToMap(vpc.Tags))

	// Attributes
	attribute := "enableDnsSupport"
	DescribeAttrOpts := &ec2.DescribeVPCAttributeRequest{
		Attribute: &attribute,
		VPCID:     &vpcid,
	}
	resp, err := ec2conn.DescribeVPCAttribute(DescribeAttrOpts)
	if err != nil {
		return err
	}
	d.Set("enable_dns_support", *resp.EnableDNSSupport)
	attribute = "enableDnsHostnames"
	DescribeAttrOpts = &ec2.DescribeVPCAttributeRequest{
		Attribute: &attribute,
		VPCID:     &vpcid,
	}
	resp, err = ec2conn.DescribeVPCAttribute(DescribeAttrOpts)
	if err != nil {
		return err
	}
	d.Set("enable_dns_hostnames", *resp.EnableDNSHostnames)

	// Get the main routing table for this VPC
	// Really Ugly need to make this better - rmenn
	filter1 := &ec2.Filter{
		Name:   awsGo.String("association.main"),
		Values: []string{("true")},
	}
	filter2 := &ec2.Filter{
		Name:   awsGo.String("VPCID"),
		Values: []string{(d.Id())},
	}
	DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{
		Filters: []ec2.Filter{*filter1, *filter2},
	}
	routeResp, err := ec2conn.DescribeRouteTables(DescribeRouteOpts)
	if err != nil {
		return err
	}
	if v := routeResp.RouteTables; len(v) > 0 {
		d.Set("main_route_table_id", *v[0].RouteTableID)
	}

	resourceAwsVpcSetDefaultNetworkAcl(ec2conn, d)
	resourceAwsVpcSetDefaultSecurityGroup(ec2conn, d)

	return nil
}

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

	// Turn on partial mode
	d.Partial(true)

	if d.HasChange("enable_dns_hostnames") {
		options := new(ec2.ModifyVpcAttribute)
		options.EnableDnsHostnames = d.Get("enable_dns_hostnames").(bool)
		options.SetEnableDnsHostnames = true

		log.Printf(
			"[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v",
			d.Id(), options)
		if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil {
			return err
		}

		d.SetPartial("enable_dns_hostnames")
	}

	if d.HasChange("enable_dns_support") {
		options := new(ec2.ModifyVpcAttribute)
		options.EnableDnsSupport = d.Get("enable_dns_support").(bool)
		options.SetEnableDnsSupport = true

		log.Printf(
			"[INFO] Modifying enable_dns_support vpc attribute for %s: %#v",
			d.Id(), options)
		if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil {
			return err
		}

		d.SetPartial("enable_dns_support")
	}

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

	d.Partial(false)
	return resourceAwsVpcRead(d, meta)
}

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

	log.Printf("[INFO] Deleting VPC: %s", d.Id())
	if _, err := ec2conn.DeleteVpc(d.Id()); err != nil {
		ec2err, ok := err.(*ec2.Error)
		if ok && ec2err.Code == "InvalidVpcID.NotFound" {
			return nil
		}

		return fmt.Errorf("Error deleting VPC: %s", err)
	}

	return nil
}

// VPCStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a VPC.
func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeVpcs([]string{id}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on VPCStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		vpc := &resp.VPCs[0]
		return vpc, vpc.State, nil
	}
}

func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) error {
	filter := ec2.NewFilter()
	filter.Add("default", "true")
	filter.Add("vpc-id", d.Id())
	networkAclResp, err := conn.NetworkAcls(nil, filter)

	if err != nil {
		return err
	}
	if v := networkAclResp.NetworkAcls; len(v) > 0 {
		d.Set("default_network_acl_id", v[0].NetworkAclId)
	}

	return nil
}

func resourceAwsVpcSetDefaultSecurityGroup(conn *ec2.EC2, d *schema.ResourceData) error {
	filter := ec2.NewFilter()
	filter.Add("group-name", "default")
	filter.Add("vpc-id", d.Id())
	securityGroupResp, err := conn.SecurityGroups(nil, filter)

	if err != nil {
		return err
	}
	if v := securityGroupResp.Groups; len(v) > 0 {
		d.Set("default_security_group_id", v[0].Id)
	}

	return nil
}
<commit_msg>VPC Refactor<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	awsGo "github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/gen/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsVpc() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVpcCreate,
		Read:   resourceAwsVpcRead,
		Update: resourceAwsVpcUpdate,
		Delete: resourceAwsVpcDelete,

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

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

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

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

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

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

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

			//			"tags": tagsSchema(),
		},
	}
}

func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).awsEc2conn
	cidr := d.Get("cidr_block").(string)
	instance_tenancy := "default"
	if v := d.Get("instance_tenancy"); v != nil {
		instance_tenancy = v.(string)
	}
	// Create the VPC
	createOpts := &ec2.CreateVPCRequest{
		CIDRBlock:       &cidr,
		InstanceTenancy: &instance_tenancy,
	}
	log.Printf("[DEBUG] VPC create config: %#v", createOpts)
	vpcResp, err := ec2conn.CreateVPC(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating VPC: %s", err)
	}

	// Get the ID and store it
	vpc := vpcResp.VPC
	d.SetId(*vpc.VPCID)
	log.Printf("[INFO] VPC ID: %s", d.Id())

	// Set partial mode and say that we setup the cidr block
	d.Partial(true)
	d.SetPartial("cidr_block")

	// Wait for the VPC to become available
	log.Printf(
		"[DEBUG] Waiting for VPC (%s) to become available",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: VPCStateRefreshFunc(ec2conn, d.Id()),
		Timeout: 10 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for VPC (%s) to become available: %s",
			d.Id(), err)
	}

	// Update our attributes and return
	return resourceAwsVpcUpdate(d, meta)
}

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

	// Refresh the VPC state
	vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if vpcRaw == nil {
		d.SetId("")
		return nil
	}

	// VPC stuff
	vpc := vpcRaw.(*ec2.VPC)
	vpcid := d.Id()
	d.Set("cidr_block", vpc.CIDRBlock)

	// Tags - TBD rmenn
	//d.Set("tags", tagsToMap(vpc.Tags))

	// Attributes
	attribute := "enableDnsSupport"
	DescribeAttrOpts := &ec2.DescribeVPCAttributeRequest{
		Attribute: &attribute,
		VPCID:     &vpcid,
	}
	resp, err := ec2conn.DescribeVPCAttribute(DescribeAttrOpts)
	if err != nil {
		return err
	}
	d.Set("enable_dns_support", *resp.EnableDNSSupport)
	attribute = "enableDnsHostnames"
	DescribeAttrOpts = &ec2.DescribeVPCAttributeRequest{
		Attribute: &attribute,
		VPCID:     &vpcid,
	}
	resp, err = ec2conn.DescribeVPCAttribute(DescribeAttrOpts)
	if err != nil {
		return err
	}
	d.Set("enable_dns_hostnames", *resp.EnableDNSHostnames)

	// Get the main routing table for this VPC
	// Really Ugly need to make this better - rmenn
	filter1 := &ec2.Filter{
		Name:   awsGo.String("association.main"),
		Values: []string{("true")},
	}
	filter2 := &ec2.Filter{
		Name:   awsGo.String("VPCID"),
		Values: []string{(d.Id())},
	}
	DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{
		Filters: []ec2.Filter{*filter1, *filter2},
	}
	routeResp, err := ec2conn.DescribeRouteTables(DescribeRouteOpts)
	if err != nil {
		return err
	}
	if v := routeResp.RouteTables; len(v) > 0 {
		d.Set("main_route_table_id", *v[0].RouteTableID)
	}

	resourceAwsVpcSetDefaultNetworkAcl(ec2conn, d)
	resourceAwsVpcSetDefaultSecurityGroup(ec2conn, d)

	return nil
}

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

	// Turn on partial mode
	d.Partial(true)
	vpcid := d.Id()
	modifyOpts := &ec2.ModifyVPCAttributeRequest{
		VPCID: &vpcid,
	}
	if d.HasChange("enable_dns_hostnames") {
		val := d.Get("enable_dns_hostnames").(bool)
		modifyOpts.EnableDNSHostnames = &ec2.AttributeBooleanValue{
			Value: &val,
		}

		log.Printf(
			"[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v",
			d.Id(), modifyOpts)
		if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil {
			return err
		}

		d.SetPartial("enable_dns_hostnames")
	}

	if d.HasChange("enable_dns_support") {
		val := d.Get("enable_dns_hostnames").(bool)
		modifyOpts.EnableDNSSupport = &ec2.AttributeBooleanValue{
			Value: &val,
		}

		log.Printf(
			"[INFO] Modifying enable_dns_support vpc attribute for %s: %#v",
			d.Id(), modifyOpts)
		if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil {
			return err
		}

		d.SetPartial("enable_dns_support")
	}
	//Tagging Support need to be worked on - rmenn
	//	if err := setTags(ec2conn, d); err != nil {
	//		return err
	//	} else {
	//		d.SetPartial("tags")
	//	}

	d.Partial(false)
	return resourceAwsVpcRead(d, meta)
}

func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).awsEc2conn
	vpcID := d.Id()
	DeleteVpcOpts := &ec2.DeleteVPCRequest{
		VPCID: &vpcID,
	}
	log.Printf("[INFO] Deleting VPC: %s", d.Id())
	if err := ec2conn.DeleteVPC(DeleteVpcOpts); err != nil {
		ec2err, ok := err.(*awsGo.APIError)
		if ok && ec2err.Code == "InvalidVpcID.NotFound" {
			return nil
		}

		return fmt.Errorf("Error deleting VPC: %s", err)
	}

	return nil
}

// VPCStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a VPC.
func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		DescribeVpcOpts := &ec2.DescribeVPCsRequest{
			VPCIDs: []string{id},
		}
		resp, err := conn.DescribeVPCs(DescribeVpcOpts)
		if err != nil {
			if ec2err, ok := err.(*awsGo.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on VPCStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		vpc := &resp.VPCs[0]
		return vpc, *vpc.State, nil
	}
}

func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) error {
	filter1 := &ec2.Filter{
		Name:   awsGo.String("default"),
		Values: []string{("true")},
	}
	filter2 := &ec2.Filter{
		Name:   awsGo.String("vpc-id"),
		Values: []string{(d.Id())},
	}
	DescribeNetworkACLOpts := &ec2.DescribeNetworkACLsRequest{
		Filters: []ec2.Filter{*filter1, *filter2},
	}
	networkAclResp, err := conn.DescribeNetworkACLs(DescribeNetworkACLOpts)

	if err != nil {
		return err
	}
	if v := networkAclResp.NetworkACLs; len(v) > 0 {
		d.Set("default_network_acl_id", v[0].NetworkACLID)
	}

	return nil
}

func resourceAwsVpcSetDefaultSecurityGroup(conn *ec2.EC2, d *schema.ResourceData) error {
	filter1 := &ec2.Filter{
		Name:   awsGo.String("group-name"),
		Values: []string{("default")},
	}
	filter2 := &ec2.Filter{
		Name:   awsGo.String("vpc-id"),
		Values: []string{(d.Id())},
	}
	DescribeSgOpts := &ec2.DescribeSecurityGroupsRequest{
		Filters: []ec2.Filter{*filter1, *filter2},
	}
	securityGroupResp, err := conn.DescribeSecurityGroups(DescribeSgOpts)

	if err != nil {
		return err
	}
	if v := securityGroupResp.SecurityGroups; len(v) > 0 {
		d.Set("default_security_group_id", v[0].GroupID)
	}

	return nil
}
<|endoftext|>


<commit_before>package xmpp

// Manages the stack of filters that can read and modify stanzas on
// their way from the remote to the application.

// Receive new filters on filterAdd; those new filters get added to
// the top of the stack. Receive stanzas at the bottom of the stack on
// input. Send stanzas out the top of the stack on output.
func filterMgr(filterAdd <-chan Filter, input <-chan Stanza, output chan<- Stanza) {
	botFiltIn := output
	topFiltOut := input

loop:
	for {
		select {
		case stan, ok := <-input:
			if !ok {
				break loop
			}
			botFiltIn <- stan

		case stan, ok := <-topFiltOut:
			if !ok {
				break loop
			}
			output <- stan

		case filt := <-filterAdd:
			newTop := make(chan Stanza)
			go filt(topFiltOut, newTop)
			topFiltOut = newTop
		}
	}
	close(botFiltIn)
}

// Starts the filter chain. Filters will all interpose themselves
// between srvIn and cliOut.
func (cl *Client) startFilters(srvIn, cliIn <-chan Stanza) (<-chan Stanza, <-chan Stanza) {
	cliOut := make(chan Stanza)
	srvOut := make(chan Stanza)
	go filterMgr(cl.sendFilterAdd, srvIn, cliOut)
	go filterMgr(cl.recvFilterAdd, cliIn, srvOut)
	return cliOut, srvOut
}

// AddRecvFilter adds a new filter to the top of the stack through which
// incoming stanzas travel on their way up to the client.
func (cl *Client) AddRecvFilter(filt Filter) {
	if filt == nil {
		return
	}
	cl.recvFilterAdd <- filt
}

// AddSendFilter adds a new filter to the top of the stack through
// which outgoing stanzas travel on their way down from the client to
// the network.
func (cl *Client) AddSendFilter(filt Filter) {
	if filt == nil {
		return
	}
	cl.sendFilterAdd <- filt
}
<commit_msg>Removed some unused code.<commit_after>package xmpp

// Manages the stack of filters that can read and modify stanzas on
// their way from the remote to the application.

// Receive new filters on filterAdd; those new filters get added to
// the top of the stack. Receive stanzas at the bottom of the stack on
// input. Send stanzas out the top of the stack on output.
func filterMgr(filterAdd <-chan Filter, input <-chan Stanza, output chan<- Stanza) {
	botFiltIn := output
	topFiltOut := input

loop:
	for {
		select {
		case stan, ok := <-input:
			if !ok {
				break loop
			}
			botFiltIn <- stan

		case stan, ok := <-topFiltOut:
			if !ok {
				break loop
			}
			output <- stan

		case filt := <-filterAdd:
			newTop := make(chan Stanza)
			go filt(topFiltOut, newTop)
			topFiltOut = newTop
		}
	}
	close(botFiltIn)
}

// AddRecvFilter adds a new filter to the top of the stack through which
// incoming stanzas travel on their way up to the client.
func (cl *Client) AddRecvFilter(filt Filter) {
	if filt == nil {
		return
	}
	cl.recvFilterAdd <- filt
}

// AddSendFilter adds a new filter to the top of the stack through
// which outgoing stanzas travel on their way down from the client to
// the network.
func (cl *Client) AddSendFilter(filt Filter) {
	if filt == nil {
		return
	}
	cl.sendFilterAdd <- filt
}
<|endoftext|>


<commit_before>package xxhash

import (
	"bytes"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/binary"
	"fmt"
	"hash"
	"hash/crc32"
	"hash/fnv"
	"strings"
	"testing"

	"github.com/spaolacci/murmur3"
)

func TestSum(t *testing.T) {
	for i, tt := range []struct {
		input string
		want  uint64
	}{
		{"", 0xef46db3751d8e999},
		{"a", 0xd24ec4f1a98c6e5b},
		{"as", 0x1c330fb2d66be179},
		{"asd", 0x631c37ce72a97393},
		{"asdf", 0x415872f599cea71e},
		{
			// Exactly 63 characters, which exercises all code paths.
			"Call me Ishmael. Some years ago--never mind how long precisely-",
			0x02a2e85470d6fd96,
		},
	} {
		for chunkSize := 1; chunkSize <= len(tt.input); chunkSize++ {
			x := New()
			for j := 0; j < len(tt.input); j += chunkSize {
				end := j + chunkSize
				if end > len(tt.input) {
					end = len(tt.input)
				}
				chunk := []byte(tt.input[j:end])
				n, err := x.Write(chunk)
				if err != nil || n != len(chunk) {
					t.Fatalf("[i=%d,chunkSize=%d] Write: got (%d, %v); want (%d, nil)",
						i, chunkSize, n, err, len(chunk))
				}
			}
			if got := x.Sum64(); got != tt.want {
				t.Fatalf("[i=%d,chunkSize=%d] got 0x%x; want 0x%x",
					i, chunkSize, got, tt.want)
			}
			var b [8]byte
			binary.BigEndian.PutUint64(b[:], tt.want)
			if got := x.Sum(nil); !bytes.Equal(got, b[:]) {
				t.Fatalf("[i=%d,chunkSize=%d] Sum: got %v; want %v",
					i, chunkSize, got, b[:])
			}
		}
		if got := Sum64([]byte(tt.input)); got != tt.want {
			t.Fatalf("[i=%d] Sum64: got 0x%x; want 0x%x", i, got, tt.want)
		}
	}
}

func TestReset(t *testing.T) {
	parts := []string{"The quic", "k br", "o", "wn fox jumps", " ov", "er the lazy ", "dog."}
	x := New()
	for _, part := range parts {
		x.Write([]byte(part))
	}
	h0 := x.Sum64()

	x.Reset()
	x.Write([]byte(strings.Join(parts, "")))
	h1 := x.Sum64()

	if h0 != h1 {
		t.Errorf("0x%x != 0x%x", h0, h1)
	}
}

func BenchmarkHashes(b *testing.B) {
	for _, ht := range []struct {
		name string
		h    hash.Hash
	}{
		{"xxhash", New()},
		{"murmur3", murmur3.New64()},
		{"SHA-1", sha1.New()},
		{"SHA256", sha256.New()},
		{"CRC-32", crc32.NewIEEE()},
		{"MD5", md5.New()},
		{"FNV", fnv.New64()},
	} {
		for _, nt := range []struct {
			name string
			n    int
		}{
			{"5b", 5},
			{"20b", 20},
			{"100b", 100},
			{"4KB", 4e3},
			{"10MB", 10e6},
		} {
			s := make([]byte, nt.n)
			for i := range s {
				s[i] = byte(i)
			}
			b.Run(
				fmt.Sprintf("%s,n=%s", ht.name, nt.name),
				func(b *testing.B) { bench(b, ht.h, s) },
			)
		}
	}
}

func bench(b *testing.B, h hash.Hash, s []byte) {
	b.SetBytes(int64(len(s)))
	for i := 0; i < b.N; i++ {
		h.Write(s)
	}
}
<commit_msg>Update benchmarks<commit_after>package xxhash

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"hash"
	"hash/crc32"
	"strings"
	"testing"

	"github.com/OneOfOne/xxhash"
	"github.com/spaolacci/murmur3"
)

func TestSum(t *testing.T) {
	for i, tt := range []struct {
		input string
		want  uint64
	}{
		{"", 0xef46db3751d8e999},
		{"a", 0xd24ec4f1a98c6e5b},
		{"as", 0x1c330fb2d66be179},
		{"asd", 0x631c37ce72a97393},
		{"asdf", 0x415872f599cea71e},
		{
			// Exactly 63 characters, which exercises all code paths.
			"Call me Ishmael. Some years ago--never mind how long precisely-",
			0x02a2e85470d6fd96,
		},
	} {
		for chunkSize := 1; chunkSize <= len(tt.input); chunkSize++ {
			x := New()
			for j := 0; j < len(tt.input); j += chunkSize {
				end := j + chunkSize
				if end > len(tt.input) {
					end = len(tt.input)
				}
				chunk := []byte(tt.input[j:end])
				n, err := x.Write(chunk)
				if err != nil || n != len(chunk) {
					t.Fatalf("[i=%d,chunkSize=%d] Write: got (%d, %v); want (%d, nil)",
						i, chunkSize, n, err, len(chunk))
				}
			}
			if got := x.Sum64(); got != tt.want {
				t.Fatalf("[i=%d,chunkSize=%d] got 0x%x; want 0x%x",
					i, chunkSize, got, tt.want)
			}
			var b [8]byte
			binary.BigEndian.PutUint64(b[:], tt.want)
			if got := x.Sum(nil); !bytes.Equal(got, b[:]) {
				t.Fatalf("[i=%d,chunkSize=%d] Sum: got %v; want %v",
					i, chunkSize, got, b[:])
			}
		}
		if got := Sum64([]byte(tt.input)); got != tt.want {
			t.Fatalf("[i=%d] Sum64: got 0x%x; want 0x%x", i, got, tt.want)
		}
	}
}

func TestReset(t *testing.T) {
	parts := []string{"The quic", "k br", "o", "wn fox jumps", " ov", "er the lazy ", "dog."}
	x := New()
	for _, part := range parts {
		x.Write([]byte(part))
	}
	h0 := x.Sum64()

	x.Reset()
	x.Write([]byte(strings.Join(parts, "")))
	h1 := x.Sum64()

	if h0 != h1 {
		t.Errorf("0x%x != 0x%x", h0, h1)
	}
}

var (
	sink  uint64
	sinkb []byte
)

func sumFunc(h hash.Hash) func(b []byte) uint64 {
	return func(b []byte) uint64 {
		h.Reset()
		h.Write(b)
		sinkb = h.Sum(nil)
		return 0 // value doesn't matter
	}
}

func BenchmarkHashes(b *testing.B) {
	for _, ht := range []struct {
		name string
		f    func(b []byte) uint64
	}{
		{"xxhash", Sum64},
		{"OneOfOne", xxhash.Checksum64},
		{"murmur3", murmur3.Sum64},
		{"CRC-32", sumFunc(crc32.NewIEEE())},
	} {
		for _, nt := range []struct {
			name string
			n    int
		}{
			{"5b", 5},
			{"20b", 20},
			{"100b", 100},
			{"4KB", 4e3},
			{"10MB", 10e6},
		} {
			s := make([]byte, nt.n)
			for i := range s {
				s[i] = byte(i)
			}
			b.Run(
				fmt.Sprintf("%s,n=%s", ht.name, nt.name),
				func(b *testing.B) { bench(b, ht.f, s) },
			)
		}
	}
}

func bench(b *testing.B, f func(b []byte) uint64, s []byte) {
	b.SetBytes(int64(len(s)))
	for i := 0; i < b.N; i++ {
		sink = f(s)
	}
}
<|endoftext|>


<commit_before>package lua

import (
	"bytes"
	"image/png"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	"image/jpeg"

	"github.com/kardianos/osext"
	"github.com/nfnt/resize"
	"github.com/yuin/gopher-lua"
)

type formFileUserData struct {
	File   []byte
	Header *multipart.FileHeader
}

func createFormFileMetaTable(file []byte, header *multipart.FileHeader, L *lua.LState) *lua.LTable {
	// Create metatable
	table := L.NewTable()

	// Set metatable functions
	L.SetFuncs(table, formFileMethods)

	// Create new user data to hold file and header information
	u := L.NewUserData()

	// Set user value
	u.Value = &formFileUserData{
		File:   file,
		Header: header,
	}

	// Set user data as field
	L.SetField(table, "__file", u)

	// Set filename as field
	L.SetField(table, "name", lua.LString(header.Filename))

	return table
}

func getFormFileObject(L *lua.LState) *formFileUserData {
	// Retrieve metatable
	table := L.ToTable(1)

	// Get user data field
	data := L.GetField(table, "__file").(*lua.LUserData)

	// Return user value as form file pointer
	return data.Value.(*formFileUserData)
}

// FormFileIsValidPNG checks if the current form file is a valid png file
func FormFileIsValidPNG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	if http.DetectContentType(formFile.File) != "image/png" {

		// Push false
		L.Push(lua.LBool(false))

		return 1
	}

	// The file is a image png
	L.Push(lua.LBool(true))

	return 1
}

// FormFileIsValidExtension checks if the current form file is a valid extension
func FormFileIsValidExtension(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	if http.DetectContentType(formFile.File) != L.ToString(2) {

		// Push false
		L.Push(lua.LBool(false))

		return 1
	}

	// The file is a image png
	L.Push(lua.LBool(true))

	return 1
}

// FormFileDetectContentType returns the form file content type
func FormFileDetectContentType(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Push file content type
	L.Push(lua.LString(http.DetectContentType(formFile.File)))

	return 1
}

// GetFormFileByteArray returns the form file byte array as a lua string
func GetFormFileByteArray(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Push file as string
	L.Push(lua.LString(formFile.File))

	return 1
}

// SaveFormFile saves the current form file to the given destination
func SaveFormFile(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Write file to handle
	if err := ioutil.WriteFile(filepath.Join(f, destination), formFile.File, 0666); err != nil {
		L.RaiseError("Cannot save file to destination: %v", err)
	}

	return 0
}

// SaveFormFileAsJPEG saves the current form file as a jpeg with resizing optional
func SaveFormFileAsJPEG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Create file handle
	file, err := os.OpenFile(filepath.Join(f, destination), os.O_CREATE|os.O_WRONLY, 0666)

	if err != nil {
		L.RaiseError("Cannot get file handle: %v", err)
		return 0
	}

	// Close file handle
	defer file.Close()

	// Create png image from byte array
	pngImage, err := jpeg.Decode(bytes.NewBuffer(formFile.File))

	if err != nil {
		L.RaiseError("Cannot decode image from byte array: %v", err)
		return 0
	}

	// Get quality
	imageQuality := L.ToInt(3)

	// Get desired image sizes
	imageWidth := L.ToInt(4)
	imageHeight := L.ToInt(5)

	// Set default image quality
	if imageQuality <= 0 {
		imageQuality = 50
	}

	// Check if valid max quality
	if imageQuality >= 100 {
		imageQuality = 100
	}

	// Resize if wanted using nearest neighbor algorithm
	if imageWidth > 0 && imageHeight > 0 {
		pngImage = resize.Resize(uint(imageWidth), uint(imageHeight), pngImage, resize.NearestNeighbor)
	}

	// Encode image to file handle
	if err := jpeg.Encode(file, pngImage, &jpeg.Options{
		Quality: imageQuality,
	}); err != nil {
		L.RaiseError("Cannot encode jpeg image to handle: %v", err)
	}

	return 0
}

// SaveFormFileAsPNG saves the current form file as a png with resizing optional
func SaveFormFileAsPNG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Create file handle
	file, err := os.OpenFile(filepath.Join(f, destination), os.O_CREATE|os.O_WRONLY, 0666)

	if err != nil {
		L.RaiseError("Cannot get file handle: %v", err)
		return 0
	}

	// Close file handle
	defer file.Close()

	// Create png image from byte array
	pngImage, err := png.Decode(bytes.NewBuffer(formFile.File))

	if err != nil {
		L.RaiseError("Cannot decode image from byte array: %v", err)
		return 0
	}

	// Get desired image sizes
	imageWidth := L.ToInt(3)
	imageHeight := L.ToInt(4)

	// Resize if wanted using nearest neighbor algorithm
	if imageWidth > 0 && imageHeight > 0 {
		pngImage = resize.Resize(uint(imageWidth), uint(imageHeight), pngImage, resize.NearestNeighbor)
	}

	// Encode image to file handle
	if err := png.Encode(file, pngImage); err != nil {
		L.RaiseError("Cannot encode png image to handle: %v", err)
	}

	return 0
}
<commit_msg>Update formfile image check methods<commit_after>package lua

import (
	"bytes"
	"image"
	"image/png"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	_ "image/gif"
	"image/jpeg"

	"github.com/kardianos/osext"
	"github.com/nfnt/resize"
	"github.com/yuin/gopher-lua"
)

type formFileUserData struct {
	File   []byte
	Header *multipart.FileHeader
}

func createFormFileMetaTable(file []byte, header *multipart.FileHeader, L *lua.LState) *lua.LTable {
	// Create metatable
	table := L.NewTable()

	// Set metatable functions
	L.SetFuncs(table, formFileMethods)

	// Create new user data to hold file and header information
	u := L.NewUserData()

	// Set user value
	u.Value = &formFileUserData{
		File:   file,
		Header: header,
	}

	// Set user data as field
	L.SetField(table, "__file", u)

	// Set filename as field
	L.SetField(table, "name", lua.LString(header.Filename))

	return table
}

func getFormFileObject(L *lua.LState) *formFileUserData {
	// Retrieve metatable
	table := L.ToTable(1)

	// Get user data field
	data := L.GetField(table, "__file").(*lua.LUserData)

	// Return user value as form file pointer
	return data.Value.(*formFileUserData)
}

// FormFileIsValidPNG checks if the current form file is a valid png file
func FormFileIsValidPNG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	if http.DetectContentType(formFile.File) != "image/png" {

		// Push false
		L.Push(lua.LBool(false))

		return 1
	}

	// The file is a image png
	L.Push(lua.LBool(true))

	return 1
}

// FormFileIsValidExtension checks if the current form file is a valid extension
func FormFileIsValidExtension(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	if http.DetectContentType(formFile.File) != L.ToString(2) {

		// Push false
		L.Push(lua.LBool(false))

		return 1
	}

	// The file is a image png
	L.Push(lua.LBool(true))

	return 1
}

// FormFileDetectContentType returns the form file content type
func FormFileDetectContentType(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Push file content type
	L.Push(lua.LString(http.DetectContentType(formFile.File)))

	return 1
}

// GetFormFileByteArray returns the form file byte array as a lua string
func GetFormFileByteArray(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Push file as string
	L.Push(lua.LString(formFile.File))

	return 1
}

// SaveFormFile saves the current form file to the given destination
func SaveFormFile(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Write file to handle
	if err := ioutil.WriteFile(filepath.Join(f, destination), formFile.File, 0666); err != nil {
		L.RaiseError("Cannot save file to destination: %v", err)
	}

	return 0
}

// SaveFormFileAsJPEG saves the current form file as a jpeg with resizing optional
func SaveFormFileAsJPEG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Create file handle
	file, err := os.OpenFile(filepath.Join(f, destination), os.O_CREATE|os.O_WRONLY, 0666)

	if err != nil {
		L.RaiseError("Cannot get file handle: %v", err)
		return 0
	}

	// Close file handle
	defer file.Close()

	// Create png image from byte array
	pngImage, _, err := image.Decode(bytes.NewBuffer(formFile.File))

	if err != nil {
		L.RaiseError("Cannot decode image from byte array: %v", err)
		return 0
	}

	// Get quality
	imageQuality := L.ToInt(3)

	// Get desired image sizes
	imageWidth := L.ToInt(4)
	imageHeight := L.ToInt(5)

	// Set default image quality
	if imageQuality <= 0 {
		imageQuality = 50
	}

	// Check if valid max quality
	if imageQuality >= 100 {
		imageQuality = 100
	}

	// Resize if wanted using nearest neighbor algorithm
	if imageWidth > 0 && imageHeight > 0 {
		pngImage = resize.Resize(uint(imageWidth), uint(imageHeight), pngImage, resize.NearestNeighbor)
	}

	// Encode image to file handle
	if err := jpeg.Encode(file, pngImage, &jpeg.Options{
		Quality: imageQuality,
	}); err != nil {
		L.RaiseError("Cannot encode jpeg image to handle: %v", err)
	}

	return 0
}

// SaveFormFileAsPNG saves the current form file as a png with resizing optional
func SaveFormFileAsPNG(L *lua.LState) int {
	// Get form file
	formFile := getFormFileObject(L)

	// Get executable folder
	f, err := osext.ExecutableFolder()

	if err != nil {
		L.RaiseError("Cannot get executable folder path: %v", err)
		return 0
	}

	// Get destination
	destination := L.ToString(2)

	// Create file handle
	file, err := os.OpenFile(filepath.Join(f, destination), os.O_CREATE|os.O_WRONLY, 0666)

	if err != nil {
		L.RaiseError("Cannot get file handle: %v", err)
		return 0
	}

	// Close file handle
	defer file.Close()

	// Create png image from byte array
	pngImage, _, err := image.Decode(bytes.NewBuffer(formFile.File))

	if err != nil {
		L.RaiseError("Cannot decode image from byte array: %v", err)
		return 0
	}

	// Get desired image sizes
	imageWidth := L.ToInt(3)
	imageHeight := L.ToInt(4)

	// Resize if wanted using nearest neighbor algorithm
	if imageWidth > 0 && imageHeight > 0 {
		pngImage = resize.Resize(uint(imageWidth), uint(imageHeight), pngImage, resize.NearestNeighbor)
	}

	// Encode image to file handle
	if err := png.Encode(file, pngImage); err != nil {
		L.RaiseError("Cannot encode png image to handle: %v", err)
	}

	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"sort"
	"time"

	"github.com/pladdy/lumberjack"
	"github.com/pladdy/timepiece"
)

func main() {
	lumberjack.StartLogging()

	if len(os.Args) == 1 {
		lumberjack.Fatal("Config file is required as an argument")
	}

	config := readConfig(os.Args[1], time.Now())
	var filesToDownload []string

	if config["file list host"] != nil {
		matchingFiles, err := getFileList(config)
		if err != nil {
			lumberjack.Fatal("Failed to get file list")
		}

		if len(matchingFiles) == 0 {
			lumberjack.Info("No files found to download")
			os.Exit(0)
		}

		switch config["files to get"] {
		case "latest":
			lumberjack.Info("Getting latest file from matches")
			sort.Strings(matchingFiles)
			filesToDownload =
				append(filesToDownload, matchingFiles[len(matchingFiles)-1])
			lumberjack.Info("Latest file is %v", filesToDownload[0])
		case "all":
			lumberjack.Info("Getting all matching files")
			filesToDownload = matchingFiles
			lumberjack.Info("Files to download: %v", filesToDownload)
		default:
			lumberjack.Panic("Don't know which files to get; update config with 'latest' or 'all'")
		}

	} else {
		filesToDownload =
			append(filesToDownload, fmt.Sprintf("%v", config["download host"]))
	}

	if len(filesToDownload) == 0 {
		lumberjack.Info("No files to download")
	}

	// Get files
	for _, file := range filesToDownload {
		downloadLink := fmt.Sprintf("%v", config["download root"]) + "/" + file
		filePath := "./" + file
		gatherData(downloadLink, filePath)
	}
}

/* private */

// Given a uri and a file path, get the data and save to the path
func gatherData(downloadLink string, filePath string) error {
	lumberjack.Info("Getting response from " + downloadLink)

	response, err := http.Get(downloadLink)
	if err != nil {
		lumberjack.Panic("Error in Get: %v", err)
	}
	defer response.Body.Close()

	// Download file
	lumberjack.Info("Starting to download " + downloadLink)

	downloadHandle, err := os.Create(filePath)
	if err != nil {
		lumberjack.Panic("Error creating file %v", err)
	}
	defer downloadHandle.Close()

	_, err = io.Copy(downloadHandle, response.Body)
	if err != nil {
		lumberjack.Error("Failed to download file %v", downloadLink)
	}

	lumberjack.Info("Finished downloading %v", downloadLink)
	return err
}

func getFileList(config map[string]interface{}) (files []string, err error) {
	// Get response from host
	lumberjack.Info("Calling Get on %v", config["file list host"])

	response, err := http.Get(fmt.Sprintf("%v", config["file list host"]))
	if err != nil {
		lumberjack.Panic("Error in Get: ", err)
	}
	defer response.Body.Close()

	// Parse response
	fileRegexp := regexp.MustCompile(fmt.Sprintf("%v", config["file pattern"]))
	scanner := bufio.NewScanner(response.Body)
	var matchingFiles []string

	for scanner.Scan() {
		match := fileRegexp.FindAllStringSubmatch(scanner.Text(), 1)
		if len(match) > 0 {
			lumberjack.Info("Found match: %v", match[0])
			matchingFiles = append(matchingFiles, match[0][1])
		}
	}
	if err := scanner.Err(); err != nil {
		lumberjack.Panic("Error in scanning response: ", err)
	}

	return matchingFiles, err
}

// GIven a JSON config file name, read in the file and return a go lang
// data structure
func readConfig(fileName string, theTime time.Time) map[string]interface{} {
	lumberjack.Info("Reading in config " + fileName)

	contents, err := ioutil.ReadFile(fileName)
	if err != nil {
		lumberjack.Fatal("Couldn't read your config file.  Contents: %v", contents)
	}

	lumberjack.Info("Replacing time vars in config")

	replacedContents :=
		timepiece.ReplaceTime(string(contents), timepiece.TimeToTimePiece(theTime))

	lumberjack.Info("Unmarshalling config from JSON")

	var configJson interface{}
	err = json.Unmarshal([]byte(replacedContents), &configJson)
	if err != nil {
		lumberjack.Fatal("Failed to Unmarshal JSON; contents: %v", configJson)
	}

	return configJson.(map[string]interface{})
}
<commit_msg>only assign if defined<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"sort"
	"time"

	"github.com/pladdy/lumberjack"
	"github.com/pladdy/timepiece"
)

func main() {
	lumberjack.StartLogging()

	if len(os.Args) == 1 {
		lumberjack.Fatal("Config file is required as an argument")
	}

	config := readConfig(os.Args[1], time.Now())
	var filesToDownload []string

	if config["file list host"] != nil {
		matchingFiles, err := getFileList(config)
		if err != nil {
			lumberjack.Fatal("Failed to get file list")
		}

		if len(matchingFiles) == 0 {
			lumberjack.Info("No files found to download")
			os.Exit(0)
		}

		switch config["files to get"] {
		case "latest":
			lumberjack.Info("Getting latest file from matches")
			sort.Strings(matchingFiles)
			filesToDownload =
				append(filesToDownload, matchingFiles[len(matchingFiles)-1])
			lumberjack.Info("Latest file is %v", filesToDownload[0])
		case "all":
			lumberjack.Info("Getting all matching files")
			filesToDownload = matchingFiles
			lumberjack.Info("Files to download: %v", filesToDownload)
		default:
			lumberjack.Panic("Don't know which files to get; update config with 'latest' or 'all'")
		}

	} else if config["download host"] != nil {
		filesToDownload =
			append(filesToDownload, fmt.Sprintf("%v", config["download host"]))
	}

	if len(filesToDownload) == 0 {
		lumberjack.Info("No files to download")
	}

	// Get files
	for _, file := range filesToDownload {
		downloadLink := fmt.Sprintf("%v", config["download root"]) + "/" + file
		filePath := "./" + file
		gatherData(downloadLink, filePath)
	}
}

/* private */

// Given a uri and a file path, get the data and save to the path
func gatherData(downloadLink string, filePath string) error {
	lumberjack.Info("Getting response from " + downloadLink)

	response, err := http.Get(downloadLink)
	if err != nil {
		lumberjack.Panic("Error in Get: %v", err)
	}
	defer response.Body.Close()

	// Download file
	lumberjack.Info("Starting to download " + downloadLink)

	downloadHandle, err := os.Create(filePath)
	if err != nil {
		lumberjack.Panic("Error creating file %v", err)
	}
	defer downloadHandle.Close()

	_, err = io.Copy(downloadHandle, response.Body)
	if err != nil {
		lumberjack.Error("Failed to download file %v", downloadLink)
	}

	lumberjack.Info("Finished downloading %v", downloadLink)
	return err
}

func getFileList(config map[string]interface{}) (files []string, err error) {
	// Get response from host
	lumberjack.Info("Calling Get on %v", config["file list host"])

	response, err := http.Get(fmt.Sprintf("%v", config["file list host"]))
	if err != nil {
		lumberjack.Panic("Error in Get: ", err)
	}
	defer response.Body.Close()

	// Parse response
	fileRegexp := regexp.MustCompile(fmt.Sprintf("%v", config["file pattern"]))
	scanner := bufio.NewScanner(response.Body)
	var matchingFiles []string

	for scanner.Scan() {
		match := fileRegexp.FindAllStringSubmatch(scanner.Text(), 1)
		if len(match) > 0 {
			lumberjack.Info("Found match: %v", match[0])
			matchingFiles = append(matchingFiles, match[0][1])
		}
	}
	if err := scanner.Err(); err != nil {
		lumberjack.Panic("Error in scanning response: ", err)
	}

	return matchingFiles, err
}

// GIven a JSON config file name, read in the file and return a go lang
// data structure
func readConfig(fileName string, theTime time.Time) map[string]interface{} {
	lumberjack.Info("Reading in config " + fileName)

	contents, err := ioutil.ReadFile(fileName)
	if err != nil {
		lumberjack.Fatal("Couldn't read your config file.  Contents: %v", contents)
	}

	lumberjack.Info("Replacing time vars in config")

	replacedContents :=
		timepiece.ReplaceTime(string(contents), timepiece.TimeToTimePiece(theTime))

	lumberjack.Info("Unmarshalling config from JSON")

	var configJson interface{}
	err = json.Unmarshal([]byte(replacedContents), &configJson)
	if err != nil {
		lumberjack.Fatal("Failed to Unmarshal JSON; contents: %v", configJson)
	}

	return configJson.(map[string]interface{})
}
<|endoftext|>


<commit_before>package v2

import (
	"encoding/json"
	"net/http"

	"io/ioutil"

	"github.com/SpectoLabs/hoverfly/core/handlers"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"

	log "github.com/Sirupsen/logrus"
)

type HoverflySimulation interface {
	GetSimulation() (SimulationViewV4, error)
	PutSimulation(SimulationViewV4) error
	DeleteSimulation()
}

type SimulationHandler struct {
	Hoverfly HoverflySimulation
}

func (this *SimulationHandler) RegisterRoutes(mux *bone.Mux, am *handlers.AuthHandler) {
	mux.Get("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Get),
	))
	mux.Put("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Put),
	))
	mux.Delete("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Delete),
	))
	mux.Options("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(this.Options),
	))

	mux.Get("/api/v2/simulation/schema", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.GetSchema),
	))
	mux.Options("/api/v2/simulation/schema", negroni.New(
		negroni.HandlerFunc(this.Options),
	))
}

func (this *SimulationHandler) Get(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	simulationView, err := this.Hoverfly.GetSimulation()
	if err != nil {
		handlers.WriteErrorResponse(w, err.Error(), http.StatusInternalServerError)
		return
	}

	bytes, _ := json.Marshal(simulationView)

	handlers.WriteResponse(w, bytes)
}

func (this *SimulationHandler) Put(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	body, _ := ioutil.ReadAll(req.Body)

	simulationView, err := NewSimulationViewFromResponseBody(body)
	if err != nil {
		handlers.WriteErrorResponse(w, err.Error(), http.StatusBadRequest)
		return
	}

	this.Hoverfly.DeleteSimulation()

	err = this.Hoverfly.PutSimulation(simulationView)
	if err != nil {

		log.WithFields(log.Fields{
			"body": string(body),
		}).Debug(err.Error())

		handlers.WriteErrorResponse(w, "An error occured: "+err.Error(), http.StatusInternalServerError)
		return
	}

	this.Get(w, req, next)
}

func (this *SimulationHandler) Delete(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	this.Hoverfly.DeleteSimulation()

	this.Get(w, req, next)
}

func (this *SimulationHandler) Options(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("Allow", "OPTIONS, GET, PUT, DELETE")
	handlers.WriteResponse(w, []byte(""))
}

func (this *SimulationHandler) GetSchema(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	bytes, _ := json.Marshal(SimulationViewV4Schema)

	handlers.WriteResponse(w, bytes)
}

func (this *SimulationHandler) OptionsSchema(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("Allow", "OPTIONS, GET")
}
<commit_msg>Changed SimulationHandler to use util.JSONMarshal<commit_after>package v2

import (
	"encoding/json"
	"net/http"

	"io/ioutil"

	"github.com/SpectoLabs/hoverfly/core/handlers"
	"github.com/SpectoLabs/hoverfly/core/util"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"

	log "github.com/Sirupsen/logrus"
)

type HoverflySimulation interface {
	GetSimulation() (SimulationViewV4, error)
	PutSimulation(SimulationViewV4) error
	DeleteSimulation()
}

type SimulationHandler struct {
	Hoverfly HoverflySimulation
}

func (this *SimulationHandler) RegisterRoutes(mux *bone.Mux, am *handlers.AuthHandler) {
	mux.Get("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Get),
	))
	mux.Put("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Put),
	))
	mux.Delete("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Delete),
	))
	mux.Options("/api/v2/simulation", negroni.New(
		negroni.HandlerFunc(this.Options),
	))

	mux.Get("/api/v2/simulation/schema", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.GetSchema),
	))
	mux.Options("/api/v2/simulation/schema", negroni.New(
		negroni.HandlerFunc(this.Options),
	))
}

func (this *SimulationHandler) Get(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	simulationView, err := this.Hoverfly.GetSimulation()
	if err != nil {
		handlers.WriteErrorResponse(w, err.Error(), http.StatusInternalServerError)
		return
	}

	bytes, _ := util.JSONMarshal(simulationView)

	handlers.WriteResponse(w, bytes)
}

func (this *SimulationHandler) Put(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	body, _ := ioutil.ReadAll(req.Body)

	simulationView, err := NewSimulationViewFromResponseBody(body)
	if err != nil {
		handlers.WriteErrorResponse(w, err.Error(), http.StatusBadRequest)
		return
	}

	this.Hoverfly.DeleteSimulation()

	err = this.Hoverfly.PutSimulation(simulationView)
	if err != nil {

		log.WithFields(log.Fields{
			"body": string(body),
		}).Debug(err.Error())

		handlers.WriteErrorResponse(w, "An error occured: "+err.Error(), http.StatusInternalServerError)
		return
	}

	this.Get(w, req, next)
}

func (this *SimulationHandler) Delete(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	this.Hoverfly.DeleteSimulation()

	this.Get(w, req, next)
}

func (this *SimulationHandler) Options(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("Allow", "OPTIONS, GET, PUT, DELETE")
	handlers.WriteResponse(w, []byte(""))
}

func (this *SimulationHandler) GetSchema(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	bytes, _ := json.Marshal(SimulationViewV4Schema)

	handlers.WriteResponse(w, bytes)
}

func (this *SimulationHandler) OptionsSchema(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("Allow", "OPTIONS, GET")
}
<|endoftext|>


<commit_before>package session

import (
	"github.com/danjac/photoshare/api/models"
	"net/http"
)

const UserCookieName = "userid"

var userMgr = models.NewUserManager()

func GetCurrentUser(r *http.Request) (*models.User, error) {
	cookie, err := r.Cookie(UserCookieName)
	if err != nil {
		return nil, nil
	}

	var userID int
	if err := sCookie.Decode(UserCookieName, cookie.Value, &userID); err != nil {
		return nil, nil
	}

	if userID == 0 {
		return nil, nil
	}

	return userMgr.GetActive(userID)
}

func Login(w http.ResponseWriter, user *models.User) error {
	return writeSessionCookie(w, user.ID)
}

func Logout(w http.ResponseWriter) error {
	return writeSessionCookie(w, 0)
}

func writeSessionCookie(w http.ResponseWriter, id int64) error {
	// write the user ID to the secure cookie
	encoded, err := sCookie.Encode(UserCookieName, id)
	if err != nil {
		return err
	}

	cookie := &http.Cookie{
		Name:  UserCookieName,
		Value: encoded,
		Path:  "/",
	}
	http.SetCookie(w, cookie)
	return nil

}
<commit_msg>Correct sess error handling<commit_after>package session

import (
	"github.com/danjac/photoshare/api/models"
	"net/http"
)

const UserCookieName = "userid"

var userMgr = models.NewUserManager()

func GetCurrentUser(r *http.Request) (*models.User, error) {
	cookie, err := r.Cookie(UserCookieName)
	if err != nil {
		return nil, err
	}

	var userID int
	if err := sCookie.Decode(UserCookieName, cookie.Value, &userID); err != nil {
		return nil, err
	}

	if userID == 0 {
		return nil, nil
	}

	return userMgr.GetActive(userID)
}

func Login(w http.ResponseWriter, user *models.User) error {
	return writeSessionCookie(w, user.ID)
}

func Logout(w http.ResponseWriter) error {
	return writeSessionCookie(w, 0)
}

func writeSessionCookie(w http.ResponseWriter, id int64) error {
	// write the user ID to the secure cookie
	encoded, err := sCookie.Encode(UserCookieName, id)
	if err != nil {
		return err
	}

	cookie := &http.Cookie{
		Name:  UserCookieName,
		Value: encoded,
		Path:  "/",
	}
	http.SetCookie(w, cookie)
	return nil

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/taironas/route"
	"log"
	"net/http"
	"os"
)

var root = flag.String("root", "app", "file system path")

func main() {
	r := new(route.Router)

	r.HandleFunc("/black/?", blackHandler)
	r.HandleFunc("/green/?", greenHandler)
	r.HandleFunc("/blue/?", blueHandler)
	r.HandleFunc("/red/?", redHandler)
	r.HandleFunc("/grid/?", grid6X6Handler)
	r.HandleFunc("/gradient/?", gradientHandler)
	r.HandleFunc("/[1-8]/?", colorGridHandler)
	r.AddStaticResource(root)

	log.Println("Listening on " + os.Getenv("PORT"))
	err := http.ListenAndServe(":"+os.Getenv("PORT"), r)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}
<commit_msg>add this until route pushed change into master...<commit_after>package main

import (
	"flag"
	//	"github.com/taironas/route"
	"log"
	"net/http"
	"os"
	"regexp"
)

var root = flag.String("root", "app", "file system path")

func main() {
	r := new(Router)

	r.HandleFunc("/black/?", blackHandler)
	r.HandleFunc("/green/?", greenHandler)
	r.HandleFunc("/blue/?", blueHandler)
	r.HandleFunc("/red/?", redHandler)
	r.HandleFunc("/grid/?", grid6X6Handler)
	r.HandleFunc("/gradient/?", gradientHandler)
	r.HandleFunc("/[1-8]/?", colorGridHandler)
	r.AddStaticResource(root)

	log.Println("Listening on " + os.Getenv("PORT"))
	err := http.ListenAndServe(":"+os.Getenv("PORT"), r)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

// inspired by the following sources with some small changes:
// http://stackoverflow.com/questions/6564558/wildcards-in-the-pattern-for-http-handlefunc
// https://github.com/raymi/quickerreference
type route struct {
	pattern *regexp.Regexp
	handler http.Handler
}

type Router struct {
	routes       []*route  // array of routes with a tuple (pattern, handler)
	staticRoutes []*string // array of static routes
}

func (r *Router) AddStaticResource(route *string) {
	r.staticRoutes = append(r.staticRoutes, route)
}

// Handle registers the handler for the given pattern in the router.
func (r *Router) Handle(strPattern string, handler http.Handler) {
	// encapsulate string pattern with start and end constraints.
	pattern := regexp.MustCompile("^" + strPattern + "$")
	r.routes = append(r.routes, &route{pattern, handler})
}

// HandleFunc registers the handler function for the given pattern in the router.
func (r *Router) HandleFunc(strPattern string, handler func(http.ResponseWriter, *http.Request)) {
	r.Handle(strPattern, http.HandlerFunc(handler))
}

// ServeHTTP looks for a matching route among the routes. Returns 404 if no match is found.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	// look for matching route
	for _, route := range r.routes {
		if route.pattern.MatchString(req.URL.Path) {
			route.handler.ServeHTTP(w, req)
			return
		}
	}

	// route not found. check if it is a static ressource.
	for _, sr := range r.staticRoutes {
		dir := http.Dir(*sr)
		if _, err := dir.Open(req.URL.Path); err == nil {
			// Could open file, set static route and call ServeHTTP again.
			r.Handle(req.URL.Path, http.FileServer(dir))
			r.ServeHTTP(w, req)
			return
		}
	}

	// no pattern matched; send 404 response
	http.NotFound(w, req)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"lime/backend"
	"os/exec"
	"reflect"
	"regexp"
	"strings"
)

var re = regexp.MustCompile(`\p{Lu}`)

func pyname(in string) string {
	if in == "String" {
		return "Str"
	}
	return re.ReplaceAllStringFunc(in, func(a string) string { return "_" + strings.ToLower(a) })
}

func pytype(t reflect.Type) string {
	switch t.Kind() {
	case reflect.Struct:
		return "*" + t.Name()
	case reflect.Int:
		return "*py.Int"
	default:
		panic(t.Kind())
	}
}

func pyret(ot reflect.Type) (ret string) {
	switch ot.Kind() {
	case reflect.Struct:
		return fmt.Sprintf(`
			pyret, err := %sClass.Alloc(1)
			if err != nil {
				return nil, err
			} else if v2, ok := pyret.(*%s); !ok {
				return nil, fmt.Errorf("Unable to convert return value to the right type?!: %%s", pyret.Type())
			} else {
				v2.data = ret
				return v2, nil
			}`, pyname(ot.Name()), ot.Name())
	case reflect.Bool:
		return `
			if ret {
				return py.True, nil
			} else {
				return py.False, nil
			}`
	case reflect.Int:
		return "\n\treturn py.NewInt(ret), nil"
	default:
		panic(ot.Kind())
	}
	return
}

func pyacc(ot reflect.Type) string {
	switch ot.Kind() {
	case reflect.Ptr, reflect.Struct:
		return ".data"
	case reflect.Int:
		return ".Int()"
	default:
		panic(ot.Kind())
	}
}

func pytogoconv(in, set, name string, returnsValue bool, t reflect.Type) string {
	ty := pytype(t)
	r := ""
	if returnsValue {
		r = "nil, "
	}
	return fmt.Sprintf(`
		if v2, ok := %s.(%s); !ok {
			return %sfmt.Errorf("Expected type %s for %s, not %%s", %s.Type())
		} else {
			%s = v2%s
		}`, in, ty, r, ty, name, in, set, pyacc(t))
}

func generateWrapper(t reflect.Type, canCreate bool) (ret string) {
	if t.Kind() != reflect.Struct {
		panic(t.Kind())
	}
	it := t.String()
	if !canCreate {
		it = "*" + it
	}
	ret += fmt.Sprintf(`
		var %sClass = py.Class{
			Name:    "sublime.%s",
			Pointer: (*%s)(nil),
		}

		type %s struct {
			py.BaseObject
			data %s
		}
		`, pyname(t.Name()), t.Name(), t.Name(), t.Name(), it)

	if canCreate {
		ret += fmt.Sprintf(`
			func (o *%s) PyInit(args *py.Tuple, kwds *py.Dict) error {
				if args.Size() > %d {
					return fmt.Errorf("Expected at most %d arguments")
				}
			`, t.Name(), t.NumField(), t.NumField())
		for i := 0; i < t.NumField(); i++ {
			f := t.Field(i)
			ret += fmt.Sprintf(`
					if args.Size() > %d {
						if v, err := args.GetItem(%d); err != nil {
							return err
						} else {%s
						}
					}
				`, i, i, pytogoconv("v", "o.data."+f.Name, t.Name()+"."+f.Name, false, f.Type))
		}
		ret += "\n\treturn nil\n}"
	} else {
		ret += fmt.Sprintf(`
			func (o *%s) PyInit(args *py.Tuple, kwds *py.Dict) error {
				return fmt.Errorf("Can't initialize type %s")
			}`, t.Name())
	}

	for i := 0; i < t.NumMethod(); i++ {
		var (
			m    = t.Method(i)
			args string
			rv   string
			in   = m.Type.NumIn() - 1
			out  = m.Type.NumOut()
		)
		if out > 1 {
			panic(fmt.Errorf("Can't handle out > 1: %d", out))
		}

		if in > 0 {
			args = "tu *py.Tuple, kw *py.Dict"
		}
		if m.Name == "String" {
			rv = "string"
		} else if m.Type.NumOut() == 0 {
			rv = "error"
		} else {
			rv = "(py.Object, error)"
		}

		ret += fmt.Sprintf("\nfunc (o *%s) Py%s(%s) %s {", t.Name(), pyname(m.Name), args, rv)

		if in > 0 {
			ret += "\n\tvar ("
			for j := 1; j <= in; j++ {
				ret += fmt.Sprintf("\n\t\targ%d %s", j, m.Type.In(j))
			}
			ret += "\n\t)"
			ret += fmt.Sprintf(`
					if tu.Size() != %d {
						return nil, fmt.Errorf("Expected %d arguments but got %%d", tu.Size())
					}`, in, in)

			for j := 1; j <= in; j++ {
				name := fmt.Sprintf("arg%d", j)
				msg := fmt.Sprintf("%s.%s() %s", t, m.Name, name)
				ret += fmt.Sprintf(`
					if v, err := tu.GetItem(%d); err != nil {
						return nil, err
					} else {%s}`, j-1, pytogoconv("v", name, msg, out > 0, m.Type.In(j)))
			}
		}

		call := ""
		if in > 0 {
			call = "o.data." + m.Name + "("
			for j := 1; j <= in; j++ {
				if j > 1 {
					call += ", "
				}
				call += fmt.Sprintf("arg%d", j)
				call += ")"
			}
		} else {
			call = "o.data." + m.Name + "()"
		}
		if m.Name == "String" {
			ret += "\n\treturn " + call
		} else if out > 0 {
			ret += "\n\tret := " + call
			ret += pyret(m.Type.Out(0))
		} else {
			ret += "\n\t" + call + "\n\treturn nil"
		}
		ret += "\n}\n"
	}

	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if !f.Anonymous {
			ret += fmt.Sprintf(`
				func (o *%s) PyGet%s() (py.Object, error) {
					ret := o.data.%s%s
				}

				func (o *%s) PySet%s(v py.Object) error {%s
					return  nil
				}

				`, t.Name(), pyname(f.Name), f.Name, pyret(f.Type),
				t.Name(), pyname(f.Name), pytogoconv("v", "o.data."+f.Name, t.Name()+"."+f.Name, false, f.Type),
			)
		}
	}

	return
}

func main() {
	data := [][]string{
		{"../backend/sublime/region.go", generateWrapper(reflect.TypeOf(backend.Region{}), true)},
	}
	for _, gen := range data {
		wr := `// This file was generated as part of a build step and shouldn't be manually modified
			package sublime

			import (
				"fmt"
				"github.com/qur/gopy/lib"
				"lime/backend"
			)
			` + gen[1]
		if err := ioutil.WriteFile(gen[0], []byte(wr), 0644); err != nil {
			panic(err)
		} else {
			c := exec.Command("go", "fmt", gen[0])
			if o, err := c.CombinedOutput(); err != nil {
				panic(err)
			} else {
				fmt.Println(string(o))
			}
		}
	}
}
<commit_msg>build/python.go: fix for methods not returning a value (untested)<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"lime/backend"
	"os/exec"
	"reflect"
	"regexp"
	"strings"
)

var re = regexp.MustCompile(`\p{Lu}`)

func pyname(in string) string {
	if in == "String" {
		return "Str"
	}
	return re.ReplaceAllStringFunc(in, func(a string) string { return "_" + strings.ToLower(a) })
}

func pytype(t reflect.Type) string {
	switch t.Kind() {
	case reflect.Struct:
		return "*" + t.Name()
	case reflect.Int:
		return "*py.Int"
	default:
		panic(t.Kind())
	}
}

func pyret(ot reflect.Type) (ret string) {
	switch ot.Kind() {
	case reflect.Struct:
		return fmt.Sprintf(`
			pyret, err := %sClass.Alloc(1)
			if err != nil {
				return nil, err
			} else if v2, ok := pyret.(*%s); !ok {
				return nil, fmt.Errorf("Unable to convert return value to the right type?!: %%s", pyret.Type())
			} else {
				v2.data = ret
				return v2, nil
			}`, pyname(ot.Name()), ot.Name())
	case reflect.Bool:
		return `
			if ret {
				return py.True, nil
			} else {
				return py.False, nil
			}`
	case reflect.Int:
		return "\n\treturn py.NewInt(ret), nil"
	default:
		panic(ot.Kind())
	}
	return
}

func pyacc(ot reflect.Type) string {
	switch ot.Kind() {
	case reflect.Ptr, reflect.Struct:
		return ".data"
	case reflect.Int:
		return ".Int()"
	default:
		panic(ot.Kind())
	}
}

func pytogoconv(in, set, name string, returnsValue bool, t reflect.Type) string {
	ty := pytype(t)
	r := ""
	if returnsValue {
		r = "nil, "
	}
	return fmt.Sprintf(`
		if v2, ok := %s.(%s); !ok {
			return %sfmt.Errorf("Expected type %s for %s, not %%s", %s.Type())
		} else {
			%s = v2%s
		}`, in, ty, r, ty, name, in, set, pyacc(t))
}

func generateWrapper(t reflect.Type, canCreate bool) (ret string) {
	if t.Kind() != reflect.Struct {
		panic(t.Kind())
	}
	it := t.String()
	if !canCreate {
		it = "*" + it
	}
	ret += fmt.Sprintf(`
		var %sClass = py.Class{
			Name:    "sublime.%s",
			Pointer: (*%s)(nil),
		}

		type %s struct {
			py.BaseObject
			data %s
		}
		`, pyname(t.Name()), t.Name(), t.Name(), t.Name(), it)

	if canCreate {
		ret += fmt.Sprintf(`
			func (o *%s) PyInit(args *py.Tuple, kwds *py.Dict) error {
				if args.Size() > %d {
					return fmt.Errorf("Expected at most %d arguments")
				}
			`, t.Name(), t.NumField(), t.NumField())
		for i := 0; i < t.NumField(); i++ {
			f := t.Field(i)
			ret += fmt.Sprintf(`
					if args.Size() > %d {
						if v, err := args.GetItem(%d); err != nil {
							return err
						} else {%s
						}
					}
				`, i, i, pytogoconv("v", "o.data."+f.Name, t.Name()+"."+f.Name, false, f.Type))
		}
		ret += "\n\treturn nil\n}"
	} else {
		ret += fmt.Sprintf(`
			func (o *%s) PyInit(args *py.Tuple, kwds *py.Dict) error {
				return fmt.Errorf("Can't initialize type %s")
			}`, t.Name())
	}

	for i := 0; i < t.NumMethod(); i++ {
		var (
			m    = t.Method(i)
			args string
			rv   string
			in   = m.Type.NumIn() - 1
			out  = m.Type.NumOut()
		)
		if out > 1 {
			panic(fmt.Errorf("Can't handle out > 1: %d", out))
		}

		if in > 0 {
			args = "tu *py.Tuple, kw *py.Dict"
		}
		if m.Name == "String" {
			rv = "string"
		} else if m.Type.NumOut() == 0 {
			rv = "error"
		} else {
			rv = "(py.Object, error)"
		}

		ret += fmt.Sprintf("\nfunc (o *%s) Py%s(%s) %s {", t.Name(), pyname(m.Name), args, rv)

		if in > 0 {
			ret += "\n\tvar ("
			for j := 1; j <= in; j++ {
				ret += fmt.Sprintf("\n\t\targ%d %s", j, m.Type.In(j))
			}
			r := ""
			if out > 0 {
				r = "nil, "
			}
			ret += "\n\t)"
			ret += fmt.Sprintf(`
					if tu.Size() != %d {
						return %sfmt.Errorf("Expected %d arguments but got %%d", tu.Size())
					}`, in, r, in)

			for j := 1; j <= in; j++ {
				name := fmt.Sprintf("arg%d", j)
				msg := fmt.Sprintf("%s.%s() %s", t, m.Name, name)
				ret += fmt.Sprintf(`
					if v, err := tu.GetItem(%d); err != nil {
						return %serr
					} else {%s}`, j-1, r, pytogoconv("v", name, msg, out > 0, m.Type.In(j)))
			}
		}

		call := ""
		if in > 0 {
			call = "o.data." + m.Name + "("
			for j := 1; j <= in; j++ {
				if j > 1 {
					call += ", "
				}
				call += fmt.Sprintf("arg%d", j)
				call += ")"
			}
		} else {
			call = "o.data." + m.Name + "()"
		}
		if m.Name == "String" {
			ret += "\n\treturn " + call
		} else if out > 0 {
			ret += "\n\tret := " + call
			ret += pyret(m.Type.Out(0))
		} else {
			ret += "\n\t" + call + "\n\treturn nil"
		}
		ret += "\n}\n"
	}

	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if !f.Anonymous {
			ret += fmt.Sprintf(`
				func (o *%s) PyGet%s() (py.Object, error) {
					ret := o.data.%s%s
				}

				func (o *%s) PySet%s(v py.Object) error {%s
					return  nil
				}

				`, t.Name(), pyname(f.Name), f.Name, pyret(f.Type),
				t.Name(), pyname(f.Name), pytogoconv("v", "o.data."+f.Name, t.Name()+"."+f.Name, false, f.Type),
			)
		}
	}

	return
}

func main() {
	data := [][]string{
		{"../backend/sublime/region.go", generateWrapper(reflect.TypeOf(backend.Region{}), true)},
	}
	for _, gen := range data {
		wr := `// This file was generated as part of a build step and shouldn't be manually modified
			package sublime

			import (
				"fmt"
				"github.com/qur/gopy/lib"
				"lime/backend"
			)
			` + gen[1]
		if err := ioutil.WriteFile(gen[0], []byte(wr), 0644); err != nil {
			panic(err)
		} else {
			c := exec.Command("go", "fmt", gen[0])
			if o, err := c.CombinedOutput(); err != nil {
				panic(err)
			} else {
				fmt.Println(string(o))
			}
		}
	}
}
<|endoftext|>


<commit_before>package app

import (
	"bufio"
	"regexp"
	"strconv"
	"time"
)

var (
	bashTimestampRegexp = regexp.MustCompile(`^#'s*\d+$`)
	zshLineRegexp       = regexp.MustCompile(`^:\s*(\d*)\s*:(\d*)\s*;(.*)`)

	defaultEventsCapacity = 5000
)

func parseBash(scanner *bufio.Scanner, filter *regexp.Regexp) ([]HistoryEntry, error) {
	currentTime := time.Now()
	currentNumber := 1
	events := make([]HistoryEntry, 0, defaultEventsCapacity)

	for scanner.Scan() {
		text := scanner.Text()
		if bashTimestampRegexp.MatchString(text) {
			if converted, err := strconv.Atoi(text[1:]); err == nil {
				currentTime = convertTimestamp(converted)
			}
		} else if filter.MatchString(text) {
			newEvent := HistoryEntry{
				Number:     currentNumber,
				Command:    text,
				Timestamp:  currentTime,
				HasHistory: false} // HasHistory = false temporarily
			events = append(events, newEvent)
			currentNumber += 1
		}
	}

	return scanEnd(scanner, events)
}

func parseZsh(scanner *bufio.Scanner, filter *regexp.Regexp) ([]HistoryEntry, error) {
	currentNumber := 1
	events := make([]HistoryEntry, 0, defaultEventsCapacity)

	for scanner.Scan() {
		matcher := zshLineRegexp.FindStringSubmatch(scanner.Text())
		if matcher == nil {
			continue
		}
		timestamp := matcher[1]
		command := matcher[3]

		if timestamp == "" || command == "" {
			continue
		}
		if filter != nil && filter.MatchString(command) {
			continue
		}

		converted, _ := strconv.Atoi(timestamp)
		newEvent := HistoryEntry{
			Number:     currentNumber,
			Command:    command,
			Timestamp:  convertTimestamp(converted),
			HasHistory: false} // HasHistory = false temporarily
		events = append(events, newEvent)
		currentNumber += 1
	}

	return scanEnd(scanner, events)
}

func convertTimestamp(timestamp int) time.Time {
	return time.Unix(int64(timestamp), 0)
}

func scanEnd(scanner *bufio.Scanner, events []HistoryEntry) ([]HistoryEntry, error) {
	if err := scanner.Err(); err != nil {
		return nil, err
	} else {
		return events, nil
	}
}
<commit_msg>Small fix for grepping<commit_after>package app

import (
	"bufio"
	"regexp"
	"strconv"
	"time"
)

var (
	bashTimestampRegexp = regexp.MustCompile(`^#'s*\d+$`)
	zshLineRegexp       = regexp.MustCompile(`^:\s*(\d*)\s*:(\d*)\s*;(.*)`)

	defaultEventsCapacity = 5000
)

func parseBash(scanner *bufio.Scanner, filter *regexp.Regexp) ([]HistoryEntry, error) {
	currentTime := time.Now()
	currentNumber := 1
	events := make([]HistoryEntry, 0, defaultEventsCapacity)

	for scanner.Scan() {
		text := scanner.Text()
		if bashTimestampRegexp.MatchString(text) {
			if converted, err := strconv.Atoi(text[1:]); err == nil {
				currentTime = convertTimestamp(converted)
			}
		} else if filter.MatchString(text) {
			newEvent := HistoryEntry{
				Number:     currentNumber,
				Command:    text,
				Timestamp:  currentTime,
				HasHistory: false} // HasHistory = false temporarily
			events = append(events, newEvent)
			currentNumber += 1
		}
	}

	return scanEnd(scanner, events)
}

func parseZsh(scanner *bufio.Scanner, filter *regexp.Regexp) ([]HistoryEntry, error) {
	currentNumber := 1
	events := make([]HistoryEntry, 0, defaultEventsCapacity)

	for scanner.Scan() {
		matcher := zshLineRegexp.FindStringSubmatch(scanner.Text())
		if matcher == nil {
			continue
		}
		timestamp := matcher[1]
		command := matcher[3]

		if timestamp == "" || command == "" {
			continue
		}
		if filter != nil && !filter.MatchString(command) {
			continue
		}

		converted, _ := strconv.Atoi(timestamp)
		newEvent := HistoryEntry{
			Number:     currentNumber,
			Command:    command,
			Timestamp:  convertTimestamp(converted),
			HasHistory: false} // HasHistory = false temporarily
		events = append(events, newEvent)
		currentNumber += 1
	}

	return scanEnd(scanner, events)
}

func convertTimestamp(timestamp int) time.Time {
	return time.Unix(int64(timestamp), 0)
}

func scanEnd(scanner *bufio.Scanner, events []HistoryEntry) ([]HistoryEntry, error) {
	if err := scanner.Err(); err != nil {
		return nil, err
	} else {
		return events, nil
	}
}
<|endoftext|>


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

package qopher

import (
	"html/template"
	"net/http"

	"appengine"
	"appengine/datastore"
	"appengine/user"

	"qopher/task"
)

type FrontPage struct {
	NTotal          int
	QueueEmail      string // showing queue for this email address
	QueueEmailShort string
	Yours           []*Task
	Other           []*Task
}

func serveFront(rw http.ResponseWriter, r *http.Request) {
	if !getMethod(r) {
		http.Error(rw, "bad method", http.StatusMethodNotAllowed)
		return
	}
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		http.Error(rw, "login required", http.StatusUnauthorized)
		return
	}

	email := r.FormValue("q")
	if email == "" {
		email = u.Email
	}
	email = mapEmail(email)

	if email == "crash" {
		panic("fake crash")
	}

	q := datastore.NewQuery("Task").Filter("Closed = ", false)
	var tasks []*Task
	_, err := q.GetAll(c, &tasks)
	if err != nil {
		c.Errorf("GetAll: %v", err)
		http.Error(rw, err.Error(), 500)
		return
	}
	numIssues := len(tasks)

	var yours, other []*Task
	for _, t := range tasks {
		if t.Owner == email {
			yours = append(yours, t)
		} else {
			other = append(other, t)
		}
	}

	const maxOther = 50
	if len(other) > maxOther {
		other = other[:maxOther]
	}

	page := &FrontPage{
		NTotal:          numIssues,
		QueueEmail:      email,
		QueueEmailShort: emailToShort(email),
		Yours:           yours,
		Other:           other,
	}

	err = frontPage.ExecuteTemplate(rw, "front", page)
	if err != nil && r.Method != "HEAD" {
		c.Errorf("template error: %v", err)
	}
}

var frontPage = template.Must(template.New("front").Funcs(template.FuncMap{
	"taskURL": func(taskType, id string) string {
		return task.TypeMap[taskType].TaskURL(id)
	},
	"shortOwner": func(t *Task) string {
		if t.Owner == "" {
			return ""
		}
		return emailToShort(t.Owner) + ": "
	},
}).Parse(`
<!doctype html>

    <title>qopher - Go queue</title>

qopher: the Gopher Queue

WORK IN PROGRESS

Total {{$.NTotal}} open tasks

Viewing queue for {{$.QueueEmail}} (change with ?q= nickname or email)

{{if $.Yours}}

Assigned to {{$.QueueEmailShort}} ({{len $.Yours}})

This list doesn't include your open and assigned issues.

  {{range $i, $t := $.Yours}}

{{$t.Type}}.{{$t.ID}}: {{$t.Title}}

  {{end}}

{{else}}

Nothing assigned to {{$.QueueEmail}}

Also check your open and assigned issues.

{{end}}

{{if $.Other}}

Some other open tasks

  {{range $i, $t := $.Other}}

{{$t.Type}}.{{$t.ID}}: {{shortOwner $t}} {{$t.Title}}

  {{end}}

{{end}}

`))
<commit_msg>snippet<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package qopher

import (
	"html/template"
	"net/http"
	"strings"

	"appengine"
	"appengine/datastore"
	"appengine/user"
	"qopher/task"
)

type FrontPage struct {
	NTotal          int
	QueueEmail      string // showing queue for this email address
	QueueEmailShort string
	Yours           []*Task
	Other           []*Task
}

func serveFront(rw http.ResponseWriter, r *http.Request) {
	if !getMethod(r) {
		http.Error(rw, "bad method", http.StatusMethodNotAllowed)
		return
	}
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		http.Error(rw, "login required", http.StatusUnauthorized)
		return
	}

	email := r.FormValue("q")
	if email == "" {
		email = u.Email
	}
	email = mapEmail(email)

	if email == "crash" {
		panic("fake crash")
	}

	q := datastore.NewQuery("Task").Filter("Closed = ", false)
	var tasks []*Task
	_, err := q.GetAll(c, &tasks)
	if err != nil {
		c.Errorf("GetAll: %v", err)
		http.Error(rw, err.Error(), 500)
		return
	}
	numIssues := len(tasks)

	var yours, other []*Task
	for _, t := range tasks {
		if t.Owner == email {
			yours = append(yours, t)
		} else {
			other = append(other, t)
		}
	}

	const maxOther = 200
	if len(other) > maxOther {
		other = other[:maxOther]
	}

	page := &FrontPage{
		NTotal:          numIssues,
		QueueEmail:      email,
		QueueEmailShort: emailToShort(email),
		Yours:           yours,
		Other:           other,
	}

	err = frontPage.ExecuteTemplate(rw, "front", page)
	if err != nil && r.Method != "HEAD" {
		c.Errorf("template error: %v", err)
	}
}

var frontPage = template.Must(template.New("front").Funcs(template.FuncMap{
	"taskURL": func(taskType, id string) string {
		return task.TypeMap[taskType].TaskURL(id)
	},
	"shortOwner": func(t *Task) string {
		if t.Owner == "" {
			return ""
		}
		return emailToShort(t.Owner) + ": "
	},
	"snippet": func(v string) string {
		if i := strings.Index(v, "\n"); i > 0 {
			v = v[:i]
		}
		if len(v) > 100 {
			v = v[:100]
		}
		return v
	},
}).Parse(`
<!doctype html>

    <title>qopher - Go queue</title>

qopher: the Gopher Queue

WORK IN PROGRESS

Total {{$.NTotal}} open tasks

Viewing queue for {{$.QueueEmail}} (change with ?q= nickname or email)

{{if $.Yours}}

Assigned to {{$.QueueEmailShort}} ({{len $.Yours}})

This list doesn't include your open and assigned issues.

  {{range $i, $t := $.Yours}}

{{$t.Type}}.{{$t.ID}}: {{snippet $t.Title}}

  {{end}}

{{else}}

Nothing assigned to {{$.QueueEmail}}

Also check your open and assigned issues.

{{end}}

{{if $.Other}}

Some other open tasks

  {{range $i, $t := $.Other}}

{{$t.Type}}.{{$t.ID}}, owner: {{shortOwner $t}}: {{snippet $t.Title}}

 {{end}}

{{end}}

`))
<|endoftext|>