<commit_before>package aws

import (
	"fmt"
	"log"

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudwatch"
	"github.com/hashicorp/terraform/helper/validation"
)

func resourceAwsCloudWatchMetricAlarm() *schema.Resource {
	return &schema.Resource{
		Create:        resourceAwsCloudWatchMetricAlarmCreate,
		Read:          resourceAwsCloudWatchMetricAlarmRead,
		Update:        resourceAwsCloudWatchMetricAlarmUpdate,
		Delete:        resourceAwsCloudWatchMetricAlarmDelete,
		SchemaVersion: 1,
		MigrateState:  resourceAwsCloudWatchMetricAlarmMigrateState,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"alarm_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"comparison_operator": {
				Type:     schema.TypeString,
				Required: true,
			},
			"evaluation_periods": {
				Type:         schema.TypeInt,
				Required:     true,
				ValidateFunc: validation.IntAtLeast(1),
			},
			"metric_name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"namespace": {
				Type:     schema.TypeString,
				Required: true,
			},
			"period": {
				Type:     schema.TypeInt,
				Required: true,
			},
			"statistic": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"extended_statistic"},
			},
			"threshold": {
				Type:     schema.TypeFloat,
				Required: true,
			},
			"actions_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"alarm_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"alarm_description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"datapoints_to_alarm": {
				Type:         schema.TypeInt,
				Optional:     true,
				ValidateFunc: validation.IntAtLeast(1),
			},
			"dimensions": {
				Type:     schema.TypeMap,
				Optional: true,
			},
			"insufficient_data_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"ok_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"unit": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"extended_statistic": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"statistic"},
			},
			"treat_missing_data": {
				Type:         schema.TypeString,
				Optional:     true,
				Default:      "missing",
				ValidateFunc: validation.StringInSlice([]string{"breaching", "notBreaching", "ignore", "missing"}, true),
			},
			"evaluate_low_sample_count_percentiles": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validation.StringInSlice([]string{"evaluate", "ignore"}, true),
			},
		},
	}
}

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

	_, statisticOk := d.GetOk("statistic")
	_, extendedStatisticOk := d.GetOk("extended_statistic")

	if !statisticOk && !extendedStatisticOk {
		return fmt.Errorf("One of `statistic` or `extended_statistic` must be set for a cloudwatch metric alarm")
	}

	params := getAwsCloudWatchPutMetricAlarmInput(d)

	log.Printf("[DEBUG] Creating CloudWatch Metric Alarm: %#v", params)
	_, err := conn.PutMetricAlarm(&params)
	if err != nil {
		return fmt.Errorf("Creating metric alarm failed: %s", err)
	}
	d.SetId(d.Get("alarm_name").(string))
	log.Println("[INFO] CloudWatch Metric Alarm created")

	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
}

func resourceAwsCloudWatchMetricAlarmRead(d *schema.ResourceData, meta interface{}) error {
	a, err := getAwsCloudWatchMetricAlarm(d, meta)
	if err != nil {
		return err
	}
	if a == nil {
		d.SetId("")
		return nil
	}

	log.Printf("[DEBUG] Reading CloudWatch Metric Alarm: %s", d.Get("alarm_name"))

	d.Set("actions_enabled", a.ActionsEnabled)

	if err := d.Set("alarm_actions", _strArrPtrToList(a.AlarmActions)); err != nil {
		log.Printf("[WARN] Error setting Alarm Actions: %s", err)
	}
	d.Set("alarm_description", a.AlarmDescription)
	d.Set("alarm_name", a.AlarmName)
	d.Set("arn", a.AlarmArn)
	d.Set("comparison_operator", a.ComparisonOperator)
	d.Set("datapoints_to_alarm", a.DatapointsToAlarm)
	if err := d.Set("dimensions", flattenDimensions(a.Dimensions)); err != nil {
		return err
	}
	d.Set("evaluation_periods", a.EvaluationPeriods)

	if err := d.Set("insufficient_data_actions", _strArrPtrToList(a.InsufficientDataActions)); err != nil {
		log.Printf("[WARN] Error setting Insufficient Data Actions: %s", err)
	}
	d.Set("metric_name", a.MetricName)
	d.Set("namespace", a.Namespace)

	if err := d.Set("ok_actions", _strArrPtrToList(a.OKActions)); err != nil {
		log.Printf("[WARN] Error setting OK Actions: %s", err)
	}
	d.Set("period", a.Period)
	d.Set("statistic", a.Statistic)
	d.Set("threshold", a.Threshold)
	d.Set("unit", a.Unit)
	d.Set("extended_statistic", a.ExtendedStatistic)
	d.Set("treat_missing_data", a.TreatMissingData)
	d.Set("evaluate_low_sample_count_percentiles", a.EvaluateLowSampleCountPercentile)

	return nil
}

func resourceAwsCloudWatchMetricAlarmUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudwatchconn
	params := getAwsCloudWatchPutMetricAlarmInput(d)

	log.Printf("[DEBUG] Updating CloudWatch Metric Alarm: %#v", params)
	_, err := conn.PutMetricAlarm(&params)
	if err != nil {
		return fmt.Errorf("Updating metric alarm failed: %s", err)
	}
	log.Println("[INFO] CloudWatch Metric Alarm updated")

	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
}

func resourceAwsCloudWatchMetricAlarmDelete(d *schema.ResourceData, meta interface{}) error {
	p, err := getAwsCloudWatchMetricAlarm(d, meta)
	if err != nil {
		return err
	}
	if p == nil {
		log.Printf("[DEBUG] CloudWatch Metric Alarm %s is already gone", d.Id())
		return nil
	}

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

	conn := meta.(*AWSClient).cloudwatchconn
	params := cloudwatch.DeleteAlarmsInput{
		AlarmNames: []*string{aws.String(d.Id())},
	}

	if _, err := conn.DeleteAlarms(&params); err != nil {
		return fmt.Errorf("Error deleting CloudWatch Metric Alarm: %s", err)
	}
	log.Println("[INFO] CloudWatch Metric Alarm deleted")

	return nil
}

func getAwsCloudWatchPutMetricAlarmInput(d *schema.ResourceData) cloudwatch.PutMetricAlarmInput {
	params := cloudwatch.PutMetricAlarmInput{
		AlarmName:          aws.String(d.Get("alarm_name").(string)),
		ComparisonOperator: aws.String(d.Get("comparison_operator").(string)),
		EvaluationPeriods:  aws.Int64(int64(d.Get("evaluation_periods").(int))),
		MetricName:         aws.String(d.Get("metric_name").(string)),
		Namespace:          aws.String(d.Get("namespace").(string)),
		Period:             aws.Int64(int64(d.Get("period").(int))),
		Threshold:          aws.Float64(d.Get("threshold").(float64)),
		TreatMissingData:   aws.String(d.Get("treat_missing_data").(string)),
	}

	if v := d.Get("actions_enabled"); v != nil {
		params.ActionsEnabled = aws.Bool(v.(bool))
	}

	if v, ok := d.GetOk("alarm_description"); ok {
		params.AlarmDescription = aws.String(v.(string))
	}

	if v, ok := d.GetOk("datapoints_to_alarm"); ok {
		params.DatapointsToAlarm = aws.Int64(int64(v.(int)))
	}

	if v, ok := d.GetOk("unit"); ok {
		params.Unit = aws.String(v.(string))
	}

	if v, ok := d.GetOk("statistic"); ok {
		params.Statistic = aws.String(v.(string))
	}

	if v, ok := d.GetOk("extended_statistic"); ok {
		params.ExtendedStatistic = aws.String(v.(string))
	}

	if v, ok := d.GetOk("evaluate_low_sample_count_percentiles"); ok {
		params.EvaluateLowSampleCountPercentile = aws.String(v.(string))
	}

	var alarmActions []*string
	if v := d.Get("alarm_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			alarmActions = append(alarmActions, aws.String(str))
		}
		params.AlarmActions = alarmActions
	}

	var insufficientDataActions []*string
	if v := d.Get("insufficient_data_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			insufficientDataActions = append(insufficientDataActions, aws.String(str))
		}
		params.InsufficientDataActions = insufficientDataActions
	}

	var okActions []*string
	if v := d.Get("ok_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			okActions = append(okActions, aws.String(str))
		}
		params.OKActions = okActions
	}

	a := d.Get("dimensions").(map[string]interface{})
	dimensions := make([]*cloudwatch.Dimension, 0, len(a))
	for k, v := range a {
		dimensions = append(dimensions, &cloudwatch.Dimension{
			Name:  aws.String(k),
			Value: aws.String(v.(string)),
		})
	}
	params.Dimensions = dimensions

	return params
}

func getAwsCloudWatchMetricAlarm(d *schema.ResourceData, meta interface{}) (*cloudwatch.MetricAlarm, error) {
	conn := meta.(*AWSClient).cloudwatchconn

	params := cloudwatch.DescribeAlarmsInput{
		AlarmNames: []*string{aws.String(d.Id())},
	}

	resp, err := conn.DescribeAlarms(&params)
	if err != nil {
		return nil, err
	}

	// Find it and return it
	for idx, ma := range resp.MetricAlarms {
		if aws.StringValue(ma.AlarmName) == d.Id() {
			return resp.MetricAlarms[idx], nil
		}
	}

	return nil, nil
}

func _strArrPtrToList(strArrPtr []*string) []string {
	var result []string
	for _, elem := range strArrPtr {
		result = append(result, aws.StringValue(elem))
	}
	return result
}

func flattenDimensions(dims []*cloudwatch.Dimension) map[string]interface{} {
	flatDims := make(map[string]interface{})
	for _, d := range dims {
		flatDims[*d.Name] = *d.Value
	}
	return flatDims
}
<commit_msg>resource/aws_cloudwatch_metric_alarm: Validate alarm actions<commit_after>package aws

import (
	"fmt"
	"log"

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudwatch"
	"github.com/hashicorp/terraform/helper/validation"
)

