<commit_before>package aws

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

	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/route53"
)

func resource_aws_r53_record_validation() *config.Validator {
	return &config.Validator{
		Required: []string{
			"zone_id",
			"name",
			"type",
			"ttl",
			"records.*",
		},
	}
}

func resource_aws_r53_record_create(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	conn := p.route53

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

	// Get the record
	rec, err := resource_aws_r53_build_record_set(rs)
	if err != nil {
		return rs, err
	}

	// Create the new records. We abuse StateChangeConf for this to
	// retry for us since Route53 sometimes returns errors about another
	// operation happening at the same time.
	req := &route53.ChangeResourceRecordSetsRequest{
		Comment: "Managed by Terraform",
		Changes: []route53.Change{
			route53.Change{
				Action: "UPSERT",
				Record: *rec,
			},
		},
	}
	zone := rs.Attributes["zone_id"]
	log.Printf("[DEBUG] Creating resource records for zone: %s, name: %s",
		zone, rs.Attributes["name"])
	wait := resource.StateChangeConf{
		Pending:    []string{"rejected"},
		Target:     "accepted",
		Timeout:    5 * time.Minute,
		MinTimeout: 1 * time.Second,
		Refresh: func() (interface{}, string, error) {
			resp, err := conn.ChangeResourceRecordSets(zone, req)
			if err != nil {
				if strings.Contains(err.Error(), "PriorRequestNotComplete") {
					// There is some pending operation, so just retry
					// in a bit.
					return nil, "rejected", nil
				}

				return nil, "failure", err
			}

			return resp.ChangeInfo, "accepted", nil
		},
	}
	respRaw, err := wait.WaitForState()
	if err != nil {
		return rs, err
	}
	changeInfo := respRaw.(route53.ChangeInfo)

	// Generate an ID
	rs.ID = fmt.Sprintf("%s_%s_%s", zone, rs.Attributes["name"], rs.Attributes["type"])

	// Wait until we are done
	wait = resource.StateChangeConf{
		Delay:      30 * time.Second,
		Pending:    []string{"PENDING"},
		Target:     "INSYNC",
		Timeout:    10 * time.Minute,
		MinTimeout: 5 * time.Second,
		Refresh: func() (result interface{}, state string, err error) {
			return resource_aws_r53_wait(conn, changeInfo.ID)
		},
	}
	_, err = wait.WaitForState()
	if err != nil {
		return rs, err
	}
	return rs, nil
}

func resource_aws_r53_build_record_set(s *terraform.InstanceState) (*route53.ResourceRecordSet, error) {
	// Parse the TTL
	ttl, err := strconv.ParseInt(s.Attributes["ttl"], 10, 32)
	if err != nil {
		return nil, err
	}

	// Expand the records
	recRaw := flatmap.Expand(s.Attributes, "records")
	var records []string
	for _, raw := range recRaw.([]interface{}) {
		records = append(records, raw.(string))
	}

	rec := &route53.ResourceRecordSet{
		Name:    s.Attributes["name"],
		Type:    s.Attributes["type"],
		TTL:     int(ttl),
		Records: records,
	}
	return rec, nil
}

