<commit_before>package cloudwatch

// So a metric is the top level fields that map to the Metric
// info in the serialization layer. So we need a map of names to their
// info. And we can map the rest in the log/publish statement...
import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"time"
)

var envMap map[string]string

func init() {
	// Get them all and turn it into a map...
	// Ref: https://docs.aws.amazon.com/lambda/latest/dg/lambda-environment-variables.html
	envMap = make(map[string]string)
	envVars := os.Environ()
	for _, eachValue := range envVars {
		parts := strings.Split(eachValue, "=")
		if len(parts) == 2 {
			envMap[parts[0]] = parts[1]
		}
	}
}

// MetricDirective represents an element in the array

// MetricUnit Represents a MetricUnit type
type MetricUnit string

const (
	// UnitSeconds Seconds
	UnitSeconds MetricUnit = "Seconds"
	// UnitMicroseconds Microseconds
	UnitMicroseconds MetricUnit = "Microseconds"
	// UnitMilliseconds Milliseconds
	UnitMilliseconds MetricUnit = "Milliseconds"
	// UnitBytes Bytes
	UnitBytes MetricUnit = "Bytes"
	//UnitKilobytes Kilobytes
	UnitKilobytes MetricUnit = "Kilobytes"
	//UnitMegabytes Megabytes
	UnitMegabytes MetricUnit = "Megabytes"
	//UnitGigabytes Gigabytes
	UnitGigabytes MetricUnit = "Gigabytes"
	//UnitTerabytes Terabytes
	UnitTerabytes MetricUnit = "Terabytes"
	//UnitBits Bits
	UnitBits MetricUnit = "Bits"
	//UnitKilobits Kilobits
	UnitKilobits MetricUnit = "Kilobits"
	//UnitMegabits Megabits
	UnitMegabits MetricUnit = "Megabits"
	//UnitGigabits Gigabits
	UnitGigabits MetricUnit = "Gigabits"
	//UnitTerabits Terabits
	UnitTerabits MetricUnit = "Terabits"
	//UnitPercent Percent
	UnitPercent MetricUnit = "Percent"
	//UnitCount Count
	UnitCount MetricUnit = "Count"
	//UnitBytesPerSecond BytesPerSecond
	UnitBytesPerSecond MetricUnit = "Bytes/Second"
	//UnitKilobytesPerSecond KilobytesPerSecond
	UnitKilobytesPerSecond MetricUnit = "Kilobytes/Second"
	//UnitMegabytesPerSecond MegabytesPerSecond
	UnitMegabytesPerSecond MetricUnit = "Megabytes/Second"
	//UnitGigabytesPerSecond GigabytesPerSecond
	UnitGigabytesPerSecond MetricUnit = "Gigabytes/Second"
	//UnitTerabytesPerSecond TerabytesPerSecond
	UnitTerabytesPerSecond MetricUnit = "Terabytes/Second"
	//UnitBitsPerSecond BitsPerSecond
	UnitBitsPerSecond MetricUnit = "Bits/Second"
	//UnitKilobitsPerSecond KilobitsPerSecond
	UnitKilobitsPerSecond MetricUnit = "Kilobits/Second"
	//UnitMegabitsPerSecond MegabitsPerSecond
	UnitMegabitsPerSecond MetricUnit = "Megabits/Second"
	//UnitGigabitsPerSecond GigabitsPerSecond
	UnitGigabitsPerSecond MetricUnit = "Gigabits/Second"
	//UnitTerabitsPerSecond TerabitsPerSecond
	UnitTerabitsPerSecond MetricUnit = "Terabits/Second"
	//UnitCountPerSecond CountPerSecond
	UnitCountPerSecond MetricUnit = "Count/Second"
	// UnitNone No units
	UnitNone MetricUnit = "None"
)

// EmbeddedMetric represents an embedded metric that should be published
type EmbeddedMetric struct {
	metrics    []*MetricDirective
	properties map[string]interface{}
}

// MetricValue represents a metric value
type MetricValue struct {
	Value interface{}
	Unit  MetricUnit
}

// MetricDirective is the directive that encapsulates a metric
type MetricDirective struct {
	// Dimensions corresponds to the JSON schema field "Dimensions".
	Dimensions map[string]string

	// Metrics corresponds to the JSON schema field "Metrics".
	Metrics map[string]MetricValue

	// namespace corresponds to the JSON schema field "Namespace".
	namespace string
}

// NewMetricDirective returns an initialized MetricDirective
// that's included in the EmbeddedMetric instance
func (em *EmbeddedMetric) NewMetricDirective(namespace string) *MetricDirective {
	md := &MetricDirective{
		namespace:  namespace,
		Dimensions: make(map[string]string),
		Metrics:    make(map[string]MetricValue),
	}
	em.metrics = append(em.metrics, md)
	return md
}

// Publish the metric to the logfile
func (em *EmbeddedMetric) Publish(additionalProperties map[string]interface{}) {
	em.properties = additionalProperties
	rawJSON, rawJSONErr := json.Marshal(em)
	if rawJSONErr == nil {
		fmt.Println((string)(rawJSON))
	} else {
		fmt.Printf("Error publishing metric: %v", rawJSONErr)
	}
}

// MarshalJSON is a custom marshaller to ensure that the marshalled
// headers are always lowercase
func (em *EmbeddedMetric) MarshalJSON() ([]byte, error) {
	/* From: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Generation_CloudWatch_Agent.html

	The logs must contain a log_group_name key that tells the agent which log group to use.

	Each log event must be on a single line. In other words, a log event cannot contain the newline (\n) character.
	*/
	jsonMap := map[string]interface{}{
		"log_group_name": envMap["AWS_LAMBDA_LOG_GROUP_NAME"],
		"log_steam_name": envMap["AWS_LAMBDA_LOG_STREAM_NAME"],
	}
	for eachKey, eachValue := range em.properties {
		jsonMap[eachKey] = eachValue
	}
	// Walk everything and create the references...
	cwMetrics := &emfAWS{
		Timestamp:         int((time.Now().UnixNano() / int64(time.Millisecond))),
		CloudWatchMetrics: []emfAWSCloudWatchMetricsElem{},
	}
	for _, eachDirective := range em.metrics {
		metricsElem := emfAWSCloudWatchMetricsElem{
			Dimensions: [][]string{},
			Namespace:  eachDirective.namespace,
			Metrics:    []emfAWSCloudWatchMetricsElemMetricsElem{},
		}

		// Create the references and update the metrics...
		for eachKey, eachMetric := range eachDirective.Metrics {
			jsonMap[eachKey] = eachMetric.Value
			metricsElem.Metrics = append(metricsElem.Metrics,
				emfAWSCloudWatchMetricsElemMetricsElem{
					Name: eachKey,
					Unit: string(eachMetric.Unit),
				})
		}
		for eachKey, eachValue := range eachDirective.Dimensions {
			jsonMap[eachKey] = eachValue
			metricsElem.Dimensions = append(metricsElem.Dimensions,
				[]string{eachKey})
		}
		cwMetrics.CloudWatchMetrics = append(cwMetrics.CloudWatchMetrics,
			metricsElem)
	}
	jsonMap["_aws"] = cwMetrics
	return json.Marshal(jsonMap)
}

// JSON encoding the fields gives us the top level keys, which we need
// to map to the Metrics...
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html#CloudWatch_Embedded_Metric_Format_Specification_structure_target

// NewEmbeddedMetric returns a new fully initialized embedded metric. Callers
// should populate the Fields
func NewEmbeddedMetric() (*EmbeddedMetric, error) {
	embeddedMetric := &EmbeddedMetric{
		metrics:    []*MetricDirective{},
		properties: make(map[string]interface{}),
	}
	return embeddedMetric, nil
}
<commit_msg>Add precondition check for DimensionSet length<commit_after>package cloudwatch

// So a metric is the top level fields that map to the Metric
// info in the serialization layer. So we need a map of names to their
// info. And we can map the rest in the log/publish statement...
import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"time"
)

var envMap map[string]string

func init() {
	// Get them all and turn it into a map...
	// Ref: https://docs.aws.amazon.com/lambda/latest/dg/lambda-environment-variables.html
	envMap = make(map[string]string)
	envVars := os.Environ()
	for _, eachValue := range envVars {
		parts := strings.Split(eachValue, "=")
		if len(parts) == 2 {
			envMap[parts[0]] = parts[1]
		}
	}
}

// MetricDirective represents an element in the array

// MetricUnit Represents a MetricUnit type
type MetricUnit string

const (
	// UnitSeconds Seconds
	UnitSeconds MetricUnit = "Seconds"
	// UnitMicroseconds Microseconds
	UnitMicroseconds MetricUnit = "Microseconds"
	// UnitMilliseconds Milliseconds
	UnitMilliseconds MetricUnit = "Milliseconds"
	// UnitBytes Bytes
	UnitBytes MetricUnit = "Bytes"
	//UnitKilobytes Kilobytes
	UnitKilobytes MetricUnit = "Kilobytes"
	//UnitMegabytes Megabytes
	UnitMegabytes MetricUnit = "Megabytes"
	//UnitGigabytes Gigabytes
	UnitGigabytes MetricUnit = "Gigabytes"
	//UnitTerabytes Terabytes
	UnitTerabytes MetricUnit = "Terabytes"
	//UnitBits Bits
	UnitBits MetricUnit = "Bits"
	//UnitKilobits Kilobits
	UnitKilobits MetricUnit = "Kilobits"
	//UnitMegabits Megabits
	UnitMegabits MetricUnit = "Megabits"
	//UnitGigabits Gigabits
	UnitGigabits MetricUnit = "Gigabits"
	//UnitTerabits Terabits
	UnitTerabits MetricUnit = "Terabits"
	//UnitPercent Percent
	UnitPercent MetricUnit = "Percent"
	//UnitCount Count
	UnitCount MetricUnit = "Count"
	//UnitBytesPerSecond BytesPerSecond
	UnitBytesPerSecond MetricUnit = "Bytes/Second"
	//UnitKilobytesPerSecond KilobytesPerSecond
	UnitKilobytesPerSecond MetricUnit = "Kilobytes/Second"
	//UnitMegabytesPerSecond MegabytesPerSecond
	UnitMegabytesPerSecond MetricUnit = "Megabytes/Second"
	//UnitGigabytesPerSecond GigabytesPerSecond
	UnitGigabytesPerSecond MetricUnit = "Gigabytes/Second"
	//UnitTerabytesPerSecond TerabytesPerSecond
	UnitTerabytesPerSecond MetricUnit = "Terabytes/Second"
	//UnitBitsPerSecond BitsPerSecond
	UnitBitsPerSecond MetricUnit = "Bits/Second"
	//UnitKilobitsPerSecond KilobitsPerSecond
	UnitKilobitsPerSecond MetricUnit = "Kilobits/Second"
	//UnitMegabitsPerSecond MegabitsPerSecond
	UnitMegabitsPerSecond MetricUnit = "Megabits/Second"
	//UnitGigabitsPerSecond GigabitsPerSecond
	UnitGigabitsPerSecond MetricUnit = "Gigabits/Second"
	//UnitTerabitsPerSecond TerabitsPerSecond
	UnitTerabitsPerSecond MetricUnit = "Terabits/Second"
	//UnitCountPerSecond CountPerSecond
	UnitCountPerSecond MetricUnit = "Count/Second"
	// UnitNone No units
	UnitNone MetricUnit = "None"
)

// EmbeddedMetric represents an embedded metric that should be published
type EmbeddedMetric struct {
	metrics    []*MetricDirective
	properties map[string]interface{}
}

// MetricValue represents a metric value
type MetricValue struct {
	Value interface{}
	Unit  MetricUnit
}