func resourceAwsCloudWatchMetricAlarm() *schema.Resource {
	return &schema.Resource{
		Create:        resourceAwsCloudWatchMetricAlarmCreate,
		Read:          resourceAwsCloudWatchMetricAlarmRead,
		Update:        resourceAwsCloudWatchMetricAlarmUpdate,
		Delete:        resourceAwsCloudWatchMetricAlarmDelete,
		SchemaVersion: 1,
		MigrateState:  resourceAwsCloudWatchMetricAlarmMigrateState,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"alarm_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"comparison_operator": {
				Type:     schema.TypeString,
				Required: true,
			},
			"evaluation_periods": {
				Type:         schema.TypeInt,
				Required:     true,
				ValidateFunc: validation.IntAtLeast(1),
			},
			"metric_name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"namespace": {
				Type:     schema.TypeString,
				Required: true,
			},
			"period": {
				Type:     schema.TypeInt,
				Required: true,
			},
			"statistic": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"extended_statistic"},
			},
			"threshold": {
				Type:     schema.TypeFloat,
				Required: true,
			},
			"actions_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"alarm_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Schema{
					Type:         schema.TypeString,
					ValidateFunc: validateArn,
				},
				Set: schema.HashString,
			},
			"alarm_description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"datapoints_to_alarm": {
				Type:         schema.TypeInt,
				Optional:     true,
				ValidateFunc: validation.IntAtLeast(1),
			},
			"dimensions": {
				Type:     schema.TypeMap,
				Optional: true,
			},
			"insufficient_data_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"ok_actions": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"unit": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"extended_statistic": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"statistic"},
			},
			"treat_missing_data": {
				Type:         schema.TypeString,
				Optional:     true,
				Default:      "missing",
				ValidateFunc: validation.StringInSlice([]string{"breaching", "notBreaching", "ignore", "missing"}, true),
			},
			"evaluate_low_sample_count_percentiles": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validation.StringInSlice([]string{"evaluate", "ignore"}, true),
			},
		},
	}
}

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

	_, statisticOk := d.GetOk("statistic")
	_, extendedStatisticOk := d.GetOk("extended_statistic")

	if !statisticOk && !extendedStatisticOk {
		return fmt.Errorf("One of `statistic` or `extended_statistic` must be set for a cloudwatch metric alarm")
	}

	params := getAwsCloudWatchPutMetricAlarmInput(d)

	log.Printf("[DEBUG] Creating CloudWatch Metric Alarm: %#v", params)
	_, err := conn.PutMetricAlarm(&params)
	if err != nil {
		return fmt.Errorf("Creating metric alarm failed: %s", err)
	}
	d.SetId(d.Get("alarm_name").(string))
	log.Println("[INFO] CloudWatch Metric Alarm created")

	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
}

func resourceAwsCloudWatchMetricAlarmRead(d *schema.ResourceData, meta interface{}) error {
	a, err := getAwsCloudWatchMetricAlarm(d, meta)
	if err != nil {
		return err
	}
	if a == nil {
		d.SetId("")
		return nil
	}

	log.Printf("[DEBUG] Reading CloudWatch Metric Alarm: %s", d.Get("alarm_name"))

	d.Set("actions_enabled", a.ActionsEnabled)

	if err := d.Set("alarm_actions", _strArrPtrToList(a.AlarmActions)); err != nil {
		log.Printf("[WARN] Error setting Alarm Actions: %s", err)
	}
	d.Set("alarm_description", a.AlarmDescription)
	d.Set("alarm_name", a.AlarmName)
	d.Set("arn", a.AlarmArn)
	d.Set("comparison_operator", a.ComparisonOperator)
	d.Set("datapoints_to_alarm", a.DatapointsToAlarm)
	if err := d.Set("dimensions", flattenDimensions(a.Dimensions)); err != nil {
		return err
	}
	d.Set("evaluation_periods", a.EvaluationPeriods)

	if err := d.Set("insufficient_data_actions", _strArrPtrToList(a.InsufficientDataActions)); err != nil {
		log.Printf("[WARN] Error setting Insufficient Data Actions: %s", err)
	}
	d.Set("metric_name", a.MetricName)
	d.Set("namespace", a.Namespace)

	if err := d.Set("ok_actions", _strArrPtrToList(a.OKActions)); err != nil {
		log.Printf("[WARN] Error setting OK Actions: %s", err)
	}
	d.Set("period", a.Period)
	d.Set("statistic", a.Statistic)
	d.Set("threshold", a.Threshold)
	d.Set("unit", a.Unit)
	d.Set("extended_statistic", a.ExtendedStatistic)
	d.Set("treat_missing_data", a.TreatMissingData)
	d.Set("evaluate_low_sample_count_percentiles", a.EvaluateLowSampleCountPercentile)

	return nil
}

func resourceAwsCloudWatchMetricAlarmUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudwatchconn
	params := getAwsCloudWatchPutMetricAlarmInput(d)

	log.Printf("[DEBUG] Updating CloudWatch Metric Alarm: %#v", params)
	_, err := conn.PutMetricAlarm(&params)
	if err != nil {
		return fmt.Errorf("Updating metric alarm failed: %s", err)
	}
	log.Println("[INFO] CloudWatch Metric Alarm updated")

	return resourceAwsCloudWatchMetricAlarmRead(d, meta)
}

func resourceAwsCloudWatchMetricAlarmDelete(d *schema.ResourceData, meta interface{}) error {
	p, err := getAwsCloudWatchMetricAlarm(d, meta)
	if err != nil {
		return err
	}
	if p == nil {
		log.Printf("[DEBUG] CloudWatch Metric Alarm %s is already gone", d.Id())
		return nil
	}

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

	conn := meta.(*AWSClient).cloudwatchconn
	params := cloudwatch.DeleteAlarmsInput{
		AlarmNames: []*string{aws.String(d.Id())},
	}

	if _, err := conn.DeleteAlarms(&params); err != nil {
		return fmt.Errorf("Error deleting CloudWatch Metric Alarm: %s", err)
	}
	log.Println("[INFO] CloudWatch Metric Alarm deleted")

	return nil
}

func getAwsCloudWatchPutMetricAlarmInput(d *schema.ResourceData) cloudwatch.PutMetricAlarmInput {
	params := cloudwatch.PutMetricAlarmInput{
		AlarmName:          aws.String(d.Get("alarm_name").(string)),
		ComparisonOperator: aws.String(d.Get("comparison_operator").(string)),
		EvaluationPeriods:  aws.Int64(int64(d.Get("evaluation_periods").(int))),
		MetricName:         aws.String(d.Get("metric_name").(string)),
		Namespace:          aws.String(d.Get("namespace").(string)),
		Period:             aws.Int64(int64(d.Get("period").(int))),
		Threshold:          aws.Float64(d.Get("threshold").(float64)),
		TreatMissingData:   aws.String(d.Get("treat_missing_data").(string)),
	}

	if v := d.Get("actions_enabled"); v != nil {
		params.ActionsEnabled = aws.Bool(v.(bool))
	}

	if v, ok := d.GetOk("alarm_description"); ok {
		params.AlarmDescription = aws.String(v.(string))
	}

	if v, ok := d.GetOk("datapoints_to_alarm"); ok {
		params.DatapointsToAlarm = aws.Int64(int64(v.(int)))
	}

	if v, ok := d.GetOk("unit"); ok {
		params.Unit = aws.String(v.(string))
	}

	if v, ok := d.GetOk("statistic"); ok {
		params.Statistic = aws.String(v.(string))
	}

	if v, ok := d.GetOk("extended_statistic"); ok {
		params.ExtendedStatistic = aws.String(v.(string))
	}

	if v, ok := d.GetOk("evaluate_low_sample_count_percentiles"); ok {
		params.EvaluateLowSampleCountPercentile = aws.String(v.(string))
	}

	var alarmActions []*string
	if v := d.Get("alarm_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			alarmActions = append(alarmActions, aws.String(str))
		}
		params.AlarmActions = alarmActions
	}

	var insufficientDataActions []*string
	if v := d.Get("insufficient_data_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			insufficientDataActions = append(insufficientDataActions, aws.String(str))
		}
		params.InsufficientDataActions = insufficientDataActions
	}

	var okActions []*string
	if v := d.Get("ok_actions"); v != nil {
		for _, v := range v.(*schema.Set).List() {
			str := v.(string)
			okActions = append(okActions, aws.String(str))
		}
		params.OKActions = okActions
	}

	a := d.Get("dimensions").(map[string]interface{})
	dimensions := make([]*cloudwatch.Dimension, 0, len(a))
	for k, v := range a {
		dimensions = append(dimensions, &cloudwatch.Dimension{
			Name:  aws.String(k),
			Value: aws.String(v.(string)),
		})
	}
	params.Dimensions = dimensions

	return params
}

func getAwsCloudWatchMetricAlarm(d *schema.ResourceData, meta interface{}) (*cloudwatch.MetricAlarm, error) {
	conn := meta.(*AWSClient).cloudwatchconn

	params := cloudwatch.DescribeAlarmsInput{
		AlarmNames: []*string{aws.String(d.Id())},
	}

	resp, err := conn.DescribeAlarms(&params)
	if err != nil {
		return nil, err
	}

	// Find it and return it
	for idx, ma := range resp.MetricAlarms {
		if aws.StringValue(ma.AlarmName) == d.Id() {
			return resp.MetricAlarms[idx], nil
		}
	}

	return nil, nil
}

func _strArrPtrToList(strArrPtr []*string) []string {
	var result []string
	for _, elem := range strArrPtr {
		result = append(result, aws.StringValue(elem))
	}
	return result
}

func flattenDimensions(dims []*cloudwatch.Dimension) map[string]interface{} {
	flatDims := make(map[string]interface{})
	for _, d := range dims {
		flatDims[*d.Name] = *d.Value
	}
	return flatDims
}
<|endoftext|>