func resource_aws_r53_record_destroy(
	s *terraform.InstanceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	conn := p.route53

	// Get the record
	rec, err := resource_aws_r53_build_record_set(s)
	if err != nil {
		return err
	}

	// Create the new records
	req := &route53.ChangeResourceRecordSetsRequest{
		Comment: "Deleted by Terraform",
		Changes: []route53.Change{
			route53.Change{
				Action: "DELETE",
				Record: *rec,
			},
		},
	}
	zone := s.Attributes["zone_id"]
	log.Printf("[DEBUG] Deleting resource records for zone: %s, name: %s",
		zone, s.Attributes["name"])
	wait := resource.StateChangeConf{
		Pending:    []string{"rejected"},
		Target:     "accepted",
		Timeout:    5 * time.Minute,
		MinTimeout: 1 * time.Second,
		Refresh: func() (interface{}, string, error) {
			_, err := conn.ChangeResourceRecordSets(zone, req)
			if err != nil {
				if strings.Contains(err.Error(), "PriorRequestNotComplete") {
					// There is some pending operation, so just retry
					// in a bit.
					return nil, "rejected", nil
				}

				return nil, "failure", err
			}

			return nil, "accepted", nil
		},
	}
	if _, err := wait.WaitForState(); err != nil {<commit_msg>providers/aws: not an error if route53 record is already destroy [GH-342]<commit_after>package aws

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

	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/route53"
)

func resource_aws_r53_record_validation() *config.Validator {
	return &config.Validator{
		Required: []string{
			"zone_id",
			"name",
			"type",
			"ttl",
			"records.*",
		},
	}
}

func resource_aws_r53_record_create(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	conn := p.route53

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

	// Get the record
	rec, err := resource_aws_r53_build_record_set(rs)
	if err != nil {
		return rs, err
	}

	// Create the new records. We abuse StateChangeConf for this to
	// retry for us since Route53 sometimes returns errors about another
	// operation happening at the same time.
	req := &route53.ChangeResourceRecordSetsRequest{
		Comment: "Managed by Terraform",
		Changes: []route53.Change{
			route53.Change{
				Action: "UPSERT",
				Record: *rec,
			},
		},
	}
	zone := rs.Attributes["zone_id"]
	log.Printf("[DEBUG] Creating resource records for zone: %s, name: %s",
		zone, rs.Attributes["name"])
	wait := resource.StateChangeConf{
		Pending:    []string{"rejected"},
		Target:     "accepted",
		Timeout:    5 * time.Minute,
		MinTimeout: 1 * time.Second,
		Refresh: func() (interface{}, string, error) {
			resp, err := conn.ChangeResourceRecordSets(zone, req)
			if err != nil {
				if strings.Contains(err.Error(), "PriorRequestNotComplete") {
					// There is some pending operation, so just retry
					// in a bit.
					return nil, "rejected", nil
				}

				return nil, "failure", err
			}

			return resp.ChangeInfo, "accepted", nil
		},
	}
	respRaw, err := wait.WaitForState()
	if err != nil {
		return rs, err
	}
	changeInfo := respRaw.(route53.ChangeInfo)

	// Generate an ID
	rs.ID = fmt.Sprintf("%s_%s_%s", zone, rs.Attributes["name"], rs.Attributes["type"])

	// Wait until we are done
	wait = resource.StateChangeConf{
		Delay:      30 * time.Second,
		Pending:    []string{"PENDING"},
		Target:     "INSYNC",
		Timeout:    10 * time.Minute,
		MinTimeout: 5 * time.Second,
		Refresh: func() (result interface{}, state string, err error) {
			return resource_aws_r53_wait(conn, changeInfo.ID)
		},
	}
	_, err = wait.WaitForState()
	if err != nil {
		return rs, err
	}
	return rs, nil
}

func resource_aws_r53_build_record_set(s *terraform.InstanceState) (*route53.ResourceRecordSet, error) {
	// Parse the TTL
	ttl, err := strconv.ParseInt(s.Attributes["ttl"], 10, 32)
	if err != nil {
		return nil, err
	}

	// Expand the records
	recRaw := flatmap.Expand(s.Attributes, "records")
	var records []string
	for _, raw := range recRaw.([]interface{}) {
		records = append(records, raw.(string))
	}

	rec := &route53.ResourceRecordSet{
		Name:    s.Attributes["name"],
		Type:    s.Attributes["type"],
		TTL:     int(ttl),
		Records: records,
	}
	return rec, nil
}

func resource_aws_r53_record_destroy(
	s *terraform.InstanceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	conn := p.route53

	// Get the record
	rec, err := resource_aws_r53_build_record_set(s)
	if err != nil {
		return err
	}

	// Create the new records
	req := &route53.ChangeResourceRecordSetsRequest{
		Comment: "Deleted by Terraform",
		Changes: []route53.Change{
			route53.Change{
				Action: "DELETE",
				Record: *rec,
			},
		},
	}
	zone := s.Attributes["zone_id"]
	log.Printf("[DEBUG] Deleting resource records for zone: %s, name: %s",
		zone, s.Attributes["name"])
	wait := resource.StateChangeConf{
		Pending:    []string{"rejected"},
		Target:     "accepted",
		Timeout:    5 * time.Minute,
		MinTimeout: 1 * time.Second,
		Refresh: func() (interface{}, string, error) {
			_, err := conn.ChangeResourceRecordSets(zone, req)
			if err != nil {
				if strings.Contains(err.Error(), "PriorRequestNotComplete") {
					// There is some pending operation, so just retry
					// in a bit.
					return 42, "rejected", nil
				}

				if strings.Contains(err.Error(), "InvalidChangeBatch") {
					// This means that the record is already gone.
					return 42, "accepted", nil
				}

				return 42, "failure", err
			}

			return 42, "accepted", nil
		},
	}
	if _, err := wait.WaitForState(); err != nil {
{'fraction_non_alphanumeric': 0.14282558267977466, 'fraction_numerical': 0.013144813873853972, 'mean_word_length': 3.5843037974683543, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4914214', 'n_tokens_mistral': 3460, 'n_tokens_neox': 3116, 'n_words': 795}