// MetricDirective is the directive that encapsulates a metric
type MetricDirective struct {
	// Dimensions corresponds to the JSON schema field "Dimensions".
	Dimensions map[string]string

	// Metrics corresponds to the JSON schema field "Metrics".
	Metrics map[string]MetricValue

	// namespace corresponds to the JSON schema field "Namespace".
	namespace string
}

// NewMetricDirective returns an initialized MetricDirective
// that's included in the EmbeddedMetric instance
func (em *EmbeddedMetric) NewMetricDirective(namespace string) *MetricDirective {
	md := &MetricDirective{
		namespace:  namespace,
		Dimensions: make(map[string]string),
		Metrics:    make(map[string]MetricValue),
	}
	em.metrics = append(em.metrics, md)
	return md
}

// Publish the metric to the logfile
func (em *EmbeddedMetric) Publish(additionalProperties map[string]interface{}) {
	// BEGIN - Preconditions
	for _, eachDirective := range em.metrics {
		// Precondition...
		if len(eachDirective.Dimensions) > 9 {
			fmt.Printf("DimensionSet for structured metric must not have more than 9 elements. Count: %d",
				len(eachDirective.Dimensions))
		}
	}
	// END - Preconditions
	em.properties = additionalProperties
	rawJSON, rawJSONErr := json.Marshal(em)
	if rawJSONErr == nil {
		fmt.Println((string)(rawJSON))
	} else {
		fmt.Printf("Error publishing metric: %v", rawJSONErr)
	}
}

// MarshalJSON is a custom marshaller to ensure that the marshalled
// headers are always lowercase
func (em *EmbeddedMetric) MarshalJSON() ([]byte, error) {
	/* From: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Generation_CloudWatch_Agent.html

	The logs must contain a log_group_name key that tells the agent which log group to use.

	Each log event must be on a single line. In other words, a log event cannot contain the newline (\n) character.
	*/
	jsonMap := map[string]interface{}{
		"log_group_name": envMap["AWS_LAMBDA_LOG_GROUP_NAME"],
		"log_steam_name": envMap["AWS_LAMBDA_LOG_STREAM_NAME"],
	}
	for eachKey, eachValue := range em.properties {
		jsonMap[eachKey] = eachValue
	}
	// Walk everything and create the references...
	cwMetrics := &emfAWS{
		Timestamp:         int((time.Now().UnixNano() / int64(time.Millisecond))),
		CloudWatchMetrics: []emfAWSCloudWatchMetricsElem{},
	}
	for _, eachDirective := range em.metrics {
		metricsElem := emfAWSCloudWatchMetricsElem{
			Dimensions: [][]string{},
			Namespace:  eachDirective.namespace,
			Metrics:    []emfAWSCloudWatchMetricsElemMetricsElem{},
		}

		// Create the references and update the metrics...
		for eachKey, eachMetric := range eachDirective.Metrics {
			jsonMap[eachKey] = eachMetric.Value
			metricsElem.Metrics = append(metricsElem.Metrics,
				emfAWSCloudWatchMetricsElemMetricsElem{
					Name: eachKey,
					Unit: string(eachMetric.Unit),
				})
		}
		for eachKey, eachValue := range eachDirective.Dimensions {
			jsonMap[eachKey] = eachValue
			metricsElem.Dimensions = append(metricsElem.Dimensions,
				[]string{eachKey})
		}
		cwMetrics.CloudWatchMetrics = append(cwMetrics.CloudWatchMetrics,
			metricsElem)
	}
	jsonMap["_aws"] = cwMetrics
	return json.Marshal(jsonMap)
}

// JSON encoding the fields gives us the top level keys, which we need
// to map to the Metrics...
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html#CloudWatch_Embedded_Metric_Format_Specification_structure_target

// NewEmbeddedMetric returns a new fully initialized embedded metric. Callers
// should populate the Fields
func NewEmbeddedMetric() (*EmbeddedMetric, error) {
	embeddedMetric := &EmbeddedMetric{
		metrics:    []*MetricDirective{},
		properties: make(map[string]interface{}),
	}
	return embeddedMetric, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsAcmCertificate() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAcmCertificateCreate,
		Read:   resourceAwsAcmCertificateRead,
		Update: resourceAwsAcmCertificateUpdate,
		Delete: resourceAwsAcmCertificateDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"domain_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subject_alternative_names": {
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"validation_method": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"domain_validation_options": {
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"domain_name": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_name": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_type": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_value": {
							Type:     schema.TypeString,
							Computed: true,
						},
					},
				},
			},
			"validation_emails": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsAcmCertificateCreate(d *schema.ResourceData, meta interface{}) error {
	acmconn := meta.(*AWSClient).acmconn
	params := &acm.RequestCertificateInput{
		DomainName:       aws.String(d.Get("domain_name").(string)),
		ValidationMethod: aws.String(d.Get("validation_method").(string)),
	}

	sans, ok := d.GetOk("subject_alternative_names")
	if ok {
		sanStrings := sans.([]interface{})
		params.SubjectAlternativeNames = expandStringList(sanStrings)
	}

	log.Printf("[DEBUG] ACM Certificate Request: %#v", params)
	resp, err := acmconn.RequestCertificate(params)

	if err != nil {
		return fmt.Errorf("Error requesting certificate: %s", err)
	}

	d.SetId(*resp.CertificateArn)
	if v, ok := d.GetOk("tags"); ok {
		params := &acm.AddTagsToCertificateInput{
			CertificateArn: resp.CertificateArn,
			Tags:           tagsFromMapACM(v.(map[string]interface{})),
		}
		_, err := acmconn.AddTagsToCertificate(params)

		if err != nil {
			return fmt.Errorf("Error requesting certificate: %s", err)
		}
	}

	return resourceAwsAcmCertificateRead(d, meta)
}

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

	params := &acm.DescribeCertificateInput{
		CertificateArn: aws.String(d.Id()),
	}

	return resource.Retry(time.Duration(1)*time.Minute, func() *resource.RetryError {
		resp, err := acmconn.DescribeCertificate(params)

		if err != nil && isAWSErr(err, acm.ErrCodeResourceNotFoundException, "") {
			d.SetId("")
			return nil
		} else if err != nil {
			return resource.NonRetryableError(fmt.Errorf("Error describing certificate: %s", err))
		}

		if *resp.Certificate.Type != acm.CertificateTypeAmazonIssued {
			return resource.NonRetryableError(fmt.Errorf("Certificate has type %s, only AMAZON_ISSUED is supported at the moment", *resp.Certificate.Type))
		}

		d.Set("domain_name", resp.Certificate.DomainName)
		d.Set("arn", resp.Certificate.CertificateArn)

		if err := d.Set("subject_alternative_names", cleanUpSubjectAlternativeNames(resp.Certificate)); err != nil {
			return resource.NonRetryableError(err)
		}

		domainValidationOptions, emailValidationOptions, err := convertValidationOptions(resp.Certificate.DomainValidationOptions)

		if err != nil {
			return resource.RetryableError(err)
		}

		if err := d.Set("domain_validation_options", domainValidationOptions); err != nil {
			return resource.NonRetryableError(err)
		}
		if err := d.Set("validation_emails", emailValidationOptions); err != nil {
			return resource.NonRetryableError(err)
		}
		d.Set("validation_method", resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions, emailValidationOptions))

		params := &acm.ListTagsForCertificateInput{
			CertificateArn: aws.String(d.Id()),
		}

		tagResp, err := acmconn.ListTagsForCertificate(params)
		if err := d.Set("tags", tagsToMapACM(tagResp.Tags)); err != nil {
			return resource.NonRetryableError(err)
		}

		return nil
	})
}
func resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions []map[string]interface{}, emailValidationOptions []string) string {
	// The DescribeCertificate Response doesn't have information on what validation method was used
	// so we need to guess from the validation options we see...
	if len(domainValidationOptions) > 0 {
		return acm.ValidationMethodDns
	} else if len(emailValidationOptions) > 0 {
		return acm.ValidationMethodEmail
	} else {
		return "NONE"
	}
}

func resourceAwsAcmCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
	if d.HasChange("tags") {
		acmconn := meta.(*AWSClient).acmconn
		err := setTagsACM(acmconn, d)
		if err != nil {
			return err
		}
	}
	return nil
}

func cleanUpSubjectAlternativeNames(cert *acm.CertificateDetail) []string {
	sans := cert.SubjectAlternativeNames
	vs := make([]string, 0, len(sans)-1)
	for _, v := range sans {
		if *v != *cert.DomainName {
			vs = append(vs, *v)
		}
	}
	return vs

}

func convertValidationOptions(validations []*acm.DomainValidation) ([]map[string]interface{}, []string, error) {
	var domainValidationResult []map[string]interface{}
	var emailValidationResult []string

	for _, o := range validations {
		if o.ResourceRecord != nil {
			validationOption := map[string]interface{}{
				"domain_name":           *o.DomainName,
				"resource_record_name":  *o.ResourceRecord.Name,
				"resource_record_type":  *o.ResourceRecord.Type,
				"resource_record_value": *o.ResourceRecord.Value,
			}
			domainValidationResult = append(domainValidationResult, validationOption)
		} else if o.ValidationEmails != nil && len(o.ValidationEmails) > 0 {
			for _, validationEmail := range o.ValidationEmails {
				emailValidationResult = append(emailValidationResult, *validationEmail)
			}
		} else {
			log.Printf("[DEBUG] No validation options need to retry: %#v", o)
			return nil, nil, fmt.Errorf("No validation options need to retry: %#v", o)
		}
	}

	return domainValidationResult, emailValidationResult, nil
}

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

	params := &acm.DeleteCertificateInput{
		CertificateArn: aws.String(d.Id()),
	}

	_, err := acmconn.DeleteCertificate(params)

	if err != nil && !isAWSErr(err, acm.ErrCodeResourceNotFoundException, "") {
		return fmt.Errorf("Error deleting certificate: %s", err)
	}

	d.SetId("")
	return nil
}
<commit_msg>r/aws_acm_certificate: Refactor if-statement for readability<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsAcmCertificate() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAcmCertificateCreate,
		Read:   resourceAwsAcmCertificateRead,
		Update: resourceAwsAcmCertificateUpdate,
		Delete: resourceAwsAcmCertificateDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"domain_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subject_alternative_names": {
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"validation_method": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"domain_validation_options": {
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"domain_name": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_name": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_type": {
							Type:     schema.TypeString,
							Computed: true,
						},
						"resource_record_value": {
							Type:     schema.TypeString,
							Computed: true,
						},
					},
				},
			},
			"validation_emails": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsAcmCertificateCreate(d *schema.ResourceData, meta interface{}) error {
	acmconn := meta.(*AWSClient).acmconn
	params := &acm.RequestCertificateInput{
		DomainName:       aws.String(d.Get("domain_name").(string)),
		ValidationMethod: aws.String(d.Get("validation_method").(string)),
	}

	sans, ok := d.GetOk("subject_alternative_names")
	if ok {
		sanStrings := sans.([]interface{})
		params.SubjectAlternativeNames = expandStringList(sanStrings)
	}

	log.Printf("[DEBUG] ACM Certificate Request: %#v", params)
	resp, err := acmconn.RequestCertificate(params)

	if err != nil {
		return fmt.Errorf("Error requesting certificate: %s", err)
	}

	d.SetId(*resp.CertificateArn)
	if v, ok := d.GetOk("tags"); ok {
		params := &acm.AddTagsToCertificateInput{
			CertificateArn: resp.CertificateArn,
			Tags:           tagsFromMapACM(v.(map[string]interface{})),
		}
		_, err := acmconn.AddTagsToCertificate(params)

		if err != nil {
			return fmt.Errorf("Error requesting certificate: %s", err)
		}
	}

	return resourceAwsAcmCertificateRead(d, meta)
}

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

	params := &acm.DescribeCertificateInput{
		CertificateArn: aws.String(d.Id()),
	}

	return resource.Retry(time.Duration(1)*time.Minute, func() *resource.RetryError {
		resp, err := acmconn.DescribeCertificate(params)

		if err != nil {
			if isAWSErr(err, acm.ErrCodeResourceNotFoundException, "") {
				d.SetId("")
				return nil
			}
			return resource.NonRetryableError(fmt.Errorf("Error describing certificate: %s", err))
		}

		if *resp.Certificate.Type != acm.CertificateTypeAmazonIssued {
			return resource.NonRetryableError(fmt.Errorf("Certificate has type %s, only AMAZON_ISSUED is supported at the moment", *resp.Certificate.Type))
		}

		d.Set("domain_name", resp.Certificate.DomainName)
		d.Set("arn", resp.Certificate.CertificateArn)

		if err := d.Set("subject_alternative_names", cleanUpSubjectAlternativeNames(resp.Certificate)); err != nil {
			return resource.NonRetryableError(err)
		}

		domainValidationOptions, emailValidationOptions, err := convertValidationOptions(resp.Certificate.DomainValidationOptions)

		if err != nil {
			return resource.RetryableError(err)
		}

		if err := d.Set("domain_validation_options", domainValidationOptions); err != nil {
			return resource.NonRetryableError(err)
		}
		if err := d.Set("validation_emails", emailValidationOptions); err != nil {
			return resource.NonRetryableError(err)
		}
		d.Set("validation_method", resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions, emailValidationOptions))

		params := &acm.ListTagsForCertificateInput{
			CertificateArn: aws.String(d.Id()),
		}

		tagResp, err := acmconn.ListTagsForCertificate(params)
		if err := d.Set("tags", tagsToMapACM(tagResp.Tags)); err != nil {
			return resource.NonRetryableError(err)
		}

		return nil
	})
}
func resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions []map[string]interface{}, emailValidationOptions []string) string {
	// The DescribeCertificate Response doesn't have information on what validation method was used
	// so we need to guess from the validation options we see...
	if len(domainValidationOptions) > 0 {
		return acm.ValidationMethodDns
	} else if len(emailValidationOptions) > 0 {
		return acm.ValidationMethodEmail
	} else {
		return "NONE"
	}
}

func resourceAwsAcmCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
	if d.HasChange("tags") {
		acmconn := meta.(*AWSClient).acmconn
		err := setTagsACM(acmconn, d)
		if err != nil {
			return err
		}
	}
	return nil
}

func cleanUpSubjectAlternativeNames(cert *acm.CertificateDetail) []string {
	sans := cert.SubjectAlternativeNames
	vs := make([]string, 0, len(sans)-1)
	for _, v := range sans {
		if *v != *cert.DomainName {
			vs = append(vs, *v)
		}
	}
	return vs

}

func convertValidationOptions(validations []*acm.DomainValidation) ([]map[string]interface{}, []string, error) {
	var domainValidationResult []map[string]interface{}
	var emailValidationResult []string

	for _, o := range validations {
		if o.ResourceRecord != nil {
			validationOption := map[string]interface{}{
				"domain_name":           *o.DomainName,
				"resource_record_name":  *o.ResourceRecord.Name,
				"resource_record_type":  *o.ResourceRecord.Type,
				"resource_record_value": *o.ResourceRecord.Value,
			}
			domainValidationResult = append(domainValidationResult, validationOption)
		} else if o.ValidationEmails != nil && len(o.ValidationEmails) > 0 {
			for _, validationEmail := range o.ValidationEmails {
				emailValidationResult = append(emailValidationResult, *validationEmail)
			}
		} else {
			log.Printf("[DEBUG] No validation options need to retry: %#v", o)
			return nil, nil, fmt.Errorf("No validation options need to retry: %#v", o)
		}
	}

	return domainValidationResult, emailValidationResult, nil
}

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

	params := &acm.DeleteCertificateInput{
		CertificateArn: aws.String(d.Id()),
	}

	_, err := acmconn.DeleteCertificate(params)

	if err != nil && !isAWSErr(err, acm.ErrCodeResourceNotFoundException, "") {
		return fmt.Errorf("Error deleting certificate: %s", err)
	}

	d.SetId("")
	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/validation"

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

func resourceAwsAthenaDatabase() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAthenaDatabaseCreate,
		Read:   resourceAwsAthenaDatabaseRead,
		Update: resourceAwsAthenaDatabaseUpdate,
		Delete: resourceAwsAthenaDatabaseDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringMatch(regexp.MustCompile("^[_a-z0-9]+$"), "see https://docs.aws.amazon.com/athena/latest/ug/tables-databases-columns-names.html"),
			},
			"bucket": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"force_destroy": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"encryption_key": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"type": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},
		},
	}
}

func getResultConfig(d *schema.ResourceData) (*athena.ResultConfiguration, error) {
	e := d.Get("encryption_key").([]interface{})
	data := e[0].(map[string]interface{})
	keyType := data["type"].(string)
	keyID := data["id"].(string)

	resultConfig := athena.ResultConfiguration{
		OutputLocation: aws.String("s3://" + d.Get("bucket").(string)),
	}

	if len(keyType) > 0 {
		if strings.HasSuffix(keyType, "_KMS") && len(keyID) <= 0 {
			return nil, fmt.Errorf("Key type %s requires a valid KMS key ID", keyType)
		}

		encryptionConfig := athena.EncryptionConfiguration{
			EncryptionOption: aws.String(keyType),
		}

		if len(keyID) > 0 {
			encryptionConfig.KmsKey = aws.String(keyID)
		}

		resultConfig.EncryptionConfiguration = &encryptionConfig
	}

	return &resultConfig, nil
}

func resourceAwsAthenaDatabaseCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(fmt.Sprintf("create database `%s`;", d.Get("name").(string))),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectNoRowsWhenCreate(*resp.QueryExecutionId, d, conn); err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))
	return resourceAwsAthenaDatabaseRead(d, meta)
}

func resourceAwsAthenaDatabaseRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(fmt.Sprint("show databases;")),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectMatchingRow(*resp.QueryExecutionId, d.Get("name").(string), conn); err != nil {
		return err
	}
	return nil
}

func resourceAwsAthenaDatabaseUpdate(d *schema.ResourceData, meta interface{}) error {
	return resourceAwsAthenaDatabaseRead(d, meta)
}

func resourceAwsAthenaDatabaseDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	name := d.Get("name").(string)

	queryString := fmt.Sprintf("drop database `%s`", name)
	if d.Get("force_destroy").(bool) {
		queryString += " cascade"
	}
	queryString += ";"

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(queryString),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectNoRowsWhenDrop(*resp.QueryExecutionId, d, conn); err != nil {
		return err
	}
	return nil
}

func executeAndExpectNoRowsWhenCreate(qeid string, d *schema.ResourceData, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	if len(rs.Rows) != 0 {
		return fmt.Errorf("Athena create database, unexpected query result: %s", flattenAthenaResultSet(rs))
	}
	return nil
}

func executeAndExpectMatchingRow(qeid string, dbName string, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	for _, row := range rs.Rows {
		for _, datum := range row.Data {
			if *datum.VarCharValue == dbName {
				return nil
			}
		}
	}
	return fmt.Errorf("Athena not found database: %s, query result: %s", dbName, flattenAthenaResultSet(rs))
}

func executeAndExpectNoRowsWhenDrop(qeid string, d *schema.ResourceData, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	if len(rs.Rows) != 0 {
		return fmt.Errorf("Athena drop database, unexpected query result: %s", flattenAthenaResultSet(rs))
	}
	return nil
}

func queryExecutionResult(qeid string, conn *athena.Athena) (*athena.ResultSet, error) {
	executionStateConf := &resource.StateChangeConf{
		Pending:    []string{athena.QueryExecutionStateQueued, athena.QueryExecutionStateRunning},
		Target:     []string{athena.QueryExecutionStateSucceeded},
		Refresh:    queryExecutionStateRefreshFunc(qeid, conn),
		Timeout:    10 * time.Minute,
		Delay:      3 * time.Second,
		MinTimeout: 3 * time.Second,
	}
	_, err := executionStateConf.WaitForState()
	if err != nil {
		return nil, err
	}

	qrinput := &athena.GetQueryResultsInput{
		QueryExecutionId: aws.String(qeid),
	}
	resp, err := conn.GetQueryResults(qrinput)
	if err != nil {
		return nil, err
	}
	return resp.ResultSet, nil
}

func queryExecutionStateRefreshFunc(qeid string, conn *athena.Athena) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		input := &athena.GetQueryExecutionInput{
			QueryExecutionId: aws.String(qeid),
		}
		out, err := conn.GetQueryExecution(input)
		if err != nil {
			return nil, "failed", err
		}
		status := out.QueryExecution.Status
		if *status.State == athena.QueryExecutionStateFailed &&
			status.StateChangeReason != nil {
			err = fmt.Errorf("reason: %s", *status.StateChangeReason)
		}
		return out, *out.QueryExecution.Status.State, err
	}
}

func flattenAthenaResultSet(rs *athena.ResultSet) string {
	ss := make([]string, 0)
	for _, row := range rs.Rows {
		for _, datum := range row.Data {
			ss = append(ss, *datum.VarCharValue)
		}
	}
	return strings.Join(ss, "\n")
}
<commit_msg>Early return if an encryption key isn't passed into the HCL.<commit_after>package aws

import (
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/validation"

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

func resourceAwsAthenaDatabase() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsAthenaDatabaseCreate,
		Read:   resourceAwsAthenaDatabaseRead,
		Update: resourceAwsAthenaDatabaseUpdate,
		Delete: resourceAwsAthenaDatabaseDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringMatch(regexp.MustCompile("^[_a-z0-9]+$"), "see https://docs.aws.amazon.com/athena/latest/ug/tables-databases-columns-names.html"),
			},
			"bucket": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"force_destroy": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"encryption_key": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"type": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},
		},
	}
}

func getResultConfig(d *schema.ResourceData) (*athena.ResultConfiguration, error) {
	resultConfig := athena.ResultConfiguration{
		OutputLocation: aws.String("s3://" + d.Get("bucket").(string)),
	}

	e := d.Get("encryption_key").([]interface{})
	if len(e) <= 0 {
		return &resultConfig
	}

	data := e[0].(map[string]interface{})
	keyType := data["type"].(string)
	keyID := data["id"].(string)

	if len(keyType) <= 0 {
		return fmt.Errorf("An encryption key type is required")
	}

	if strings.HasSuffix(keyType, "_KMS") && len(keyID) <= 0 {
		return nil, fmt.Errorf("Key type %s requires a valid KMS key ID", keyType)
	}

	encryptionConfig := athena.EncryptionConfiguration{
		EncryptionOption: aws.String(keyType),
	}

	if len(keyID) > 0 {
		encryptionConfig.KmsKey = aws.String(keyID)
	}

	resultConfig.EncryptionConfiguration = &encryptionConfig

	return &resultConfig, nil
}

func resourceAwsAthenaDatabaseCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(fmt.Sprintf("create database `%s`;", d.Get("name").(string))),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectNoRowsWhenCreate(*resp.QueryExecutionId, d, conn); err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))
	return resourceAwsAthenaDatabaseRead(d, meta)
}

func resourceAwsAthenaDatabaseRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(fmt.Sprint("show databases;")),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectMatchingRow(*resp.QueryExecutionId, d.Get("name").(string), conn); err != nil {
		return err
	}
	return nil
}

func resourceAwsAthenaDatabaseUpdate(d *schema.ResourceData, meta interface{}) error {
	return resourceAwsAthenaDatabaseRead(d, meta)
}

func resourceAwsAthenaDatabaseDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).athenaconn

	resultConfig, err := getResultConfig(d)
	if err != nil {
		return err
	}

	name := d.Get("name").(string)

	queryString := fmt.Sprintf("drop database `%s`", name)
	if d.Get("force_destroy").(bool) {
		queryString += " cascade"
	}
	queryString += ";"

	input := &athena.StartQueryExecutionInput{
		QueryString:         aws.String(queryString),
		ResultConfiguration: resultConfig,
	}

	resp, err := conn.StartQueryExecution(input)
	if err != nil {
		return err
	}

	if err := executeAndExpectNoRowsWhenDrop(*resp.QueryExecutionId, d, conn); err != nil {
		return err
	}
	return nil
}

func executeAndExpectNoRowsWhenCreate(qeid string, d *schema.ResourceData, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	if len(rs.Rows) != 0 {
		return fmt.Errorf("Athena create database, unexpected query result: %s", flattenAthenaResultSet(rs))
	}
	return nil
}

func executeAndExpectMatchingRow(qeid string, dbName string, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	for _, row := range rs.Rows {
		for _, datum := range row.Data {
			if *datum.VarCharValue == dbName {
				return nil
			}
		}
	}
	return fmt.Errorf("Athena not found database: %s, query result: %s", dbName, flattenAthenaResultSet(rs))
}

func executeAndExpectNoRowsWhenDrop(qeid string, d *schema.ResourceData, conn *athena.Athena) error {
	rs, err := queryExecutionResult(qeid, conn)
	if err != nil {
		return err
	}
	if len(rs.Rows) != 0 {
		return fmt.Errorf("Athena drop database, unexpected query result: %s", flattenAthenaResultSet(rs))
	}
	return nil
}

func queryExecutionResult(qeid string, conn *athena.Athena) (*athena.ResultSet, error) {
	executionStateConf := &resource.StateChangeConf{
		Pending:    []string{athena.QueryExecutionStateQueued, athena.QueryExecutionStateRunning},
		Target:     []string{athena.QueryExecutionStateSucceeded},
		Refresh:    queryExecutionStateRefreshFunc(qeid, conn),
		Timeout:    10 * time.Minute,
		Delay:      3 * time.Second,
		MinTimeout: 3 * time.Second,
	}
	_, err := executionStateConf.WaitForState()
	if err != nil {
		return nil, err
	}

	qrinput := &athena.GetQueryResultsInput{
		QueryExecutionId: aws.String(qeid),
	}
	resp, err := conn.GetQueryResults(qrinput)
	if err != nil {
		return nil, err
	}
	return resp.ResultSet, nil
}

func queryExecutionStateRefreshFunc(qeid string, conn *athena.Athena) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		input := &athena.GetQueryExecutionInput{
			QueryExecutionId: aws.String(qeid),
		}
		out, err := conn.GetQueryExecution(input)
		if err != nil {
			return nil, "failed", err
		}
		status := out.QueryExecution.Status
		if *status.State == athena.QueryExecutionStateFailed &&
			status.StateChangeReason != nil {
			err = fmt.Errorf("reason: %s", *status.StateChangeReason)
		}
		return out, *out.QueryExecution.Status.State, err
	}
}

func flattenAthenaResultSet(rs *athena.ResultSet) string {
	ss := make([]string, 0)
	for _, row := range rs.Rows {
		for _, datum := range row.Data {
			ss = append(ss, *datum.VarCharValue)
		}
	}
	return strings.Join(ss, "\n")
}
<|endoftext|>


<commit_before>package actions

import (
	log "github.com/Sirupsen/logrus"
	"github.com/gaia-docker/tugbot-common"
	"github.com/gaia-docker/tugbot/container"
	"github.com/samalba/dockerclient"
)

// Run looks at Docker containers to see if any of the images
// used to start those containers is a test container.
// For each test container it'll create and start a new container according
// to tugbots' labels.
func Run(client container.Client, names []string, e *dockerclient.Event) error {
	var ec common.ErrorBuilder
	if !container.IsSwarmTask(e) && !container.IsCreatedByTugbot(e) {
		candidates, err := client.ListContainers(containerFilter(names))
		if err != nil {
			return err
		}
		for _, candidate := range candidates {
			if candidate.IsEventListener(e) {
				if err := client.StartContainerFrom(candidate); err != nil {
					log.Error(err)
					ec.Append(err)
				}
			}
		}
	}

	return ec.ToError()
}

func containerFilter(names []string) container.Filter {

	return func(c container.Container) bool {
		return nameFilter(names)(c) && c.IsTugbotCandidate()
	}
}

func nameFilter(names []string) container.Filter {

	if len(names) == 0 {
		// all containers
		return func(container.Container) bool {
			return true
		}
	}

	return func(c container.Container) bool {
		for _, name := range names {
			if (name == c.Name()) || (name == c.Name()[1:]) {
				return true
			}
		}
		return false
	}
}
<commit_msg>small refactor;<commit_after>package actions

import (
	log "github.com/Sirupsen/logrus"
	"github.com/gaia-docker/tugbot-common"
	"github.com/gaia-docker/tugbot/container"
	"github.com/samalba/dockerclient"
)

// Run looks at Docker containers to see if any of the images
// used to start those containers is a test container.
// For each test container it'll create and start a new container according
// to tugbots' labels.
func Run(client container.Client, names []string, e *dockerclient.Event) error {
	var ec common.ErrorBuilder
	if !container.IsSwarmTask(e) && !container.IsCreatedByTugbot(e) {
		candidates, err := client.ListContainers(containerFilter(names))
		if err != nil {
			ec.Append(err)
		} else {
			for _, currCandidate := range candidates {
				if currCandidate.IsEventListener(e) {
					if err := client.StartContainerFrom(currCandidate); err != nil {
						log.Error(err)
						ec.Append(err)
					}
				}
			}
		}
	}

	return ec.ToError()
}

func containerFilter(names []string) container.Filter {
	return func(c container.Container) bool {
		return nameFilter(names)(c) && c.IsTugbotCandidate()
	}
}

func nameFilter(names []string) container.Filter {
	if len(names) == 0 {
		// all containers
		return func(container.Container) bool {
			return true
		}
	}

	return func(c container.Container) bool {
		for _, name := range names {
			if (name == c.Name()) || (name == c.Name()[1:]) {
				return true
			}
		}
		return false
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"fmt"
	"go/build"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/daaku/go.zipexe"
)

func operationAppend(pkgs []*build.Package) {
	if runtime.GOOS == "windows" {
		_, err := exec.LookPath("zip")
		if err != nil {
			fmt.Println("#### WARNING ! ####")
			fmt.Println("`rice append` is known not to work under windows because the `zip` command is not available. Please let me know if you got this to work (and how).")
		}
	}

	// MARKED FOR DELETION
	// This is actually not required, the append command now has the option --exec required.
	// // check if package is a command
	// if !pkg.IsCommand() {
	// 	fmt.Println("Error: can not append to non-main package. Please follow instructions at github.com/GeertJohan/go.rice")
	// 	os.Exit(1)
	// }

	// create tmp zipfile
	tmpZipfileName := filepath.Join(os.TempDir(), fmt.Sprintf("ricebox-%d-%s.zip", time.Now().Unix(), randomString(10)))
	verbosef("Will create tmp zipfile: %s\n", tmpZipfileName)
	tmpZipfile, err := os.Create(tmpZipfileName)
	if err != nil {
		fmt.Printf("Error creating tmp zipfile: %s\n", err)
		os.Exit(1)
	}

	// find abs path for binary file
	binfileName, err := filepath.Abs(flags.Append.Executable)
	if err != nil {
		fmt.Printf("Error finding absolute path for executable to append: %s\n", err)
		os.Exit(1)
	}
	verbosef("Will append to file: %s\n", binfileName)

	// check that command doesn't already have zip appended
	if rd, _ := zipexe.Open(binfileName); rd != nil {
		fmt.Printf("Cannot append to already appended executable. Please remove %s and build a fresh one.\n", binfileName)
		os.Exit(1)
	}

	// open binfile
	binfile, err := os.OpenFile(binfileName, os.O_WRONLY, os.ModeAppend)
	if err != nil {
		fmt.Printf("Error: unable to open executable file: %s\n", err)
		os.Exit(1)
	}

	// create zip.Writer
	zipWriter := zip.NewWriter(tmpZipfile)

	for _, pkg := range pkgs {
		// find boxes for this command
		boxMap := findBoxes(pkg)

		// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
		if len(boxMap) == 0 {
			fmt.Println("no calls to rice.FindBox() or rice.MustFindBox() found")
			return
		}

		verbosef("\n")

		for boxname := range boxMap {
			appendedBoxName := strings.Replace(boxname, `/`, `-`, -1)

			// walk box path's and insert files
			boxPath := filepath.Clean(filepath.Join(pkg.Dir, boxname))
			filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
				// create zipFilename
				zipFileName := filepath.Join(appendedBoxName, strings.TrimPrefix(path, boxPath))

				// write directories as empty file with comment "dir"
				if info.IsDir() {
					_, err := zipWriter.CreateHeader(&zip.FileHeader{
						Name:    zipFileName,
						Comment: "dir",
					})
					if err != nil {
						fmt.Printf("Error creating dir in tmp zip: %s\n", err)
						os.Exit(1)
					}
					return nil
				}

				// create zipFileWriter
				zipFileHeader, err := zip.FileInfoHeader(info)
				if err != nil {
					fmt.Printf("Error creating zip FileHeader: %v\n", err)
					os.Exit(1)
				}
				zipFileHeader.Name = zipFileName
				zipFileWriter, err := zipWriter.CreateHeader(zipFileHeader)
				if err != nil {
					fmt.Printf("Error creating file in tmp zip: %s\n", err)
					os.Exit(1)
				}
				srcFile, err := os.Open(path)
				if err != nil {
					fmt.Printf("Error opening file to append: %s\n", err)
					os.Exit(1)
				}
				_, err = io.Copy(zipFileWriter, srcFile)
				if err != nil {
					fmt.Printf("Error copying file contents to zip: %s\n", err)
					os.Exit(1)
				}
				srcFile.Close()

				return nil
			})
		}
	}

	err = zipWriter.Close()
	if err != nil {
		fmt.Printf("Error closing tmp zipfile: %s\n", err)
		os.Exit(1)
	}

	err = tmpZipfile.Sync()
	if err != nil {
		fmt.Printf("Error syncing tmp zipfile: %s\n", err)
		os.Exit(1)
	}
	_, err = tmpZipfile.Seek(0, 0)
	if err != nil {
		fmt.Printf("Error seeking tmp zipfile: %s\n", err)
		os.Exit(1)
	}
	_, err = binfile.Seek(0, 2)
	if err != nil {
		fmt.Printf("Error seeking bin file: %s\n", err)
		os.Exit(1)
	}

	_, err = io.Copy(binfile, tmpZipfile)
	if err != nil {
		fmt.Printf("Error appending zipfile to executable: %s\n", err)
		os.Exit(1)
	}

	zipA := exec.Command("zip", "-A", binfileName)
	err = zipA.Run()
	if err != nil {
		fmt.Printf("Error setting zip offset: %s\n", err)
		os.Exit(1)
	}
}
<commit_msg>Don't exit when one import path doesn't have FindBox calls.<commit_after>package main

import (
	"archive/zip"
	"fmt"
	"go/build"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/daaku/go.zipexe"
)