<commit_before>package aws

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/wafv2"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsWafv2RegexPatternSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsWafv2RegexPatternSetCreate,
		Read:   resourceAwsWafv2RegexPatternSetRead,
		Update: resourceAwsWafv2RegexPatternSetUpdate,
		Delete: resourceAwsWafv2RegexPatternSetDelete,
		Importer: &schema.ResourceImporter{
			State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
				idParts := strings.Split(d.Id(), "/")
				if len(idParts) != 3 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" {
					return nil, fmt.Errorf("Unexpected format of ID (%q), expected ID/NAME/SCOPE", d.Id())
				}
				id := idParts[0]
				name := idParts[1]
				scope := idParts[2]
				d.SetId(id)
				d.Set("name", name)
				d.Set("scope", scope)
				return []*schema.ResourceData{d}, nil
			},
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"description": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validation.StringLenBetween(1, 256),
			},
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringLenBetween(1, 128),
			},
			"regular_expression_list": {
				Type:     schema.TypeSet,
				Required: true,
				MinItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"regex_string": {
							Type:         schema.TypeString,
							Required:     true,
							ValidateFunc: validation.StringLenBetween(1, 512),
						},
					},
				},
			},
			"scope": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: validation.StringInSlice([]string{
					wafv2.ScopeCloudfront,
					wafv2.ScopeRegional,
				}, false),
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsWafv2RegexPatternSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafv2conn
	var resp *wafv2.CreateRegexPatternSetOutput

	params := &wafv2.CreateRegexPatternSetInput{
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}

	if d.HasChange("description") {
		params.Description = aws.String(d.Get("description").(string))
	}

	if v, ok := d.GetOk("regular_expression_list"); ok && v.(*schema.Set).Len() > 0 {
		params.RegularExpressionList = expandWafv2RegexPatternSet(d.Get("regular_expression_list").(*schema.Set).List())
	}

	if v := d.Get("tags").(map[string]interface{}); len(v) > 0 {
		params.Tags = keyvaluetags.New(v).IgnoreAws().Wafv2Tags()
	}

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		var err error
		resp, err = conn.CreateRegexPatternSet(params)
		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFTagOperationException, "An error occurred during the tagging operation") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFTagOperationInternalErrorException, "AWS WAF couldn’t perform your tagging operation because of an internal error") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFOptimisticLockException, "AWS WAF couldn’t save your changes because you tried to update or delete a resource that has changed since you last retrieved it") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})
	if isResourceTimeoutError(err) {
		_, err = conn.CreateRegexPatternSet(params)
	}
	if err != nil {
		return err
	}
	d.SetId(*resp.Summary.Id)

	return resourceAwsWafv2RegexPatternSetRead(d, meta)
}

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

	params := &wafv2.GetRegexPatternSetInput{
		Id:    aws.String(d.Id()),
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}

	resp, err := conn.GetRegexPatternSet(params)
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == wafv2.ErrCodeWAFNonexistentItemException {
			log.Printf("[WARN] WAFV2 RegexPatternSet (%s) not found, removing from state", d.Id())
			d.SetId("")
			return nil
		}

		return err
	}

	d.Set("name", resp.RegexPatternSet.Name)
	d.Set("description", resp.RegexPatternSet.Description)
	d.Set("arn", resp.RegexPatternSet.ARN)

	if err := d.Set("regular_expression_list", flattenWafv2RegexPatternSet(resp.RegexPatternSet.RegularExpressionList)); err != nil {
		return fmt.Errorf("Error setting regular_expression_list: %s", err)
	}

	tags, err := keyvaluetags.Wafv2ListTags(conn, *resp.RegexPatternSet.ARN)
	if err != nil {
		return fmt.Errorf("error listing tags for WAFV2 RegexPatternSet (%s): %s", *resp.RegexPatternSet.ARN, err)
	}

	if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil {
		return fmt.Errorf("error setting tags: %s", err)
	}

	return nil
}

func flattenWafv2RegexPatternSet(r []*wafv2.Regex) interface{} {
	regexPatterns := make([]interface{}, len(r))

	for i, regexPattern := range r {
		d := map[string]interface{}{
			"regex_string": *regexPattern.RegexString,
		}
		regexPatterns[i] = d
	}

	return regexPatterns
}

func resourceAwsWafv2RegexPatternSetUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafv2conn
	var resp *wafv2.GetRegexPatternSetOutput
	params := &wafv2.GetRegexPatternSetInput{
		Id:    aws.String(d.Id()),
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}
	log.Printf("[INFO] Updating WAFV2 RegexPatternSet %s", d.Id())

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		var err error
		resp, err = conn.GetRegexPatternSet(params)
		if err != nil {
			return resource.NonRetryableError(fmt.Errorf("Error getting lock token: %s", err))
		}

		u := &wafv2.UpdateRegexPatternSetInput{
			Id:          aws.String(d.Id()),
			Name:        aws.String(d.Get("name").(string)),
			Scope:       aws.String(d.Get("scope").(string)),
			Description: aws.String(d.Get("description").(string)),
			LockToken:   resp.LockToken,
		}

		if v, ok := d.GetOk("regular_expression_list"); ok && v.(*schema.Set).Len() > 0 {
			u.RegularExpressionList = expandWafv2RegexPatternSet(d.Get("regular_expression_list").(*schema.Set).List())
		}

		if d.HasChange("description") {
			u.Description = aws.String(d.Get("description").(string))
		}

		_, err = conn.UpdateRegexPatternSet(u)

		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFOptimisticLockException, "AWS WAF couldn’t save your changes because you tried to update or delete a resource that has changed since you last retrieved it") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})

	if isResourceTimeoutError(err) {
		_, err = conn.DeleteRegexPatternSet(&wafv2.DeleteRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: resp.LockToken,
		})
	}

	if err != nil {
		return fmt.Errorf("Error updating WAFV2 RegexPatternSet: %s", err)
	}

	if d.HasChange("tags") {
		o, n := d.GetChange("tags")
		if err := keyvaluetags.Wafv2UpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
			return fmt.Errorf("error updating tags: %s", err)
		}
	}

	return resourceAwsWafv2RegexPatternSetRead(d, meta)
}

func resourceAwsWafv2RegexPatternSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafv2conn
	var resp *wafv2.GetRegexPatternSetOutput
	params := &wafv2.GetRegexPatternSetInput{
		Id:    aws.String(d.Id()),
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}
	log.Printf("[INFO] Deleting WAFV2 RegexPatternSet %s", d.Id())

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		var err error
		resp, err = conn.GetRegexPatternSet(params)
		if err != nil {
			return resource.NonRetryableError(fmt.Errorf("Error getting lock token: %s", err))
		}

		_, err = conn.DeleteRegexPatternSet(&wafv2.DeleteRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: resp.LockToken,
		})

		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFOptimisticLockException, "AWS WAF couldn’t save your changes because you tried to update or delete a resource that has changed since you last retrieved it") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})

	if isResourceTimeoutError(err) {
		_, err = conn.DeleteRegexPatternSet(&wafv2.DeleteRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: resp.LockToken,
		})
	}

	if err != nil {
		return fmt.Errorf("Error deleting WAFV2 RegexPatternSet: %s", err)
	}

	return nil
}

func expandWafv2RegexPatternSet(l []interface{}) []*wafv2.Regex {
	if len(l) == 0 || l[0] == nil {
		return nil
	}

	regexPatterns := make([]*wafv2.Regex, 0)
	for _, regexPattern := range l {
		if regexPattern == nil {
			continue
		}

		regexPatterns = append(regexPatterns, expandWafv2Regex(regexPattern.(map[string]interface{})))
	}

	return regexPatterns
}

func expandWafv2Regex(m map[string]interface{}) *wafv2.Regex {
	if m == nil {
		return nil
	}

	return &wafv2.Regex{
		RegexString: aws.String(m["regex_string"].(string)),
	}
}
<commit_msg>Make user aware of optimistic lock exception<commit_after>package aws

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/wafv2"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsWafv2RegexPatternSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsWafv2RegexPatternSetCreate,
		Read:   resourceAwsWafv2RegexPatternSetRead,
		Update: resourceAwsWafv2RegexPatternSetUpdate,
		Delete: resourceAwsWafv2RegexPatternSetDelete,
		Importer: &schema.ResourceImporter{
			State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
				idParts := strings.Split(d.Id(), "/")
				if len(idParts) != 3 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" {
					return nil, fmt.Errorf("Unexpected format of ID (%q), expected ID/NAME/SCOPE", d.Id())
				}
				id := idParts[0]
				name := idParts[1]
				scope := idParts[2]
				d.SetId(id)
				d.Set("name", name)
				d.Set("scope", scope)
				return []*schema.ResourceData{d}, nil
			},
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"description": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validation.StringLenBetween(1, 256),
			},
			"lock_token": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringLenBetween(1, 128),
			},
			"regular_expression_list": {
				Type:     schema.TypeSet,
				Required: true,
				MinItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"regex_string": {
							Type:         schema.TypeString,
							Required:     true,
							ValidateFunc: validation.StringLenBetween(1, 512),
						},
					},
				},
			},
			"scope": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: validation.StringInSlice([]string{
					wafv2.ScopeCloudfront,
					wafv2.ScopeRegional,
				}, false),
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsWafv2RegexPatternSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafv2conn
	var resp *wafv2.CreateRegexPatternSetOutput

	params := &wafv2.CreateRegexPatternSetInput{
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}

	if d.HasChange("description") {
		params.Description = aws.String(d.Get("description").(string))
	}

	if v, ok := d.GetOk("regular_expression_list"); ok && v.(*schema.Set).Len() > 0 {
		params.RegularExpressionList = expandWafv2RegexPatternSet(d.Get("regular_expression_list").(*schema.Set).List())
	}

	if v := d.Get("tags").(map[string]interface{}); len(v) > 0 {
		params.Tags = keyvaluetags.New(v).IgnoreAws().Wafv2Tags()
	}

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		var err error
		resp, err = conn.CreateRegexPatternSet(params)
		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFTagOperationException, "An error occurred during the tagging operation") {
				return resource.RetryableError(err)
			}
			if isAWSErr(err, wafv2.ErrCodeWAFTagOperationInternalErrorException, "AWS WAF couldn’t perform your tagging operation because of an internal error") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})
	if isResourceTimeoutError(err) {
		_, err = conn.CreateRegexPatternSet(params)
	}
	if err != nil {
		return err
	}
	d.SetId(*resp.Summary.Id)

	return resourceAwsWafv2RegexPatternSetRead(d, meta)
}

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

	params := &wafv2.GetRegexPatternSetInput{
		Id:    aws.String(d.Id()),
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}

	resp, err := conn.GetRegexPatternSet(params)
	if err != nil {
		if isAWSErr(err, wafv2.ErrCodeWAFNonexistentItemException, "AWS WAF couldn’t perform the operation because your resource doesn’t exist") {
			log.Printf("[WARN] WAFV2 RegexPatternSet (%s) not found, removing from state", d.Id())
			d.SetId("")
			return nil
		}

		return err
	}

	d.Set("name", resp.RegexPatternSet.Name)
	d.Set("description", resp.RegexPatternSet.Description)
	d.Set("arn", resp.RegexPatternSet.ARN)
	d.Set("lock_token", resp.LockToken)

	if err := d.Set("regular_expression_list", flattenWafv2RegexPatternSet(resp.RegexPatternSet.RegularExpressionList)); err != nil {
		return fmt.Errorf("Error setting regular_expression_list: %s", err)
	}

	tags, err := keyvaluetags.Wafv2ListTags(conn, *resp.RegexPatternSet.ARN)
	if err != nil {
		return fmt.Errorf("error listing tags for WAFV2 RegexPatternSet (%s): %s", *resp.RegexPatternSet.ARN, err)
	}

	if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil {
		return fmt.Errorf("error setting tags: %s", err)
	}

	return nil
}

func flattenWafv2RegexPatternSet(r []*wafv2.Regex) interface{} {
	regexPatterns := make([]interface{}, len(r))

	for i, regexPattern := range r {
		d := map[string]interface{}{
			"regex_string": *regexPattern.RegexString,
		}
		regexPatterns[i] = d
	}

	return regexPatterns
}

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

	log.Printf("[INFO] Updating WAFV2 RegexPatternSet %s", d.Id())

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		u := &wafv2.UpdateRegexPatternSetInput{
			Id:          aws.String(d.Id()),
			Name:        aws.String(d.Get("name").(string)),
			Scope:       aws.String(d.Get("scope").(string)),
			Description: aws.String(d.Get("description").(string)),
			LockToken:   aws.String(d.Get("lock_token").(string)),
		}

		if v, ok := d.GetOk("regular_expression_list"); ok && v.(*schema.Set).Len() > 0 {
			u.RegularExpressionList = expandWafv2RegexPatternSet(d.Get("regular_expression_list").(*schema.Set).List())
		}

		if d.HasChange("description") {
			u.Description = aws.String(d.Get("description").(string))
		}

		_, err := conn.UpdateRegexPatternSet(u)

		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})

	if isResourceTimeoutError(err) {
		_, err = conn.UpdateRegexPatternSet(&wafv2.UpdateRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: aws.String(d.Get("lock_token").(string)),
		})
	}

	if err != nil {
		return fmt.Errorf("Error updating WAFV2 RegexPatternSet: %s", err)
	}

	if d.HasChange("tags") {
		o, n := d.GetChange("tags")
		if err := keyvaluetags.Wafv2UpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
			return fmt.Errorf("error updating tags: %s", err)
		}
	}

	return resourceAwsWafv2RegexPatternSetRead(d, meta)
}

func resourceAwsWafv2RegexPatternSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafv2conn
	var resp *wafv2.GetRegexPatternSetOutput
	params := &wafv2.GetRegexPatternSetInput{
		Id:    aws.String(d.Id()),
		Name:  aws.String(d.Get("name").(string)),
		Scope: aws.String(d.Get("scope").(string)),
	}
	log.Printf("[INFO] Deleting WAFV2 RegexPatternSet %s", d.Id())

	err := resource.Retry(15*time.Minute, func() *resource.RetryError {
		var err error
		resp, err = conn.GetRegexPatternSet(params)
		if err != nil {
			return resource.NonRetryableError(fmt.Errorf("Error getting lock token: %s", err))
		}

		_, err = conn.DeleteRegexPatternSet(&wafv2.DeleteRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: aws.String(d.Get("lock_token").(string)),
		})

		if err != nil {
			if isAWSErr(err, wafv2.ErrCodeWAFInternalErrorException, "AWS WAF couldn’t perform the operation because of a system problem") {
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})

	if isResourceTimeoutError(err) {
		_, err = conn.DeleteRegexPatternSet(&wafv2.DeleteRegexPatternSetInput{
			Id:        aws.String(d.Id()),
			Name:      aws.String(d.Get("name").(string)),
			Scope:     aws.String(d.Get("scope").(string)),
			LockToken: aws.String(d.Get("lock_token").(string)),
		})
	}

	if err != nil {
		return fmt.Errorf("Error deleting WAFV2 RegexPatternSet: %s", err)
	}

	return nil
}

func expandWafv2RegexPatternSet(l []interface{}) []*wafv2.Regex {
	if len(l) == 0 || l[0] == nil {
		return nil
	}

	regexPatterns := make([]*wafv2.Regex, 0)
	for _, regexPattern := range l {
		if regexPattern == nil {
			continue
		}

		regexPatterns = append(regexPatterns, expandWafv2Regex(regexPattern.(map[string]interface{})))
	}

	return regexPatterns
}

func expandWafv2Regex(m map[string]interface{}) *wafv2.Regex {
	if m == nil {
		return nil
	}

	return &wafv2.Regex{
		RegexString: aws.String(m["regex_string"].(string)),
	}
}
<|endoftext|>


<commit_before>package gleam

import (
	"errors"
)

var (
	ErrLoadScript = errors.New("Loading script error")
)
<commit_msg>gopher-lua replace liblua<commit_after><|endoftext|>


<commit_before>package gocoins

import (
	"fmt"
)

type TradeError struct {
	Message string
}

func (t TradeError) Error() string {
	return fmt.Sprintf("Trade Error: %s", t.Message)
}
<commit_msg>error: standard TradeError<commit_after>package gocoins

import (
	"errors"
)

type TradeError error

func NewTradeError(text string) TradeError {
	return TradeError(errors.New(text))
}

var (
	ErrInvalidCredential      = NewTradeError("Invalid Credential")
	ErrInsufficientPermission = NewTradeError("Insufficient Permissions")
	ErrInsufficientBalance    = NewTradeError("Insufficient Balance")
)
<|endoftext|>


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

package jwk

import (
	"testing"

	jwt2 "github.com/dgrijalva/jwt-go"
	"github.com/ory/fosite/token/jwt"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gopkg.in/square/go-jose.v2"
)

func TestRS256JWTStrategy(t *testing.T) {
	testGenerator := &RS256Generator{}

	m := &MemoryManager{
		Keys: map[string]*jose.JSONWebKeySet{},
	}

	ks, err := testGenerator.Generate("foo", "sig")
	require.NoError(t, err)
	require.NoError(t, m.AddKeySet("foo-set", ks))

	s, err := NewRS256JWTStrategy(m, "foo-set")
	require.NoError(t, err)
	a, b, err := s.Generate(jwt2.MapClaims{"foo": "bar"}, &jwt.Headers{})
	require.NoError(t, err)
	assert.NotEmpty(t, a)
	assert.NotEmpty(t, b)
	assert.Equal(t, "public:foo", s.GetPublicKeyID())

	ks, err = testGenerator.Generate("bar", "sig")
	require.NoError(t, err)
	require.NoError(t, m.AddKeySet("foo-set", ks))

	a, b, err = s.Generate(jwt2.MapClaims{"foo": "bar"}, &jwt.Headers{})
	require.NoError(t, err)
	assert.NotEmpty(t, a)
	assert.NotEmpty(t, b)
	assert.Equal(t, "public:bar", s.GetPublicKeyID())
}
<commit_msg>jwk: Resolves minor test issues<commit_after>/*
 * Copyright © 2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @Copyright 	2017-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @license 	Apache-2.0
 */

package jwk

import (
	"testing"

	jwt2 "github.com/dgrijalva/jwt-go"
	"github.com/ory/fosite/token/jwt"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gopkg.in/square/go-jose.v2"
)

func TestRS256JWTStrategy(t *testing.T) {
	testGenerator := &RS256Generator{}

	m := &MemoryManager{
		Keys: map[string]*jose.JSONWebKeySet{},
	}

	ks, err := testGenerator.Generate("foo", "sig")
	require.NoError(t, err)
	require.NoError(t, m.AddKeySet("foo-set", ks))

	s, err := NewRS256JWTStrategy(m, "foo-set")
	require.NoError(t, err)
	a, b, err := s.Generate(jwt2.MapClaims{"foo": "bar"}, &jwt.Headers{})
	require.NoError(t, err)
	assert.NotEmpty(t, a)
	assert.NotEmpty(t, b)

	kid, err := s.GetPublicKeyID()
	assert.NoError(t, err)
	assert.Equal(t, "public:foo", kid)

	ks, err = testGenerator.Generate("bar", "sig")
	require.NoError(t, err)
	require.NoError(t, m.AddKeySet("foo-set", ks))

	a, b, err = s.Generate(jwt2.MapClaims{"foo": "bar"}, &jwt.Headers{})
	require.NoError(t, err)
	assert.NotEmpty(t, a)
	assert.NotEmpty(t, b)

	kid, err = s.GetPublicKeyID()
	assert.NoError(t, err)
	assert.Equal(t, "public:bar", kid)
}
<|endoftext|>


<commit_before>// Copyright 2014, Surul Software Labs GmbH
// All rights reserved.

/*
Package fault provides utilities to help with package internal error handling.

It supports a simple idiom for reducing the amount of package internal error
handling. It allows you to panic with a Fault instance in package internal code.
This is then recovered using a defer for a all exported methods, which then return
an error extracted from the fault. As an example, if you were to be reading data
from a file and then writing it you could use

	import (
		"github.com/surullabs/fault"
	)

	var check = fault.NewChecker()

	func ExportedMethod() (err error) {
		// Set up the recovery. err will be automatically populated and all
		// non-fault panics will be propogated.
		defer check.Recover(&err)

		// If there is an error in ReadFile the method will automatically return
		// the error.
		data := check.Return(ioutil.ReadFile("filename")).([]byte)
		// If yourFn returns false the function will return an error
		// formatted as "condition is not true: yourData"
		check.Truef(yourFn(data), "condition is not true: %s", string(data))
	}

It also provides access to an ErrorChain class which can be used to chain errors together.
Errors can be transparently checked for existence in a chain by calling the Contains method.

Please look at the tests for more sample usage.
*/
package fault

import (
	"errors"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
)

// ErrorChain is a list of errors and can be used to chain errors together.
type ErrorChain struct {
	chain []error
}

// String returns the same value as Error()
func (c *ErrorChain) String() string { return c.Error() }

// Errors returns all errors in the chain
func (c *ErrorChain) Errors() []error { return c.chain }

// Error will return a string representation of all errors.
func (c *ErrorChain) Error() string {
	errors := make([]string, len(c.chain))
	for i, err := range c.chain {
		errors[i] = err.Error()
	}
	return strings.Join(errors, "; ")
}

// Chain appends the error provided to the current chain. If the
// err is a chain then all errors in the chain are appended.
func (c *ErrorChain) Chain(err error) {
	if err == nil {
		return
	}

	if c.chain == nil {
		c.chain = make([]error, 0)
	}

	switch e := err.(type) {
	case *ErrorChain:
		if e.chain != nil {
			c.chain = append(c.chain, e.chain...)
		}
	default:
		c.chain = append(c.chain, e)
	}
}

// Chain will chain a list of errors passed in. The errors can
// be of type *ErrorChain in which case their chains will be appended.
func Chain(errs ...error) error {
	if len(errs) == 0 {
		return nil
	}

	chain := &ErrorChain{}
	if errs[0] != nil {
		switch e := errs[0].(type) {
		case *ErrorChain:
			chain.chain = e.chain
		default:
			chain.chain = []error{e}
		}
	}

	for _, err := range errs[1:] {
		chain.Chain(err)
	}
	if len(chain.Errors()) == 0 {
		return nil
	}
	return chain
}