func operationAppend(pkgs []*build.Package) {
	if runtime.GOOS == "windows" {
		_, err := exec.LookPath("zip")
		if err != nil {
			fmt.Println("#### WARNING ! ####")
			fmt.Println("`rice append` is known not to work under windows because the `zip` command is not available. Please let me know if you got this to work (and how).")
		}
	}

	// MARKED FOR DELETION
	// This is actually not required, the append command now has the option --exec required.
	// // check if package is a command
	// if !pkg.IsCommand() {
	// 	fmt.Println("Error: can not append to non-main package. Please follow instructions at github.com/GeertJohan/go.rice")
	// 	os.Exit(1)
	// }

	// create tmp zipfile
	tmpZipfileName := filepath.Join(os.TempDir(), fmt.Sprintf("ricebox-%d-%s.zip", time.Now().Unix(), randomString(10)))
	verbosef("Will create tmp zipfile: %s\n", tmpZipfileName)
	tmpZipfile, err := os.Create(tmpZipfileName)
	if err != nil {
		fmt.Printf("Error creating tmp zipfile: %s\n", err)
		os.Exit(1)
	}

	// find abs path for binary file
	binfileName, err := filepath.Abs(flags.Append.Executable)
	if err != nil {
		fmt.Printf("Error finding absolute path for executable to append: %s\n", err)
		os.Exit(1)
	}
	verbosef("Will append to file: %s\n", binfileName)

	// check that command doesn't already have zip appended
	if rd, _ := zipexe.Open(binfileName); rd != nil {
		fmt.Printf("Cannot append to already appended executable. Please remove %s and build a fresh one.\n", binfileName)
		os.Exit(1)
	}

	// open binfile
	binfile, err := os.OpenFile(binfileName, os.O_WRONLY, os.ModeAppend)
	if err != nil {
		fmt.Printf("Error: unable to open executable file: %s\n", err)
		os.Exit(1)
	}

	// create zip.Writer
	zipWriter := zip.NewWriter(tmpZipfile)

	for _, pkg := range pkgs {
		// find boxes for this command
		boxMap := findBoxes(pkg)

		// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
		if len(boxMap) == 0 {
			fmt.Printf("no calls to rice.FindBox() or rice.MustFindBox() found in import path `%s`\n", pkg.ImportPath)
			continue
		}

		verbosef("\n")

		for boxname := range boxMap {
			appendedBoxName := strings.Replace(boxname, `/`, `-`, -1)

			// walk box path's and insert files
			boxPath := filepath.Clean(filepath.Join(pkg.Dir, boxname))
			filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
				// create zipFilename
				zipFileName := filepath.Join(appendedBoxName, strings.TrimPrefix(path, boxPath))

				// write directories as empty file with comment "dir"
				if info.IsDir() {
					_, err := zipWriter.CreateHeader(&zip.FileHeader{
						Name:    zipFileName,
						Comment: "dir",
					})
					if err != nil {
						fmt.Printf("Error creating dir in tmp zip: %s\n", err)
						os.Exit(1)
					}
					return nil
				}

				// create zipFileWriter
				zipFileHeader, err := zip.FileInfoHeader(info)
				if err != nil {
					fmt.Printf("Error creating zip FileHeader: %v\n", err)
					os.Exit(1)
				}
				zipFileHeader.Name = zipFileName
				zipFileWriter, err := zipWriter.CreateHeader(zipFileHeader)
				if err != nil {
					fmt.Printf("Error creating file in tmp zip: %s\n", err)
					os.Exit(1)
				}
				srcFile, err := os.Open(path)
				if err != nil {
					fmt.Printf("Error opening file to append: %s\n", err)
					os.Exit(1)
				}
				_, err = io.Copy(zipFileWriter, srcFile)
				if err != nil {
					fmt.Printf("Error copying file contents to zip: %s\n", err)
					os.Exit(1)
				}
				srcFile.Close()

				return nil
			})
		}
	}

	err = zipWriter.Close()
	if err != nil {
		fmt.Printf("Error closing tmp zipfile: %s\n", err)
		os.Exit(1)
	}

	err = tmpZipfile.Sync()
	if err != nil {
		fmt.Printf("Error syncing tmp zipfile: %s\n", err)
		os.Exit(1)
	}
	_, err = tmpZipfile.Seek(0, 0)
	if err != nil {
		fmt.Printf("Error seeking tmp zipfile: %s\n", err)
		os.Exit(1)
	}
	_, err = binfile.Seek(0, 2)
	if err != nil {
		fmt.Printf("Error seeking bin file: %s\n", err)
		os.Exit(1)
	}

	_, err = io.Copy(binfile, tmpZipfile)
	if err != nil {
		fmt.Printf("Error appending zipfile to executable: %s\n", err)
		os.Exit(1)
	}

	zipA := exec.Command("zip", "-A", binfileName)
	err = zipA.Run()
	if err != nil {
		fmt.Printf("Error setting zip offset: %s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package mpo

import (
	"errors"
	"image"
	"image/color"
)

type colorType int

const (
	// RedCyan is Red on left eye, cyan on right
	RedCyan colorType = iota

	// CyanRed is Cyan on left eye, red on right
	CyanRed

	// RedGreen is Red on left eye, green on right
	RedGreen

	// GreenRed is Green on left eye, red on right
	GreenRed
)

// ErrInvalidImageCount indicates that incorrect number of images were found
// durring the anaglyph conversion proccess.
var ErrInvalidImageCount = errors.New("anaglph conversion only supports 2 image")

// ErrInconsistentBounds indicates that not all images within the MPO file were
// found to be the same size, which is a requirement for the anaglyph conversion.
var ErrInconsistentBounds = errors.New("anaglyph images must be the same size")

// ConvertToAnaglyph converts an MPO to the anaglyph format specified by ct colorType constant
func (m *MPO) ConvertToAnaglyph(ct colorType) (image.Image, error) {
	if len(m.Image) != 2 {
		return nil, ErrInvalidImageCount
	}

	left := m.Image[0]
	right := m.Image[1]

	if !left.Bounds().Eq(right.Bounds()) {
		return nil, ErrInconsistentBounds
	}

	img := image.NewRGBA(left.Bounds())

	for x := 0; x <= left.Bounds().Max.X; x++ {
		for y := 0; y <= left.Bounds().Max.Y; y++ {
			lr, lg, lb, _ := left.At(x, y).RGBA()
			rr, rg, rb, _ := right.At(x, y).RGBA()

			lgs := (((float32(lr) / 65535) * .229) * 65535) +
				(((float32(lg) / 65535) * .587) * 65535) +
				(((float32(lb) / 65535) * .144) * 65535)

			rgs := (((float32(rr) / 65535) * .229) * 65535) +
				(((float32(rg) / 65535) * .587) * 65535) +
				(((float32(rb) / 65535) * .144) * 65535)

			var c color.RGBA64
			switch ct {
			case RedCyan:
				c = color.RGBA64{
					R: uint16(lgs),
					G: uint16(rg),
					B: uint16(rb),
					A: 65535,
				}
			case CyanRed:
				c = color.RGBA64{
					R: uint16(rgs),
					G: uint16(lg),
					B: uint16(lb),
					A: 65535,
				}
			case RedGreen:
				c = color.RGBA64{
					R: uint16(lgs),
					G: uint16(rgs),
					B: 65535 / 2,
					A: 65535,
				}
			case GreenRed:
				c = color.RGBA64{
					R: uint16(rgs),
					G: uint16(lgs),
					B: 65535 / 2,
					A: 65535,
				}
			default:
				return nil, errors.New("unsupported color type")
			}

			img.Set(x, y, c)
		}
	}

	return img, nil
}
<commit_msg>Corrects spelling<commit_after>package mpo

import (
	"errors"
	"image"
	"image/color"
)

type colorType int

const (
	// RedCyan is Red on left eye, cyan on right
	RedCyan colorType = iota

	// CyanRed is Cyan on left eye, red on right
	CyanRed

	// RedGreen is Red on left eye, green on right
	RedGreen

	// GreenRed is Green on left eye, red on right
	GreenRed
)

// ErrInvalidImageCount indicates that incorrect number of images were found
// during the anaglyph conversion process.
var ErrInvalidImageCount = errors.New("anaglph conversion only supports 2 image")

// ErrInconsistentBounds indicates that not all images within the MPO file were
// found to be the same size, which is a requirement for the anaglyph conversion.
var ErrInconsistentBounds = errors.New("anaglyph images must be the same size")

// ConvertToAnaglyph converts an MPO to the anaglyph format specified by ct colorType constant
func (m *MPO) ConvertToAnaglyph(ct colorType) (image.Image, error) {
	if len(m.Image) != 2 {
		return nil, ErrInvalidImageCount
	}

	left := m.Image[0]
	right := m.Image[1]

	if !left.Bounds().Eq(right.Bounds()) {
		return nil, ErrInconsistentBounds
	}

	img := image.NewRGBA(left.Bounds())

	for x := 0; x <= left.Bounds().Max.X; x++ {
		for y := 0; y <= left.Bounds().Max.Y; y++ {
			lr, lg, lb, _ := left.At(x, y).RGBA()
			rr, rg, rb, _ := right.At(x, y).RGBA()

			lgs := (((float32(lr) / 65535) * .229) * 65535) +
				(((float32(lg) / 65535) * .587) * 65535) +
				(((float32(lb) / 65535) * .144) * 65535)

			rgs := (((float32(rr) / 65535) * .229) * 65535) +
				(((float32(rg) / 65535) * .587) * 65535) +
				(((float32(rb) / 65535) * .144) * 65535)

			var c color.RGBA64
			switch ct {
			case RedCyan:
				c = color.RGBA64{
					R: uint16(lgs),
					G: uint16(rg),
					B: uint16(rb),
					A: 65535,
				}
			case CyanRed:
				c = color.RGBA64{
					R: uint16(rgs),
					G: uint16(lg),
					B: uint16(lb),
					A: 65535,
				}
			case RedGreen:
				c = color.RGBA64{
					R: uint16(lgs),
					G: uint16(rgs),
					B: 65535 / 2,
					A: 65535,
				}
			case GreenRed:
				c = color.RGBA64{
					R: uint16(rgs),
					G: uint16(lgs),
					B: 65535 / 2,
					A: 65535,
				}
			default:
				return nil, errors.New("unsupported color type")
			}

			img.Set(x, y, c)
		}
	}

	return img, nil
}
<|endoftext|>


<commit_before>package config

import (
	"errors"
	"flag"
	"fmt"
	"github.com/kormat/go-slackapi/util"
	"io/ioutil"
	"net/url"
)

type Config struct {
	Token       string
	APIEndpoint string
	GlogFlags   []string
}

var Cfg *Config
var CfgErr error
var defAPIEndpoint = "https://slack.com/api"

func Load(path string) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		CfgErr = errors.New(fmt.Sprintf("config: Error reading file: %v", err))
		return
	}
	Cfg = &Config{}
	if util.ParseJSON(input, Cfg) != nil {
		CfgErr = errors.New(fmt.Sprintf("config: JSON parsing failure: %v", err))
		return
	}
	flag.CommandLine.Parse(Cfg.GlogFlags)
	if len(Cfg.Token) == 0 {
		CfgErr = errors.New(fmt.Sprintf("config: No token specified."))
		return
	}
	if len(Cfg.APIEndpoint) == 0 {
		Cfg.APIEndpoint = defAPIEndpoint
	}
}

func MakeURLValues(values map[string]string) url.Values {
	v := url.Values{}
	v.Set("token", Cfg.Token)
	v.Set("pretty", "1")
	for key, val := range values {
		v.Set(key, val)
	}
	return v
}
<commit_msg>Add config.Set<commit_after>package config

import (
	"errors"
	"flag"
	"fmt"
	"github.com/kormat/go-slackapi/util"
	"io/ioutil"
	"net/url"
)

type Config struct {
	Token       string
	APIEndpoint string
	GlogFlags   []string
}

var Cfg *Config
var CfgErr error
var defAPIEndpoint = "https://slack.com/api"
var configured = false

func Load(path string) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		CfgErr = errors.New(fmt.Sprintf("config: Error reading file: %v", err))
		return
	}
	Cfg = &Config{}
	if util.ParseJSON(input, Cfg) != nil {
		CfgErr = errors.New(fmt.Sprintf("config: JSON parsing failure: %v", err))
		return
	}
	flag.CommandLine.Parse(Cfg.GlogFlags)
	if len(Cfg.Token) == 0 {
		CfgErr = errors.New(fmt.Sprintf("config: No token specified."))
		return
	}
	if len(Cfg.APIEndpoint) == 0 {
		Cfg.APIEndpoint = defAPIEndpoint
	}
	configured = true
}