// Contains will return true in the following cases:
//
// 	* chain.Error() == target.Error()
// 	* chain is an ErrorChain and one of the errors is target
// 	* Contains(target, chain) returns true
func Contains(chain, target error) bool {
	if chain == nil || target == nil {
		return false
	}
	if chain.Error() == target.Error() {
		return true
	}
	if chainErr, isChain := chain.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == target.Error() {
				return true
			}
		}
	}
	if chainErr, isChain := target.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == chain.Error() {
				return true
			}
		}
	}
	return false
}

// Fault is an interface for representing a package internal fault.
type Fault interface {
	// Fault returns the error tied to this fault
	Fault() error
}

// Faulter is an interface used to generate faults from errors
type Faulter interface {
	New(err error) Fault
}

// FaultCheck is an interface providing functionality to check for faults and recover from them.
type FaultCheck interface {
	// Recover is used to recover from faults that were expressed through panics.
	// It will call recover() internally and the error variable pointed to by the argument will be populated with the fault information.
	Recover(*error)
	// RecoverPanic works exactly like recover with the exception that the second argument
	// must be the result of a call to recover()
	RecoverPanic(*error, interface{})
	// True will panic with a fault if the condition provided is false
	// The fault error string will be the second argument
	True(bool, string)
	// Truef behaves like Check with the error string as the result of a call to fmt.Errorf(format, args...)
	Truef(bool, string, ...interface{})
	// Return will panic if the error provided is not nil. It will return the first argument if not
	Return(interface{}, error) interface{}
	// Error is equivalent to a call to Return(nil, err)
	Error(error)
	// Output functions exactly as Return, with the only difference being that the output is included in the error message.
	// If the output is a byte array it is converted to a string.
	// This can be useful when debugging use of os/exec package for instance.
	Output(interface{}, error) interface{}
}

// Checker provides a default implementation of FaultCheck
type Checker struct {
	faulter Faulter
}

func NewChecker() *Checker { return &Checker{faulter: ErrorFaulter{}} }

func (c *Checker) SetFaulter(f Faulter) *Checker {
	c.faulter = f
	return c
}

// RecoverPanic implements FaultCheck.RecoverPanic
func (c *Checker) RecoverPanic(errPtr *error, panicked interface{}) {
	if panicked == nil {
		return
	} else if fault, faulty := panicked.(Fault); faulty {
		*errPtr = Chain(fault.Fault(), *errPtr)
		return
	} else {
		panic(panicked)
	}
}

// Recover implements FaultCheck.Recover
func (c *Checker) Recover(errPtr *error) {
	c.RecoverPanic(errPtr, recover())
}

type ErrorFaulter struct{}

func (ErrorFaulter) New(err error) Fault { return &errorFault{err: err} }

type errorFault struct {
	err error
}

func (e *errorFault) Fault() error { return e.err }

func (e *errorFault) String() string {
	if e.err == nil {
		return ""
	}
	return e.err.Error()

}

func (c *Checker) True(condition bool, errStr string) {
	if !condition {
		panic(c.faulter.New(errors.New(errStr)))
	}
}

// True implements FaultCheck.True
func (c *Checker) Truef(condition bool, format string, args ...interface{}) {
	if !condition {
		panic(c.faulter.New(fmt.Errorf(format, args...)))
	}
}

// Return implements FaultCheck.Return
func (c *Checker) Return(i interface{}, err error) interface{} {
	if err != nil {
		panic(c.faulter.New(err))
	}
	return i
}

// Error implements FaultCheck.Error
func (c *Checker) Error(err error) {
	if err != nil {
		panic(c.faulter.New(err))
	}
}

// Output implements FaultCheck.Output
func (c *Checker) Output(i interface{}, err error) interface{} {
	if err != nil {
		var out string
		if bytes, isByteArray := i.([]byte); isByteArray {
			out = string(bytes)
		} else {
			out = fmt.Sprintf("%v", i)
		}
		panic(c.faulter.New(&ErrorChain{chain: []error{err, fmt.Errorf("output: %s", out)}}))
	}
	return i
}

// Call provides information about a function call.
type Call struct {
	File string // File provides the file of the caller
	Line int    // Line provides the line number
	Name string // Name is the name of the calling function
}

func (c *Call) String() string { return fmt.Sprintf("%s:%d:%s", filepath.Base(c.File), c.Line, c.Name) }

func (c *Call) Equal(c2 *Call) bool {
	if c == nil {
		return c2 == nil
	} else if c2 == nil {
		return false
	}
	return c.File == c2.File && c.Line == c2.Line && c.Name == c2.Name
}

type debugFault struct {
	err   error
	trace []Call
}

func GetTrace(err error) (trace []Call) {
	if chain, isChain := err.(*ErrorChain); isChain {
		if fault, isFault := chain.Errors()[0].(*debugFault); isFault {
			return fault.trace
		}
	}
	return nil
}

func StartSite(trace []Call) (call *Call) {
	if len(trace) == 0 {
		call = &Call{"?", -1, "?"}
	} else {
		call = &trace[0]
	}
	return
}

func (d *debugFault) Error() string {
	return fmt.Sprintf("%v: %s", StartSite(d.trace), d.err.Error())
}

func (d *debugFault) Fault() error { return d }

type DebugFaulter struct{}

var checkerPrefix = TypePrefix(&Checker{})

func TypePrefix(i interface{}) string {
	val := reflect.ValueOf(i)
	if val.Kind() == reflect.Ptr {
		typeVal := val.Elem().Type()
		return fmt.Sprintf("%s.(*%s)", typeVal.PkgPath(), typeVal.Name())
	} else {
		return fmt.Sprintf("%s.(%s)", val.Type().PkgPath(), val.Type().Name())
	}
}

// ReadStack reads returns the stack after ignoring all calls up to the
// function which has the first parameter as a prefix . An empty string returns
// the entire stack.
func ReadStack(prefix string) (trace []Call) {
	trace = make([]Call, 0)
	var (
		pc uintptr
		fn *runtime.Func
	)
	appendTo := false
	for skip, ok := 0, true; ok; skip++ {
		call := Call{Name: "?"}
		if pc, call.File, call.Line, ok = runtime.Caller(skip); !ok {
			break
		}
		if fn = runtime.FuncForPC(pc); fn != nil {
			call.Name = fn.Name()
		}

		if appendTo {
			trace = append(trace, call)
		}
		if strings.HasPrefix(call.Name, prefix) {
			appendTo = true
		}
	}
	return
}

func (DebugFaulter) New(err error) Fault {
	return &debugFault{err: err, trace: ReadStack(checkerPrefix)}
}
<commit_msg>Convenient ErrorChain to error conversion<commit_after>// Copyright 2014, Surul Software Labs GmbH
// All rights reserved.

/*
Package fault provides utilities to help with package internal error handling.

It supports a simple idiom for reducing the amount of package internal error
handling. It allows you to panic with a Fault instance in package internal code.
This is then recovered using a defer for a all exported methods, which then return
an error extracted from the fault. As an example, if you were to be reading data
from a file and then writing it you could use

	import (
		"github.com/surullabs/fault"
	)

	var check = fault.NewChecker()

	func ExportedMethod() (err error) {
		// Set up the recovery. err will be automatically populated and all
		// non-fault panics will be propogated.
		defer check.Recover(&err)

		// If there is an error in ReadFile the method will automatically return
		// the error.
		data := check.Return(ioutil.ReadFile("filename")).([]byte)
		// If yourFn returns false the function will return an error
		// formatted as "condition is not true: yourData"
		check.Truef(yourFn(data), "condition is not true: %s", string(data))
	}

It also provides access to an ErrorChain class which can be used to chain errors together.
Errors can be transparently checked for existence in a chain by calling the Contains method.

Please look at the tests for more sample usage.
*/
package fault

import (
	"errors"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
)

// ErrorChain is a list of errors and can be used to chain errors together.
type ErrorChain struct {
	chain []error
}

// AsError returns an error if any are present in the chain or nil if not
func (c *ErrorChain) AsError() error {
	if c == nil || len(c.chain) == 0 {
		return nil
	}
	return c
}

// String returns the same value as Error()
func (c *ErrorChain) String() string { return c.Error() }

// Errors returns all errors in the chain
func (c *ErrorChain) Errors() []error { return c.chain }

// Error will return a string representation of all errors.
func (c *ErrorChain) Error() string {
	errors := make([]string, len(c.chain))
	for i, err := range c.chain {
		errors[i] = err.Error()
	}
	return strings.Join(errors, "; ")
}

// Chain appends the error provided to the current chain. If the
// err is a chain then all errors in the chain are appended.
func (c *ErrorChain) Chain(err error) {
	if err == nil {
		return
	}

	if c.chain == nil {
		c.chain = make([]error, 0)
	}

	switch e := err.(type) {
	case *ErrorChain:
		if e.chain != nil {
			c.chain = append(c.chain, e.chain...)
		}
	default:
		c.chain = append(c.chain, e)
	}
}

// Chain will chain a list of errors passed in. The errors can
// be of type *ErrorChain in which case their chains will be appended.
func Chain(errs ...error) error {
	chain := &ErrorChain{}
	for _, err := range errs {
		chain.Chain(err)
	}
	return chain.AsError()
}

// Contains will return true in the following cases:
//
// 	* chain.Error() == target.Error()
// 	* chain is an ErrorChain and one of the errors is target
// 	* Contains(target, chain) returns true
func Contains(chain, target error) bool {
	if chain == nil || target == nil {
		return false
	}
	if chain.Error() == target.Error() {
		return true
	}
	if chainErr, isChain := chain.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == target.Error() {
				return true
			}
		}
	}
	if chainErr, isChain := target.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == chain.Error() {
				return true
			}
		}
	}
	return false
}

// Fault is an interface for representing a package internal fault.
type Fault interface {
	// Fault returns the error tied to this fault
	Fault() error
}

// Faulter is an interface used to generate faults from errors
type Faulter interface {
	New(err error) Fault
}

// FaultCheck is an interface providing functionality to check for faults and recover from them.
type FaultCheck interface {
	// Recover is used to recover from faults that were expressed through panics.
	// It will call recover() internally and the error variable pointed to by the argument will be populated with the fault information.
	Recover(*error)
	// RecoverPanic works exactly like recover with the exception that the second argument
	// must be the result of a call to recover()
	RecoverPanic(*error, interface{})
	// True will panic with a fault if the condition provided is false
	// The fault error string will be the second argument
	True(bool, string)
	// Truef behaves like Check with the error string as the result of a call to fmt.Errorf(format, args...)
	Truef(bool, string, ...interface{})
	// Return will panic if the error provided is not nil. It will return the first argument if not
	Return(interface{}, error) interface{}
	// Error is equivalent to a call to Return(nil, err)
	Error(error)
	// Output functions exactly as Return, with the only difference being that the output is included in the error message.
	// If the output is a byte array it is converted to a string.
	// This can be useful when debugging use of os/exec package for instance.
	Output(interface{}, error) interface{}
}