func Set(cfg *Config) {
	if len(cfg.Token) == 0 {
		panic("slackapi.config: No token specified.")
	}
	if len(cfg.APIEndpoint) == 0 {
		cfg.APIEndpoint = defAPIEndpoint
	}
	Cfg = cfg
	configured = true
}

func MakeURLValues(values map[string]string) url.Values {
	if !configured {
		panic("slackapi.config: slackapi not configured")
	}
	v := url.Values{}
	v.Set("token", Cfg.Token)
	v.Set("pretty", "1")
	for key, val := range values {
		v.Set(key, val)
	}
	return v
}
<|endoftext|>


<commit_before>package remote

import (
	"context"
	"strings"
	"testing"

	tfe "github.com/hashicorp/go-tfe"
	"github.com/hashicorp/terraform/backend"
	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
)

func testOperationPlan() *backend.Operation {
	return &backend.Operation{
		Type: backend.OperationTypePlan,
	}
}

func TestRemote_planBasic(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("error running operation: %v", run.Err)
	}

	output := b.CLI.(*cli.MockUi).OutputWriter.String()
	if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
		t.Fatalf("missing plan summery in output: %s", output)
	}
}

func TestRemote_planWithPlan(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Plan = &terraform.Plan{}
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "saved plan is currently not supported") {
		t.Fatalf("expected a saved plan error, got: %v", run.Err)
	}
}

func TestRemote_planWithPath(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.PlanOutPath = "./test-fixtures/plan"
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "generated plan is currently not supported") {
		t.Fatalf("expected a generated plan error, got: %v", run.Err)
	}
}

func TestRemote_planWithTarget(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Targets = []string{"null_resource.foo"}
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "targeting is currently not supported") {
		t.Fatalf("expected a targeting error, got: %v", run.Err)
	}
}

func TestRemote_planNoConfig(t *testing.T) {
	b := testBackendDefault(t)

	op := testOperationPlan()
	op.Module = nil
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "configuration files found") {
		t.Fatalf("expected configuration files error, got: %v", run.Err)
	}
}

func TestRemote_planDestroy(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Destroy = true
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("unexpected plan error: %v", run.Err)
	}
}

func TestRemote_planDestroyNoConfig(t *testing.T) {
	b := testBackendDefault(t)

	op := testOperationPlan()
	op.Destroy = true
	op.Module = nil
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("unexpected plan error: %v", run.Err)
	}
}

func TestRemote_planWithWorkingDirectory(t *testing.T) {
	b := testBackendDefault(t)

	options := tfe.WorkspaceUpdateOptions{
		WorkingDirectory: tfe.String("terraform"),
	}

	// Configure the workspace to use a custom working direcrtory.
	_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.workspace, options)
	if err != nil {
		t.Fatalf("error configuring working directory: %v", err)
	}

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan-with-working-directory/terraform")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("error running operation: %v", run.Err)
	}

	output := b.CLI.(*cli.MockUi).OutputWriter.String()
	if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
		t.Fatalf("missing plan summery in output: %s", output)
	}
}
<commit_msg>Test lock timeout errors when running a plan<commit_after>package remote

import (
	"context"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"testing"
	"time"

	tfe "github.com/hashicorp/go-tfe"
	"github.com/hashicorp/terraform/backend"
	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
)

func testOperationPlan() *backend.Operation {
	return &backend.Operation{
		Type: backend.OperationTypePlan,
	}
}

func TestRemote_planBasic(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("error running operation: %v", run.Err)
	}

	output := b.CLI.(*cli.MockUi).OutputWriter.String()
	if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
		t.Fatalf("missing plan summery in output: %s", output)
	}
}

func TestRemote_planWithPlan(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Plan = &terraform.Plan{}
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "saved plan is currently not supported") {
		t.Fatalf("expected a saved plan error, got: %v", run.Err)
	}
}

func TestRemote_planWithPath(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.PlanOutPath = "./test-fixtures/plan"
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "generated plan is currently not supported") {
		t.Fatalf("expected a generated plan error, got: %v", run.Err)
	}
}

func TestRemote_planWithTarget(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Targets = []string{"null_resource.foo"}
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "targeting is currently not supported") {
		t.Fatalf("expected a targeting error, got: %v", run.Err)
	}
}

func TestRemote_planNoConfig(t *testing.T) {
	b := testBackendDefault(t)

	op := testOperationPlan()
	op.Module = nil
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}
	<-run.Done()

	if run.Err == nil {
		t.Fatalf("expected a plan error, got: %v", run.Err)
	}
	if !strings.Contains(run.Err.Error(), "configuration files found") {
		t.Fatalf("expected configuration files error, got: %v", run.Err)
	}
}

func TestRemote_planLockTimeout(t *testing.T) {
	b := testBackendDefault(t)
	ctx := context.Background()

	// Retrieve the workspace used to run this operation in.
	w, err := b.client.Workspaces.Read(ctx, b.organization, b.workspace)
	if err != nil {
		t.Fatalf("error retrieving workspace: %v", err)
	}

	// Create a new configuration version.
	c, err := b.client.ConfigurationVersions.Create(ctx, w.ID, tfe.ConfigurationVersionCreateOptions{})
	if err != nil {
		t.Fatalf("error creating configuration version: %v", err)
	}

	// Create a pending run to block this run.
	_, err = b.client.Runs.Create(ctx, tfe.RunCreateOptions{
		ConfigurationVersion: c,
		Workspace:            w,
	})
	if err != nil {
		t.Fatalf("error creating pending run: %v", err)
	}

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	input := testInput(t, map[string]string{
		"cancel":  "yes",
		"approve": "yes",
	})

	op := testOperationPlan()
	op.StateLockTimeout = 5 * time.Second
	op.Module = mod
	op.UIIn = input
	op.UIOut = b.CLI
	op.Workspace = backend.DefaultStateName

	_, err = b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, syscall.SIGINT)
	select {
	case <-sigint:
		// Stop redirecting SIGINT signals.
		signal.Stop(sigint)
	case <-time.After(10 * time.Second):
		t.Fatalf("expected lock timeout after 5 seconds, waited 10 seconds")
	}

	if len(input.answers) != 2 {
		t.Fatalf("expected unused answers, got: %v", input.answers)
	}

	output := b.CLI.(*cli.MockUi).OutputWriter.String()
	if !strings.Contains(output, "Lock timeout exceeded") {
		t.Fatalf("missing lock timout error in output: %s", output)
	}
	if strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
		t.Fatalf("unexpected plan summery in output: %s", output)
	}
}

func TestRemote_planDestroy(t *testing.T) {
	b := testBackendDefault(t)

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
	defer modCleanup()

	op := testOperationPlan()
	op.Destroy = true
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("unexpected plan error: %v", run.Err)
	}
}

func TestRemote_planDestroyNoConfig(t *testing.T) {
	b := testBackendDefault(t)

	op := testOperationPlan()
	op.Destroy = true
	op.Module = nil
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("unexpected plan error: %v", run.Err)
	}
}

func TestRemote_planWithWorkingDirectory(t *testing.T) {
	b := testBackendDefault(t)

	options := tfe.WorkspaceUpdateOptions{
		WorkingDirectory: tfe.String("terraform"),
	}

	// Configure the workspace to use a custom working direcrtory.
	_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.workspace, options)
	if err != nil {
		t.Fatalf("error configuring working directory: %v", err)
	}

	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan-with-working-directory/terraform")
	defer modCleanup()

	op := testOperationPlan()
	op.Module = mod
	op.Workspace = backend.DefaultStateName

	run, err := b.Operation(context.Background(), op)
	if err != nil {
		t.Fatalf("error starting operation: %v", err)
	}

	<-run.Done()
	if run.Err != nil {
		t.Fatalf("error running operation: %v", run.Err)
	}

	output := b.CLI.(*cli.MockUi).OutputWriter.String()
	if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
		t.Fatalf("missing plan summery in output: %s", output)
	}
}
<|endoftext|>


<commit_before>package config

import (
    "fmt"
    "log/syslog"

    "github.com/kelseyhightower/envconfig"
)

type ServiceENV string
type ServiceVersion string

func NewCustomConfigPrefix(s string) string {
    return fmt.Sprintf("%s_%s", "SERVICE_CUSTOM", s)
}

func newConfigPrefix(s string) string {
    return fmt.Sprintf("%s_%s", "SERVICE", s)
}

const (
    ServiceENVDev     ServiceENV = "dev"
    ServiceENVStaging ServiceENV = "staging"
    ServiceENVProd    ServiceENV = "production"
)

type ServiceConfig struct {
    ServiceName    string
    ServiceENV     ServiceENV
    ServiceVersion string
    ServiceTags    []string

    TraceHost string
    TracePort int

    LoggerNetwork  string
    LoggerADDR     string
    LoggerPriority syslog.Priority
}

func NewServiceConfig() *ServiceConfig {
    var serviceConfig ServiceConfig
    envconfig.Process(newConfigPrefix("SERVICE"), &serviceConfig)
    fmt.Println(serviceConfig)
    return &serviceConfig
}
<commit_msg>added config field: serviceid<commit_after>package config

import (
	"fmt"
	"log/syslog"

	"github.com/kelseyhightower/envconfig"
)

type ServiceENV string
type ServiceVersion string

func NewCustomConfigPrefix(s string) string {
	return fmt.Sprintf("%s_%s", "SERVICE_CUSTOM", s)
}

func newConfigPrefix(s string) string {
	return fmt.Sprintf("%s_%s", "SERVICE", s)
}

const (
	ServiceENVDev     ServiceENV = "dev"
	ServiceENVStaging ServiceENV = "staging"
	ServiceENVProd    ServiceENV = "production"
)

type ServiceConfig struct {
	ServiceID      string
	ServiceName    string
	ServiceENV     ServiceENV
	ServiceVersion string
	ServiceTags    []string

	TraceHost string
	TracePort int

	LoggerNetwork  string
	LoggerADDR     string
	LoggerPriority syslog.Priority
}

func NewServiceConfig() *ServiceConfig {
	var serviceConfig ServiceConfig
	envconfig.Process(newConfigPrefix("SERVICE"), &serviceConfig)
	fmt.Println(serviceConfig)
	return &serviceConfig
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"os"

	"github.com/jvehent/gozdef"
	"gopkg.in/gcfg.v1"
)

type Config struct {
	General struct {
		Enable         bool
		Postgres       string
		PostgresDB     string
		PostgresUser   string
		PostgresPass   string
		CipherscanPath string
		GoRoutines     int // * cores = The Max number of spawned Goroutines
	}
	TrustStores struct {
		Name []string
		Path []string
	}
	MozDef gozdef.MqConf
}

func Load(path string) (conf Config, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("configLoad() -> %v", e)
		}
	}()
	err = gcfg.ReadFileInto(&conf, path)
	if err != nil {
		panic(err)
	}
	if os.Getenv("TLSOBS_POSTGRES") != "" {
		conf.General.Postgres = os.Getenv("TLSOBS_POSTGRES")
	}
	if os.Getenv("TLSOBS_POSTGRESDB") != "" {
		conf.General.PostgresDB = os.Getenv("TLSOBS_POSTGRESDB")
	}
	if os.Getenv("TLSOBS_POSTGRESUSER") != "" {
		conf.General.PostgresUser = os.Getenv("TLSOBS_POSTGRESUSER")
	}
	if os.Getenv("TLSOBS_POSTGRESPASS") != "" {
		conf.General.PostgresPass = os.Getenv("TLSOBS_POSTGRESPASS")
	}
	return
}
<commit_msg>made truststore declaration specific, only known and specific truststores ( at least their names ) can be imported.<commit_after>package config