// Checker provides a default implementation of FaultCheck
type Checker struct {
	faulter Faulter
}

func NewChecker() *Checker { return &Checker{faulter: ErrorFaulter{}} }

func (c *Checker) SetFaulter(f Faulter) *Checker {
	c.faulter = f
	return c
}

// RecoverPanic implements FaultCheck.RecoverPanic
func (c *Checker) RecoverPanic(errPtr *error, panicked interface{}) {
	if panicked == nil {
		return
	} else if fault, faulty := panicked.(Fault); faulty {
		*errPtr = Chain(fault.Fault(), *errPtr)
		return
	} else {
		panic(panicked)
	}
}

// Recover implements FaultCheck.Recover
func (c *Checker) Recover(errPtr *error) {
	c.RecoverPanic(errPtr, recover())
}

type ErrorFaulter struct{}

func (ErrorFaulter) New(err error) Fault { return &errorFault{err: err} }

type errorFault struct {
	err error
}

func (e *errorFault) Fault() error { return e.err }

func (e *errorFault) String() string {
	if e.err == nil {
		return ""
	}
	return e.err.Error()

}

func (c *Checker) True(condition bool, errStr string) {
	if !condition {
		panic(c.faulter.New(errors.New(errStr)))
	}
}

// True implements FaultCheck.True
func (c *Checker) Truef(condition bool, format string, args ...interface{}) {
	if !condition {
		panic(c.faulter.New(fmt.Errorf(format, args...)))
	}
}

// Return implements FaultCheck.Return
func (c *Checker) Return(i interface{}, err error) interface{} {
	if err != nil {
		panic(c.faulter.New(err))
	}
	return i
}

// Error implements FaultCheck.Error
func (c *Checker) Error(err error) {
	if err != nil {
		panic(c.faulter.New(err))
	}
}

// Output implements FaultCheck.Output
func (c *Checker) Output(i interface{}, err error) interface{} {
	if err != nil {
		var out string
		if bytes, isByteArray := i.([]byte); isByteArray {
			out = string(bytes)
		} else {
			out = fmt.Sprintf("%v", i)
		}
		panic(c.faulter.New(&ErrorChain{chain: []error{err, fmt.Errorf("output: %s", out)}}))
	}
	return i
}

// Call provides information about a function call.
type Call struct {
	File string // File provides the file of the caller
	Line int    // Line provides the line number
	Name string // Name is the name of the calling function
}

func (c *Call) String() string { return fmt.Sprintf("%s:%d:%s", filepath.Base(c.File), c.Line, c.Name) }

func (c *Call) Equal(c2 *Call) bool {
	if c == nil {
		return c2 == nil
	} else if c2 == nil {
		return false
	}
	return c.File == c2.File && c.Line == c2.Line && c.Name == c2.Name
}

type debugFault struct {
	err   error
	trace []Call
}

func GetTrace(err error) (trace []Call) {
	if chain, isChain := err.(*ErrorChain); isChain {
		if fault, isFault := chain.Errors()[0].(*debugFault); isFault {
			return fault.trace
		}
	}
	return nil
}

func StartSite(trace []Call) (call *Call) {
	if len(trace) == 0 {
		call = &Call{"?", -1, "?"}
	} else {
		call = &trace[0]
	}
	return
}

func (d *debugFault) Error() string {
	return fmt.Sprintf("%v: %s", StartSite(d.trace), d.err.Error())
}

func (d *debugFault) Fault() error { return d }

type DebugFaulter struct{}

var checkerPrefix = TypePrefix(&Checker{})

func TypePrefix(i interface{}) string {
	val := reflect.ValueOf(i)
	if val.Kind() == reflect.Ptr {
		typeVal := val.Elem().Type()
		return fmt.Sprintf("%s.(*%s)", typeVal.PkgPath(), typeVal.Name())
	} else {
		return fmt.Sprintf("%s.(%s)", val.Type().PkgPath(), val.Type().Name())
	}
}

// ReadStack reads returns the stack after ignoring all calls up to the
// function which has the first parameter as a prefix . An empty string returns
// the entire stack.
func ReadStack(prefix string) (trace []Call) {
	trace = make([]Call, 0)
	var (
		pc uintptr
		fn *runtime.Func
	)
	appendTo := false
	for skip, ok := 0, true; ok; skip++ {
		call := Call{Name: "?"}
		if pc, call.File, call.Line, ok = runtime.Caller(skip); !ok {
			break
		}
		if fn = runtime.FuncForPC(pc); fn != nil {
			call.Name = fn.Name()
		}

		if appendTo {
			trace = append(trace, call)
		}
		if strings.HasPrefix(call.Name, prefix) {
			appendTo = true
		}
	}
	return
}

func (DebugFaulter) New(err error) Fault {
	return &debugFault{err: err, trace: ReadStack(checkerPrefix)}
}
<|endoftext|>


<commit_before>package bitrise

import (
	"fmt"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/colorstring"
	models "github.com/bitrise-io/bitrise/models/models_1_0_0"
)

const (
	stepRunSummaryBoxMaxWidthChars = 50

	// StepRunResultCodeSuccess ...
	StepRunResultCodeSuccess = 0
	// StepRunResultCodeFailed ...
	StepRunResultCodeFailed = 1
	// StepRunResultCodeFailedNotImportant ...
	StepRunResultCodeFailedNotImportant = 2
	// StepRunResultCodeSkipped ...
	StepRunResultCodeSkipped = 3
	// StepRunResultCodeSkippedWithRunIf ...
	StepRunResultCodeSkippedWithRunIf = 4
)

// PrintRunningWorkflow ...
func PrintRunningWorkflow(title string) {
	fmt.Println()
	log.Info(colorstring.Bluef("Running workflow (%s)", title))
	fmt.Println()
}

// PrintRunningStep ...
func PrintRunningStep(title string, idx int) {
	content := fmt.Sprintf("(%d) %s", idx, title)
	if len(content) > stepRunSummaryBoxMaxWidthChars {
		dif := stepRunSummaryBoxMaxWidthChars - len(content)
		title = title[0 : len(content)-dif]
		content = fmt.Sprintf("(%d) %s", idx, title)
	}
	sep := strings.Repeat("-", len(content)+4)
	log.Info(sep)
	log.Infof("| (%d) %s |", idx, title)
	log.Info(sep)
}

// PrintStepSummary ..
func PrintStepSummary(title string, resultCode int, duration time.Duration, exitCode int) {
	runTime := TimeToFormattedSeconds(duration, " sec")
	content := fmt.Sprintf("%s | .... | %s", title, runTime)
	if resultCode == StepRunResultCodeFailed || resultCode == StepRunResultCodeFailedNotImportant {
		content = fmt.Sprintf("%s | .... | exit code: %d | %s", title, exitCode, runTime)
	}
	if len(content) > stepRunSummaryBoxMaxWidthChars {
		dif := len(content) - stepRunSummaryBoxMaxWidthChars
		title = title[0:(len(title) - dif)]
		content = fmt.Sprintf("%s | .... | %s", title, runTime)
		if resultCode == StepRunResultCodeFailed || resultCode == StepRunResultCodeFailedNotImportant {
			content = fmt.Sprintf("%s | .... | exit code: %d | %s", title, exitCode, runTime)
		}
	}

	sep := strings.Repeat("-", len(content)+2)
	log.Info(sep)
	switch resultCode {
	case StepRunResultCodeSuccess:
		runStateIcon := "✅ "
		content = fmt.Sprintf("%s | %s | %s", runStateIcon, colorstring.Green(title), runTime)
		break
	case StepRunResultCodeFailed:
		runStateIcon := "❌ "
		content = fmt.Sprintf("%s | %s | %s | exit code: %d", runStateIcon, colorstring.Red(title), runTime, exitCode)
		break
	case StepRunResultCodeFailedNotImportant:
		runStateIcon := "❌ "
		content = fmt.Sprintf("%s | %s | %s | exit code: %d", runStateIcon, colorstring.Yellow(title), runTime, exitCode)
		break
	case StepRunResultCodeSkipped, StepRunResultCodeSkippedWithRunIf:
		runStateIcon := "➡ "
		content = fmt.Sprintf("%s | %s | %s", runStateIcon, colorstring.White(title), runTime)
		break
	default:
		log.Error("Unkown result code")
		return
	}

	log.Infof("| " + content + " |")
	log.Info(sep)
	fmt.Println()
}

// PrintBuildFailedFatal ...
func PrintBuildFailedFatal(startTime time.Time, err error) {
	runTime := time.Now().Sub(startTime)
	log.Error("Build failed: " + err.Error())
	log.Fatal("Total run time: " + runTime.String())
}

// PrintSummary ...
func PrintSummary(buildRunResults models.BuildRunResultsModel) {
	totalStepCount := 0
	successStepCount := 0
	failedStepCount := 0
	failedNotImportantStepCount := 0
	skippedStepCount := 0

	successStepCount += len(buildRunResults.SuccessSteps)
	failedStepCount += len(buildRunResults.FailedSteps)
	failedNotImportantStepCount += len(buildRunResults.FailedNotImportantSteps)
	skippedStepCount += len(buildRunResults.SkippedSteps)
	totalStepCount = successStepCount + failedStepCount + failedNotImportantStepCount + skippedStepCount

	fmt.Println()
	log.Infoln("==> Summary:")
	runTime := time.Now().Sub(buildRunResults.StartTime)
	log.Info("Total run time: " + TimeToFormattedSeconds(runTime, " seconds"))

	if totalStepCount > 0 {
		log.Infof("Out of %d steps:", totalStepCount)

		if successStepCount > 0 {
			log.Info(colorstring.Greenf(" * %d was successful", successStepCount))
		}
		if failedStepCount > 0 {
			log.Info(colorstring.Redf(" * %d failed", failedStepCount))
		}
		if failedNotImportantStepCount > 0 {
			log.Info(colorstring.Yellowf(" * %d failed but was marked as skippable and", failedNotImportantStepCount))
		}
		if skippedStepCount > 0 {
			log.Info(colorstring.Whitef(" * %d was skipped", skippedStepCount))
		}

		fmt.Println()
		if failedStepCount > 0 {
			log.Fatal("FINISHED but a couple of steps failed - Ouch")
		} else {
			log.Info("DONE - Congrats!!")
			if failedNotImportantStepCount > 0 {
				log.Warn("P.S.: a couple of non imporatant steps failed")
			}
		}
	}
}

// PrintStepStatus ...
func PrintStepStatus(stepRunResults models.BuildRunResultsModel) {
	failedCount := len(stepRunResults.FailedSteps)
	failedNotImportantCount := len(stepRunResults.FailedNotImportantSteps)
	skippedCount := len(stepRunResults.SkippedSteps)
	successCount := len(stepRunResults.SuccessSteps)
	totalCount := successCount + failedCount + failedNotImportantCount + skippedCount

	log.Infof("Out of %d steps, %d was successful, %d failed, %d failed but was marked as skippable and %d was skipped",
		totalCount,
		successCount,
		failedCount,
		failedNotImportantCount,
		skippedCount)

	PrintStepStatusList("Failed steps:", stepRunResults.FailedSteps)
	PrintStepStatusList("Failed but skippable steps:", stepRunResults.FailedNotImportantSteps)
	PrintStepStatusList("Skipped steps:", stepRunResults.SkippedSteps)
}

// PrintStepStatusList ...
func PrintStepStatusList(header string, stepList []models.StepRunResultsModel) {
	if len(stepList) > 0 {
		log.Infof(header)
		for _, step := range stepList {
			if step.Error != nil {
				log.Infof(" * Step: (%s) | error: (%v)", step.StepName, step.Error)
			} else {
				log.Infof(" * Step: (%s)", step.StepName)
			}
		}
	}
}
<commit_msg>math fix<commit_after>package bitrise

import (
	"fmt"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/colorstring"
	models "github.com/bitrise-io/bitrise/models/models_1_0_0"
)

const (
	stepRunSummaryBoxMaxWidthChars = 50

	// StepRunResultCodeSuccess ...
	StepRunResultCodeSuccess = 0
	// StepRunResultCodeFailed ...
	StepRunResultCodeFailed = 1
	// StepRunResultCodeFailedNotImportant ...
	StepRunResultCodeFailedNotImportant = 2
	// StepRunResultCodeSkipped ...
	StepRunResultCodeSkipped = 3
	// StepRunResultCodeSkippedWithRunIf ...
	StepRunResultCodeSkippedWithRunIf = 4
)

// PrintRunningWorkflow ...
func PrintRunningWorkflow(title string) {
	fmt.Println()
	log.Info(colorstring.Bluef("Running workflow (%s)", title))
	fmt.Println()
}

// PrintRunningStep ...
func PrintRunningStep(title string, idx int) {
	content := fmt.Sprintf("(%d) %s", idx, title)
	if len(content) > stepRunSummaryBoxMaxWidthChars {
		dif := len(content) - stepRunSummaryBoxMaxWidthChars
		title = title[0 : len(content)-dif]
		content = fmt.Sprintf("(%d) %s", idx, title)
	}
	sep := strings.Repeat("-", len(content)+4)
	log.Info(sep)
	log.Infof("| (%d) %s |", idx, title)
	log.Info(sep)
}

// PrintStepSummary ..
func PrintStepSummary(title string, resultCode int, duration time.Duration, exitCode int) {
	runTime := TimeToFormattedSeconds(duration, " sec")
	content := fmt.Sprintf("%s | .... | %s", title, runTime)
	if resultCode == StepRunResultCodeFailed || resultCode == StepRunResultCodeFailedNotImportant {
		content = fmt.Sprintf("%s | .... | exit code: %d | %s", title, exitCode, runTime)
	}
	if len(content) > stepRunSummaryBoxMaxWidthChars {
		dif := len(content) - stepRunSummaryBoxMaxWidthChars
		title = title[0:(len(title) - dif)]
		content = fmt.Sprintf("%s | .... | %s", title, runTime)
		if resultCode == StepRunResultCodeFailed || resultCode == StepRunResultCodeFailedNotImportant {
			content = fmt.Sprintf("%s | .... | exit code: %d | %s", title, exitCode, runTime)
		}
	}

	sep := strings.Repeat("-", len(content)+2)
	log.Info(sep)
	switch resultCode {
	case StepRunResultCodeSuccess:
		runStateIcon := "✅ "
		content = fmt.Sprintf("%s | %s | %s", runStateIcon, colorstring.Green(title), runTime)
		break
	case StepRunResultCodeFailed:
		runStateIcon := "❌ "
		content = fmt.Sprintf("%s | %s | %s | exit code: %d", runStateIcon, colorstring.Red(title), runTime, exitCode)
		break
	case StepRunResultCodeFailedNotImportant:
		runStateIcon := "❌ "
		content = fmt.Sprintf("%s | %s | %s | exit code: %d", runStateIcon, colorstring.Yellow(title), runTime, exitCode)
		break
	case StepRunResultCodeSkipped, StepRunResultCodeSkippedWithRunIf:
		runStateIcon := "➡ "
		content = fmt.Sprintf("%s | %s | %s", runStateIcon, colorstring.White(title), runTime)
		break
	default:
		log.Error("Unkown result code")
		return
	}

	log.Infof("| " + content + " |")
	log.Info(sep)
	fmt.Println()
}

// PrintBuildFailedFatal ...
func PrintBuildFailedFatal(startTime time.Time, err error) {
	runTime := time.Now().Sub(startTime)
	log.Error("Build failed: " + err.Error())
	log.Fatal("Total run time: " + runTime.String())
}

// PrintSummary ...
func PrintSummary(buildRunResults models.BuildRunResultsModel) {
	totalStepCount := 0
	successStepCount := 0
	failedStepCount := 0
	failedNotImportantStepCount := 0
	skippedStepCount := 0

	successStepCount += len(buildRunResults.SuccessSteps)
	failedStepCount += len(buildRunResults.FailedSteps)
	failedNotImportantStepCount += len(buildRunResults.FailedNotImportantSteps)
	skippedStepCount += len(buildRunResults.SkippedSteps)
	totalStepCount = successStepCount + failedStepCount + failedNotImportantStepCount + skippedStepCount

	fmt.Println()
	log.Infoln("==> Summary:")
	runTime := time.Now().Sub(buildRunResults.StartTime)
	log.Info("Total run time: " + TimeToFormattedSeconds(runTime, " seconds"))

	if totalStepCount > 0 {
		log.Infof("Out of %d steps:", totalStepCount)

		if successStepCount > 0 {
			log.Info(colorstring.Greenf(" * %d was successful", successStepCount))
		}
		if failedStepCount > 0 {
			log.Info(colorstring.Redf(" * %d failed", failedStepCount))
		}
		if failedNotImportantStepCount > 0 {
			log.Info(colorstring.Yellowf(" * %d failed but was marked as skippable and", failedNotImportantStepCount))
		}
		if skippedStepCount > 0 {
			log.Info(colorstring.Whitef(" * %d was skipped", skippedStepCount))
		}

		fmt.Println()
		if failedStepCount > 0 {
			log.Fatal("FINISHED but a couple of steps failed - Ouch")
		} else {
			log.Info("DONE - Congrats!!")
			if failedNotImportantStepCount > 0 {
				log.Warn("P.S.: a couple of non imporatant steps failed")
			}
		}
	}
}

// PrintStepStatus ...
func PrintStepStatus(stepRunResults models.BuildRunResultsModel) {
	failedCount := len(stepRunResults.FailedSteps)
	failedNotImportantCount := len(stepRunResults.FailedNotImportantSteps)
	skippedCount := len(stepRunResults.SkippedSteps)
	successCount := len(stepRunResults.SuccessSteps)
	totalCount := successCount + failedCount + failedNotImportantCount + skippedCount

	log.Infof("Out of %d steps, %d was successful, %d failed, %d failed but was marked as skippable and %d was skipped",
		totalCount,
		successCount,
		failedCount,
		failedNotImportantCount,
		skippedCount)

	PrintStepStatusList("Failed steps:", stepRunResults.FailedSteps)
	PrintStepStatusList("Failed but skippable steps:", stepRunResults.FailedNotImportantSteps)
	PrintStepStatusList("Skipped steps:", stepRunResults.SkippedSteps)
}

// PrintStepStatusList ...
func PrintStepStatusList(header string, stepList []models.StepRunResultsModel) {
	if len(stepList) > 0 {
		log.Infof(header)
		for _, step := range stepList {
			if step.Error != nil {
				log.Infof(" * Step: (%s) | error: (%v)", step.StepName, step.Error)
			} else {
				log.Infof(" * Step: (%s)", step.StepName)
			}
		}
	}
}
<|endoftext|>


<commit_before>package bitrise

import (
	"errors"
	"fmt"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/toolkits"
	"github.com/bitrise-io/bitrise/version"
	"github.com/bitrise-io/go-utils/colorstring"
)

const (
	minEnvmanVersion  = "1.1.3"
	minStepmanVersion = "0.9.30"
)

// PluginDependency ..
type PluginDependency struct {
	Source     string
	MinVersion string
}

// PluginDependencyMap ...
var PluginDependencyMap = map[string]PluginDependency{
	"init": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-init.git",
		MinVersion: "0.9.1",
	},
	"step": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-step.git",
		MinVersion: "0.9.1",
	},
	"workflow-editor": PluginDependency{
		Source:     "https://github.com/bitrise-io/bitrise-workflow-editor.git",
		MinVersion: "0.9.9",
	},
	"analytics": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-analytics.git",
		MinVersion: "0.9.8",
	},
}

// RunSetupIfNeeded ...
func RunSetupIfNeeded(appVersion string, isFullSetupMode bool) error {
	if !configs.CheckIsSetupWasDoneForVersion(version.VERSION) {
		log.Warnln(colorstring.Yellow("Setup was not performed for this version of bitrise, doing it now..."))
		return RunSetup(version.VERSION, false)
	}
	return nil
}

// RunSetup ...
func RunSetup(appVersion string, isFullSetupMode bool) error {
	log.Infoln("Setup")
	log.Infof("Full setup: %v", isFullSetupMode)
	log.Infoln("Detected OS:", runtime.GOOS)

	if err := doSetupBitriseCoreTools(); err != nil {
		return fmt.Errorf("Failed to do common/platform independent setup, error: %s", err)
	}

	switch runtime.GOOS {
	case "darwin":
		if err := doSetupOnOSX(isFullSetupMode); err != nil {
			return fmt.Errorf("Failed to do MacOS specific setup, error: %s", err)
		}
	case "linux":
	default:
		return errors.New("unsupported platform :(")
	}

	if err := doSetupPlugins(); err != nil {
		return fmt.Errorf("Failed to do Plugins setup, error: %s", err)
	}

	if err := doSetupToolkits(); err != nil {
		return fmt.Errorf("Failed to do Toolkits setup, error: %s", err)
	}

	log.Infoln("All the required tools are installed!")

	if err := configs.SaveSetupSuccessForVersion(appVersion); err != nil {
		return fmt.Errorf("failed to save setup-success into config file, error: %s", err)
	}

	// guide
	log.Infoln("We're ready to rock!!")
	fmt.Println()

	return nil
}