import (
	"fmt"
	"os"

	"github.com/jvehent/gozdef"
	"gopkg.in/gcfg.v1"
)

type Config struct {
	General struct {
		Enable         bool
		Postgres       string
		PostgresDB     string
		PostgresUser   string
		PostgresPass   string
		CipherscanPath string
		GoRoutines     int // * cores = The Max number of spawned Goroutines
	}
	TrustStores struct {
		Ubuntu_TS    string
		Mozilla_TS   string
		Microsoft_TS string
		Apple_TS     string
		Android_TS   string
	}
	MozDef gozdef.MqConf
}

func Load(path string) (conf Config, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("configLoad() -> %v", e)
		}
	}()
	err = gcfg.ReadFileInto(&conf, path)
	if err != nil {
		panic(err)
	}
	if os.Getenv("TLSOBS_POSTGRES") != "" {
		conf.General.Postgres = os.Getenv("TLSOBS_POSTGRES")
	}
	if os.Getenv("TLSOBS_POSTGRESDB") != "" {
		conf.General.PostgresDB = os.Getenv("TLSOBS_POSTGRESDB")
	}
	if os.Getenv("TLSOBS_POSTGRESUSER") != "" {
		conf.General.PostgresUser = os.Getenv("TLSOBS_POSTGRESUSER")
	}
	if os.Getenv("TLSOBS_POSTGRESPASS") != "" {
		conf.General.PostgresPass = os.Getenv("TLSOBS_POSTGRESPASS")
	}
	return
}
<|endoftext|>


<commit_before>package convertutil

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"

	"github.com/grokify/gotilla/cmd/cmdutil"
	"github.com/grokify/gotilla/image/imageutil"
	"github.com/grokify/gotilla/math/mathutil"
	"github.com/grokify/gotilla/type/stringsutil"
)

/*
https://stackoverflow.com/questions/9586048/imagemagick-no-decode-delegate

brew uninstall graphicsmagick jpeg libtiff jasper
brew install imagemagick

*/

const (
	PdfWidth                      = 1950 // Ideal max image width
	PdfHeight                     = 2350 // Ideal max image height
	KindleWidth                   = 1400 // 600
	PressDpi                      = 300
	WebDpi                        = 72
	ResolutionPixelsPerInchString = "PixelsPerInch"
	ConvertFormat                 = `convert %s -resize %sX%s %s %s %s`
	//ConvertFormat                 = `convert %s -resize %sx%s -set units %s -density %d %s`
)

type ResolutionUnits int

const (
	ResolutionUndefined           ResolutionUnits = iota // 0 convert cli value
	ResolutionPixelsPerInch                              // 1 convert cli value
	ResolutionPixelsPerCentimeter                        // 2 convert cli value
)

type ConvertParams struct {
	SourcePath        string
	OutputPath        string
	OutputWidth       int
	OutputHeight      int
	ResolutionDensity int
	ResolutionUnits   ResolutionUnits
}

/*
	cmdPDF := convertutil.ConvertCommand(
		filepathOrg, filepathPDF, convertutil.PdfWidth, 0, convertutil.PressDpi,
		convertutil.ResolutionPixelsPerInch)
*/

//func ConvertCommand(srcPath, outPath string, width, height, resolutionDensity, resolutionUnits int) string {

func ConvertCommand(params ConvertParams) string {
	widthStr := ""
	heightStr := ""
	densityStr := ""
	unitsStr := ""
	if params.OutputWidth > 0 {
		widthStr = strconv.Itoa(params.OutputWidth)
	}
	if params.OutputHeight > 0 {
		heightStr = strconv.Itoa(params.OutputHeight)
	}
	if params.ResolutionDensity > 0 {
		densityStr = fmt.Sprintf(" -density %d", params.ResolutionDensity)
	} /*
		if len(resolutionUnits) > 0 {
			unitsStr = fmt.Sprintf(` -set units %s`, resolutionUnits)
		}*/
	if params.ResolutionUnits == ResolutionPixelsPerInch {
		unitsStr = fmt.Sprintf(` -set units %s`, ResolutionPixelsPerInchString)
	}
	if 1 == 0 {
		quote := `"`
		params.SourcePath = quote + strings.TrimSpace(params.SourcePath) + quote
		params.OutputPath = quote + strings.TrimSpace(params.OutputPath) + quote
	}
	cmd := fmt.Sprintf(
		ConvertFormat,
		params.SourcePath,
		widthStr,
		heightStr,
		unitsStr,
		densityStr,
		params.OutputPath)

	return cmd

	//convert input.jpg -resize 1950x -set units PixelsPerInch -density 300 output.jpg
}

func ConvertToKindle(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       KindleWidth,
		OutputHeight:      0,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	return cmdutil.ExecSimple(command)
}

func ConvertToPDFSimple(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       PdfWidth,
		OutputHeight:      0,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	return cmdutil.ExecSimple(command)
}

func ConvertToPDF(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	buf := bytes.NewBufferString("")
	w, h, err := imageutil.ReadImageDimensions(sourcePath)
	if err != nil {
		return *buf, *buf, err
	}

	outputWidth := 0
	outputHeight := 0
	_, calcY := mathutil.RatioInt(w, h, PdfWidth, 0)
	if calcY >= PdfHeight {
		outputHeight = PdfHeight
	} else {
		outputWidth = PdfWidth
	}

	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       outputWidth,
		OutputHeight:      outputHeight,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	stdout, stderr, err := cmdutil.ExecSimple(command)
	fmt.Printf("STDERR: %s\n", stderr.String())
	fmt.Printf("GOLERR: %s\n", err.Error())
	fmt.Printf("INDEX: %v\n", strings.Index(stderr.String(), convertError))
	return stdout, stderr, err
	//return cmdutil.ExecSimple(command)
}

const (
	convertErrorStatus = "exit status 1"
	convertError       = "convert: no decode delegate for this image format `'"
)

// CheckError removes the error if ReadImage doesn't work.
// exit status 1: convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/501.
func CheckError(err error, stderr bytes.Buffer) error {
	if err.Error() == convertErrorStatus &&
		strings.Index(stderr.String(), convertError) > -1 {
		return nil
	}
	if stringsutil.SubstringIsSuffix(err.Error(), convertErrorStatus) {
		return nil
	}
	return err
}
<commit_msg>update convertutil.KindleWidth<commit_after>package convertutil

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"

	"github.com/grokify/gotilla/cmd/cmdutil"
	"github.com/grokify/gotilla/image/imageutil"
	"github.com/grokify/gotilla/math/mathutil"
	"github.com/grokify/gotilla/type/stringsutil"
)

/*
https://stackoverflow.com/questions/9586048/imagemagick-no-decode-delegate

brew uninstall graphicsmagick jpeg libtiff jasper
brew install imagemagick

*/

const (
	PdfWidth                      = 1950 // Ideal max image width
	PdfHeight                     = 2350 // Ideal max image height
	KindleWidth                   = 600  // 1400
	PressDpi                      = 300
	WebDpi                        = 72
	ResolutionPixelsPerInchString = "PixelsPerInch"
	ConvertFormat                 = `convert %s -resize %sX%s %s %s %s`
	//ConvertFormat                 = `convert %s -resize %sx%s -set units %s -density %d %s`
)

type ResolutionUnits int

const (
	ResolutionUndefined           ResolutionUnits = iota // 0 convert cli value
	ResolutionPixelsPerInch                              // 1 convert cli value
	ResolutionPixelsPerCentimeter                        // 2 convert cli value
)

type ConvertParams struct {
	SourcePath        string
	OutputPath        string
	OutputWidth       int
	OutputHeight      int
	ResolutionDensity int
	ResolutionUnits   ResolutionUnits
}

/*
	cmdPDF := convertutil.ConvertCommand(
		filepathOrg, filepathPDF, convertutil.PdfWidth, 0, convertutil.PressDpi,
		convertutil.ResolutionPixelsPerInch)
*/

//func ConvertCommand(srcPath, outPath string, width, height, resolutionDensity, resolutionUnits int) string {

func ConvertCommand(params ConvertParams) string {
	widthStr := ""
	heightStr := ""
	densityStr := ""
	unitsStr := ""
	if params.OutputWidth > 0 {
		widthStr = strconv.Itoa(params.OutputWidth)
	}
	if params.OutputHeight > 0 {
		heightStr = strconv.Itoa(params.OutputHeight)
	}
	if params.ResolutionDensity > 0 {
		densityStr = fmt.Sprintf(" -density %d", params.ResolutionDensity)
	} /*
		if len(resolutionUnits) > 0 {
			unitsStr = fmt.Sprintf(` -set units %s`, resolutionUnits)
		}*/
	if params.ResolutionUnits == ResolutionPixelsPerInch {
		unitsStr = fmt.Sprintf(` -set units %s`, ResolutionPixelsPerInchString)
	}
	if 1 == 0 {
		quote := `"`
		params.SourcePath = quote + strings.TrimSpace(params.SourcePath) + quote
		params.OutputPath = quote + strings.TrimSpace(params.OutputPath) + quote
	}
	cmd := fmt.Sprintf(
		ConvertFormat,
		params.SourcePath,
		widthStr,
		heightStr,
		unitsStr,
		densityStr,
		params.OutputPath)

	return cmd

	//convert input.jpg -resize 1950x -set units PixelsPerInch -density 300 output.jpg
}

func ConvertToKindle(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       KindleWidth,
		OutputHeight:      0,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	return cmdutil.ExecSimple(command)
}

func ConvertToPDFSimple(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       PdfWidth,
		OutputHeight:      0,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	return cmdutil.ExecSimple(command)
}

func ConvertToPDF(sourcePath, outputPath string) (bytes.Buffer, bytes.Buffer, error) {
	buf := bytes.NewBufferString("")
	w, h, err := imageutil.ReadImageDimensions(sourcePath)
	if err != nil {
		return *buf, *buf, err
	}

	outputWidth := 0
	outputHeight := 0
	_, calcY := mathutil.RatioInt(w, h, PdfWidth, 0)
	if calcY >= PdfHeight {
		outputHeight = PdfHeight
	} else {
		outputWidth = PdfWidth
	}

	command := ConvertCommand(ConvertParams{
		SourcePath:        sourcePath,
		OutputPath:        outputPath,
		OutputWidth:       outputWidth,
		OutputHeight:      outputHeight,
		ResolutionDensity: PressDpi,
		ResolutionUnits:   ResolutionPixelsPerInch})
	stdout, stderr, err := cmdutil.ExecSimple(command)
	fmt.Printf("STDERR: %s\n", stderr.String())
	fmt.Printf("GOLERR: %s\n", err.Error())
	fmt.Printf("INDEX: %v\n", strings.Index(stderr.String(), convertError))
	return stdout, stderr, err
	//return cmdutil.ExecSimple(command)
}

const (
	convertErrorStatus = "exit status 1"
	convertError       = "convert: no decode delegate for this image format `'"
)

// CheckError removes the error if ReadImage doesn't work.
// exit status 1: convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/501.
func CheckError(err error, stderr bytes.Buffer) error {
	if err.Error() == convertErrorStatus &&
		strings.Index(stderr.String(), convertError) > -1 {
		return nil
	}
	if stringsutil.SubstringIsSuffix(err.Error(), convertErrorStatus) {
		return nil
	}
	return err
}
<|endoftext|>