func doSetupToolkits() error {
	log.Infoln("Checking Bitrise Toolkits...")

	coreToolkits := toolkits.AllSupportedToolkits()

	for _, aCoreTK := range coreToolkits {
		toolkitName := aCoreTK.ToolkitName()
		isInstallRequired, checkResult, err := aCoreTK.Check()
		if err != nil {
			return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
		}

		if isInstallRequired {
			log.Infoln("No installed/suitable '" + toolkitName + "' found, installing toolkit ...")
			if err := aCoreTK.Install(); err != nil {
				return fmt.Errorf("Failed to install toolkit (%s), error: %s", toolkitName, err)
			}

			isInstallRequired, checkResult, err = aCoreTK.Check()
			if err != nil {
				return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
			}
		}
		if isInstallRequired {
			return fmt.Errorf("Toolkit (%s) still reports that it isn't (properly) installed", toolkitName)
		}

		log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolkitName+" :", checkResult.Path)
		log.Infoln("        version :", checkResult.Version)
	}

	return nil
}

func doSetupPlugins() error {
	log.Infoln("Checking Bitrise Plugins...")

	for pluginName, pluginDependency := range PluginDependencyMap {
		if err := CheckIsPluginInstalled(pluginName, pluginDependency); err != nil {
			return fmt.Errorf("Plugin (%s) failed to install: %s", pluginName, err)
		}
	}

	return nil
}

func doSetupBitriseCoreTools() error {
	log.Infoln("Checking Bitrise Core tools...")

	if err := CheckIsEnvmanInstalled(minEnvmanVersion); err != nil {
		return fmt.Errorf("Envman failed to install: %s", err)
	}

	if err := CheckIsStepmanInstalled(minStepmanVersion); err != nil {
		return fmt.Errorf("Stepman failed to install: %s", err)
	}

	return nil
}

func doSetupOnOSX(isMinimalSetupMode bool) error {
	log.Infoln("Doing OS X specific setup")
	log.Infoln("Checking required tools...")

	if err := CheckIsHomebrewInstalled(isMinimalSetupMode); err != nil {
		return errors.New(fmt.Sprint("Homebrew not installed or has some issues. Please fix these before calling setup again. Err:", err))
	}

	if err := PrintInstalledXcodeInfos(); err != nil {
		return errors.New(fmt.Sprint("Failed to detect installed Xcode and Xcode Command Line Tools infos. Err:", err))
	}
	return nil
}
<commit_msg>default plugin updates (#503)<commit_after>package bitrise

import (
	"errors"
	"fmt"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/toolkits"
	"github.com/bitrise-io/bitrise/version"
	"github.com/bitrise-io/go-utils/colorstring"
)

const (
	minEnvmanVersion  = "1.1.3"
	minStepmanVersion = "0.9.30"
)

// PluginDependency ..
type PluginDependency struct {
	Source     string
	MinVersion string
}

// PluginDependencyMap ...
var PluginDependencyMap = map[string]PluginDependency{
	"init": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-init.git",
		MinVersion: "0.9.2",
	},
	"step": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-step.git",
		MinVersion: "0.9.1",
	},
	"workflow-editor": PluginDependency{
		Source:     "https://github.com/bitrise-io/bitrise-workflow-editor.git",
		MinVersion: "0.9.9",
	},
	"analytics": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-analytics.git",
		MinVersion: "0.9.9",
	},
}

// RunSetupIfNeeded ...
func RunSetupIfNeeded(appVersion string, isFullSetupMode bool) error {
	if !configs.CheckIsSetupWasDoneForVersion(version.VERSION) {
		log.Warnln(colorstring.Yellow("Setup was not performed for this version of bitrise, doing it now..."))
		return RunSetup(version.VERSION, false)
	}
	return nil
}

// RunSetup ...
func RunSetup(appVersion string, isFullSetupMode bool) error {
	log.Infoln("Setup")
	log.Infof("Full setup: %v", isFullSetupMode)
	log.Infoln("Detected OS:", runtime.GOOS)

	if err := doSetupBitriseCoreTools(); err != nil {
		return fmt.Errorf("Failed to do common/platform independent setup, error: %s", err)
	}

	switch runtime.GOOS {
	case "darwin":
		if err := doSetupOnOSX(isFullSetupMode); err != nil {
			return fmt.Errorf("Failed to do MacOS specific setup, error: %s", err)
		}
	case "linux":
	default:
		return errors.New("unsupported platform :(")
	}

	if err := doSetupPlugins(); err != nil {
		return fmt.Errorf("Failed to do Plugins setup, error: %s", err)
	}

	if err := doSetupToolkits(); err != nil {
		return fmt.Errorf("Failed to do Toolkits setup, error: %s", err)
	}

	log.Infoln("All the required tools are installed!")

	if err := configs.SaveSetupSuccessForVersion(appVersion); err != nil {
		return fmt.Errorf("failed to save setup-success into config file, error: %s", err)
	}

	// guide
	log.Infoln("We're ready to rock!!")
	fmt.Println()

	return nil
}

func doSetupToolkits() error {
	log.Infoln("Checking Bitrise Toolkits...")

	coreToolkits := toolkits.AllSupportedToolkits()

	for _, aCoreTK := range coreToolkits {
		toolkitName := aCoreTK.ToolkitName()
		isInstallRequired, checkResult, err := aCoreTK.Check()
		if err != nil {
			return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
		}

		if isInstallRequired {
			log.Infoln("No installed/suitable '" + toolkitName + "' found, installing toolkit ...")
			if err := aCoreTK.Install(); err != nil {
				return fmt.Errorf("Failed to install toolkit (%s), error: %s", toolkitName, err)
			}

			isInstallRequired, checkResult, err = aCoreTK.Check()
			if err != nil {
				return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
			}
		}
		if isInstallRequired {
			return fmt.Errorf("Toolkit (%s) still reports that it isn't (properly) installed", toolkitName)
		}

		log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolkitName+" :", checkResult.Path)
		log.Infoln("        version :", checkResult.Version)
	}

	return nil
}

func doSetupPlugins() error {
	log.Infoln("Checking Bitrise Plugins...")

	for pluginName, pluginDependency := range PluginDependencyMap {
		if err := CheckIsPluginInstalled(pluginName, pluginDependency); err != nil {
			return fmt.Errorf("Plugin (%s) failed to install: %s", pluginName, err)
		}
	}

	return nil
}

func doSetupBitriseCoreTools() error {
	log.Infoln("Checking Bitrise Core tools...")

	if err := CheckIsEnvmanInstalled(minEnvmanVersion); err != nil {
		return fmt.Errorf("Envman failed to install: %s", err)
	}

	if err := CheckIsStepmanInstalled(minStepmanVersion); err != nil {
		return fmt.Errorf("Stepman failed to install: %s", err)
	}

	return nil
}

func doSetupOnOSX(isMinimalSetupMode bool) error {
	log.Infoln("Doing OS X specific setup")
	log.Infoln("Checking required tools...")

	if err := CheckIsHomebrewInstalled(isMinimalSetupMode); err != nil {
		return errors.New(fmt.Sprint("Homebrew not installed or has some issues. Please fix these before calling setup again. Err:", err))
	}

	if err := PrintInstalledXcodeInfos(); err != nil {
		return errors.New(fmt.Sprint("Failed to detect installed Xcode and Xcode Command Line Tools infos. Err:", err))
	}
	return nil
}
<|endoftext|>


<commit_before>package crawler

import (
	"fmt"
	"github.com/ChimeraCoder/anaconda"
	"log"
	"strings"
)

func failIfNeeded(e error) {
	if e != nil {
		log.Fatalln(e)
	}
}

func printResults(ts []anaconda.Tweet) {
	for _, t := range ts {
		printResult(t)
	}
}

func printResult(t anaconda.Tweet) {
	fmt.Println("InReplyToStatusID: ", t.InReplyToStatusID)
	p := Parser{}
	ns := p.ParseToNouns([]string{t.Text})
	wc := wordCount(ns)
	for noun, count := range wc {
		fmt.Println(count, noun)
	}
}

func wordCount(ss []string) map[string]int {
	res := make(map[string]int)
	for _, str := range ss {
		res[strings.ToLower(str)]++
	}
	return res
}

func containsString(ss []string, target string) bool {
	for _, s := range ss {
		if s == target {
			return true
		}
	}
	return false
}
func containsNearlyString(ss []string, target string) bool {
	for _, s := range ss {
		if strings.Contains(target, s) {
			return true
		}
	}
	return false
}

func OutputAniversarries(aniversaries []Anniversary) {
	log.Println("============SUMMARY============")
	log.Println("aniversary count: ", len(aniversaries))
	for _, aniv := range aniversaries {
		first := aniv.CreateFirstMessage()
		second, _ := aniv.CreateSecondMessage()
		log.Println("message: ", aniv.CreateFullMessage(first, second))
	}
}
<commit_msg>エラー隠蔽方針にした<commit_after>package crawler

import (
	"fmt"
	"github.com/ChimeraCoder/anaconda"
	"log"
	"strings"
)

func failIfNeeded(e error) {
	if e != nil {
		log.Println(e)
	}
}

func printResults(ts []anaconda.Tweet) {
	for _, t := range ts {
		printResult(t)
	}
}

func printResult(t anaconda.Tweet) {
	fmt.Println("InReplyToStatusID: ", t.InReplyToStatusID)
	p := Parser{}
	ns := p.ParseToNouns([]string{t.Text})
	wc := wordCount(ns)
	for noun, count := range wc {
		fmt.Println(count, noun)
	}
}

func wordCount(ss []string) map[string]int {
	res := make(map[string]int)
	for _, str := range ss {
		res[strings.ToLower(str)]++
	}
	return res
}

func containsString(ss []string, target string) bool {
	for _, s := range ss {
		if s == target {
			return true
		}
	}
	return false
}
func containsNearlyString(ss []string, target string) bool {
	for _, s := range ss {
		if strings.Contains(target, s) {
			return true
		}
	}
	return false
}

func OutputAniversarries(aniversaries []Anniversary) {
	log.Println("============SUMMARY============")
	log.Println("aniversary count: ", len(aniversaries))
	for _, aniv := range aniversaries {
		first := aniv.CreateFirstMessage()
		second, _ := aniv.CreateSecondMessage()
		log.Println("message: ", aniv.CreateFullMessage(first, second))
	}
}
<|endoftext|>