<commit_before>package dockerignore

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestReadAll(t *testing.T) {
	tmpDir, err := ioutil.TempDir("", "dockerignore-test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpDir)

	di, err := ReadAll(nil)
	if err != nil {
		t.Fatalf("Expected not to have error, got %v", err)
	}

	if diLen := len(di); diLen != 0 {
		t.Fatalf("Expected to have zero dockerignore entry, got %d", diLen)
	}

	diName := filepath.Join(tmpDir, ".dockerignore")
	content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile")
	err = ioutil.WriteFile(diName, []byte(content), 0777)
	if err != nil {
		t.Fatal(err)
	}

	diFd, err := os.Open(diName)
	if err != nil {
		t.Fatal(err)
	}
	defer diFd.Close()

	di, err = ReadAll(diFd)
	if err != nil {
		t.Fatal(err)
	}

	if di[0] != "test1" {
		t.Fatalf("First element is not test1")
	}
	if di[1] != "/test2" {
		t.Fatalf("Second element is not /test2")
	}
	if di[2] != "/a/file/here" {
		t.Fatalf("Third element is not /a/file/here")
	}
	if di[3] != "lastfile" {
		t.Fatalf("Fourth element is not lastfile")
	}
}
<commit_msg>use t.Fatal() to output the err message where the values used for formatting text does not appear to contain a placeholder<commit_after>package dockerignore

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestReadAll(t *testing.T) {
	tmpDir, err := ioutil.TempDir("", "dockerignore-test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpDir)

	di, err := ReadAll(nil)
	if err != nil {
		t.Fatalf("Expected not to have error, got %v", err)
	}

	if diLen := len(di); diLen != 0 {
		t.Fatalf("Expected to have zero dockerignore entry, got %d", diLen)
	}

	diName := filepath.Join(tmpDir, ".dockerignore")
	content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile")
	err = ioutil.WriteFile(diName, []byte(content), 0777)
	if err != nil {
		t.Fatal(err)
	}

	diFd, err := os.Open(diName)
	if err != nil {
		t.Fatal(err)
	}
	defer diFd.Close()

	di, err = ReadAll(diFd)
	if err != nil {
		t.Fatal(err)
	}

	if di[0] != "test1" {
		t.Fatal("First element is not test1")
	}
	if di[1] != "/test2" {
		t.Fatal("Second element is not /test2")
	}
	if di[2] != "/a/file/here" {
		t.Fatal("Third element is not /a/file/here")
	}
	if di[3] != "lastfile" {
		t.Fatal("Fourth element is not lastfile")
	}
}
<|endoftext|>


<commit_before>package repository

import (
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	authkeyFilename   = "auth.pub"
	managementDirname = ".lara"
	defaultFilePerms  = 0600
	defaultDirPerms   = 0700
)

// Repository represents an on-disk repository and provides methods to
// access its sub-items.
type Repository struct {
	Path string
}

// New returns a new repository instance with the given base path
func New(path string) *Repository {
	return &Repository{Path: path}
}

// CreateManagementDir ensures that this repository's management
// directory exists.
func (r *Repository) CreateManagementDir() error {
	path := filepath.Join(r.Path, managementDirname)
	err := os.Mkdir(path, defaultDirPerms)
	if err != nil && err != os.ErrExist {
		return err
	}
	return nil
}

// Create initially creates the repository directory structure.
func (r *Repository) Create() error {
	err := os.Mkdir(r.Path, defaultDirPerms)
	if err != nil {
		return err
	}
	err = r.CreateManagementDir()
	return err
}

// getAuthPubkeyPath returns the path of the repository's auth pubkey
// storage location.
func (r *Repository) getAuthPubkeyPath() string {
	return filepath.Join(r.Path, managementDirname, authkeyFilename)
}

// GetAuthPubkey returns the repository auth key's public key.
func (r *Repository) GetAuthPubkey() ([]byte, error) {
	pubkey, err := ioutil.ReadFile(r.getAuthPubkeyPath())
	return pubkey, err
}

// SetAuthPubkey sets the repository auth key's public key.
func (r *Repository) SetAuthPubkey(key []byte) error {
	return ioutil.WriteFile(r.getAuthPubkeyPath(), key,
		defaultFilePerms)
}
<commit_msg>repository: variable naming consistency<commit_after>package repository

import (
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	authkeyFileName   = "auth.pub"
	managementDirName = ".lara"
	defaultFilePerms  = 0600
	defaultDirPerms   = 0700
)

// Repository represents an on-disk repository and provides methods to
// access its sub-items.
type Repository struct {
	Path string
}

// New returns a new repository instance with the given base path
func New(path string) *Repository {
	return &Repository{Path: path}
}

// CreateManagementDir ensures that this repository's management
// directory exists.
func (r *Repository) CreateManagementDir() error {
	path := filepath.Join(r.Path, managementDirName)
	err := os.Mkdir(path, defaultDirPerms)
	if err != nil && err != os.ErrExist {
		return err
	}
	return nil
}

// Create initially creates the repository directory structure.
func (r *Repository) Create() error {
	err := os.Mkdir(r.Path, defaultDirPerms)
	if err != nil {
		return err
	}
	err = r.CreateManagementDir()
	return err
}

// getAuthPubkeyPath returns the path of the repository's auth pubkey
// storage location.
func (r *Repository) getAuthPubkeyPath() string {
	return filepath.Join(r.Path, managementDirName, authkeyFileName)
}

// GetAuthPubkey returns the repository auth key's public key.
func (r *Repository) GetAuthPubkey() ([]byte, error) {
	pubkey, err := ioutil.ReadFile(r.getAuthPubkeyPath())
	return pubkey, err
}

// SetAuthPubkey sets the repository auth key's public key.
func (r *Repository) SetAuthPubkey(key []byte) error {
	return ioutil.WriteFile(r.getAuthPubkeyPath(), key,
		defaultFilePerms)
}
<|endoftext|>


<commit_before>package repository

import (
	"fmt"
	"strings"

	"github.com/megamsys/megamd/meta"
)

const (
	//source flags
	GITHUB      = "github"
	GITLAB      = "gitlab"
	DOCKERHUB   = "dockerhub"
	MYDOCKERHUB = "mydockerhub"

	defaultManager = GITHUB

	CIHOOK   = "CI"
	TYPE     = "type"
	TOKEN    = "token"
	USERNAME = "username"
	STATUS   = "unbound"

	// IMAGE indicates that the repo is an image
	IMAGE = "image"
	// Git indicates that the repo is a GIT
	GIT = "git"
	// oneclick indicates that an oneclick image exists
	ONECLICK = "oneclick"
)

var managers map[string]RepositoryManager

/* Repository represents a repository managed by the manager. */
type Repo struct {
	Type     string
	Source   string
	OneClick bool
	URL      string
	Hook     *Hook
}

type Hook struct {
	Enabled  bool
	Token    string
	UserName string
	CartonId string
	BoxId    string
}

func (r Repo) GetType() string {
	return r.Type
}

func (r Repo) GetSource() string {
	return r.Source
}

func (r Repo) Gitr() string {
	return r.URL
}

func (r Repo) IsEnabled() bool {
	return r.Hook != nil && r.Hook.Enabled
}

func (r Repo) GetToken() string {
	return r.Hook.Token
}

func (r Repo) GetUserName() string {
	return r.Hook.UserName
}

//Check on CartonId, BoxId if it exists (r.Hook.BoxId)
func (r Repo) Trigger() string {
	return meta.MC.Api + "/assembly/upgrade/" + r.Hook.CartonId
}

func (r Repo) GetShortName() (string, error) {
	i := strings.LastIndex(r.Gitr(), "/")
	if i < 0 {
		return "", fmt.Errorf("unable to parse output of git")
	}
	return strings.TrimRight(r.Gitr()[i+1:], ".git"), nil
}

//This shall be under type Tosca {} and a global method
func ForImageName(fullTosca string, version string) string {
	img := fullTosca[strings.LastIndex(fullTosca, ".")+1:]
	if len(strings.TrimSpace(version)) > 1 {
		return img + "_" + version
	}
	return img
}

type Repository interface {
	IsEnabled() bool
	GetSource() string
	GetType() string
	GetToken() string
	GetUserName() string
	Gitr() string
	Trigger() string
	GetShortName() (string, error)
}

type Repositorys interface {
}

// RepositoryManager represents a manager of application repositories.
type RepositoryManager interface {
	CreateHook(r Repository) (string, error)
	RemoveHook(r Repository) error
}

func Get(name string) (Repositorys, error) {
	p, ok := managers[name]
	if !ok {
		return nil, fmt.Errorf("unknown repository: %q", name)
	}
	return p, nil
}

// Manager returns the current configured manager, as defined in the
// configuration file.
func Manager(managerName string) RepositoryManager {
	if _, ok := managers[managerName]; !ok {
		managerName = "nop"
	}
	return managers[managerName]
}

// Register registers a new repository manager, that can be later configured
// and used.
func Register(name string, manager RepositoryManager) {
	if managers == nil {
		managers = make(map[string]RepositoryManager)
	}
	managers[name] = manager
}
<commit_msg>removed codes added for hook testing<commit_after>package repository

import (
	"fmt"
	"strings"

	"github.com/megamsys/megamd/meta"
)

const (
	//source flags
	GITHUB      = "github"
	GITLAB      = "gitlab"
	DOCKERHUB   = "dockerhub"
	MYDOCKERHUB = "mydockerhub"

	defaultManager = GITHUB

	CIHOOK   = "CI"
	TYPE     = "type"
	TOKEN    = "token"
	USERNAME = "username"
	STATUS   = "unbound"

	// IMAGE indicates that the repo is an image
	IMAGE = "image"
	// Git indicates that the repo is a GIT
	GIT = "git"
	// oneclick indicates that an oneclick image exists
	ONECLICK = "oneclick"
)

var managers map[string]RepositoryManager

/* Repository represents a repository managed by the manager. */
type Repo struct {
	Type     string
	Source   string
	OneClick bool
	URL      string
	Hook     *Hook
}

type Hook struct {
	Enabled  bool
	Token    string
	UserName string
	CartonId string
	BoxId    string
}

func (r Repo) GetType() string {
	return r.Type
}

func (r Repo) GetSource() string {
	return r.Source
}

func (r Repo) Gitr() string {
	return r.URL
}

func (r Repo) IsEnabled() bool {
	return r.Hook != nil && r.Hook.Enabled
}

func (r Repo) GetToken() string {
	return r.Hook.Token
}

func (r Repo) GetUserName() string {
	return r.Hook.UserName
}

//Check on CartonId, BoxId if it exists (r.Hook.BoxId)
func (r Repo) Trigger() string {
	return meta.MC.Api + "/assembly/upgrade/" + r.Hook.CartonId
}

func (r Repo) GetShortName() (string, error) {
	i := strings.LastIndex(r.Gitr(), "/")
	if i < 0 {
		return "", fmt.Errorf("unable to parse output of git")
	}
	return strings.TrimRight(r.Gitr()[i+1:], ".git"), nil
}

//This shall be under type Tosca {} and a global method
func ForImageName(fullTosca string, version string) string {
	img := fullTosca[strings.LastIndex(fullTosca, ".")+1:]
	if len(strings.TrimSpace(version)) > 1 {
		return img + "_" + version
	}
	return img
}

type Repository interface {
	IsEnabled() bool
	GetSource() string
	GetType() string
	GetToken() string
	GetUserName() string
	Gitr() string
	Trigger() string
	GetShortName() (string, error)
}

// RepositoryManager represents a manager of application repositories.
type RepositoryManager interface {
	CreateHook(r Repository) (string, error)
	RemoveHook(r Repository) error
}

// Manager returns the current configured manager, as defined in the
// configuration file.
func Manager(managerName string) RepositoryManager {
	if _, ok := managers[managerName]; !ok {
		managerName = "nop"
	}
	return managers[managerName]
}

// Register registers a new repository manager, that can be later configured
// and used.
func Register(name string, manager RepositoryManager) {
	if managers == nil {
		managers = make(map[string]RepositoryManager)
	}
	managers[name] = manager
}
<|endoftext|>