func createRoute53Delete(r53Api *route53.Route53, s serviceStatus) (*route53.ChangeResourceRecordSetsInput, error) {
	domainParts := strings.Split(s.dnsName, ".")
	segments := len(domainParts)
	tld := strings.Join(domainParts[segments-2:], ".")
	subdomain := strings.Join(domainParts[:segments-2], ".")

	listHostedZoneInput := route53.ListHostedZonesByNameInput{
		DNSName: &tld,
	}
	hzOut, err := r53Api.ListHostedZonesByName(&listHostedZoneInput)
	if err != nil {
		glog.Warningf("No zone found for %s: %v", tld, err)
		return nil, err
	}
	zones := hzOut.HostedZones
	if len(zones) < 1 {
		glog.Warningf("No zone found for %s", tld)
		return nil, err
	}
	// The AWS API may return more than one zone, the first zone should be the relevant one
	tldWithDot := fmt.Sprint(tld, ".")
	if *zones[0].Name != tldWithDot {
		glog.Warningf("Zone found %s does not match tld given %s", *zones[0].Name, tld)
		return nil, err
	}
	zoneId := *zones[0].ID
	zoneParts := strings.Split(zoneId, "/")
	zoneId = zoneParts[len(zoneParts)-1]

	at := route53.AliasTarget{
		DNSName:              &s.lb.Hostname,
		EvaluateTargetHealth: aws.Boolean(false),
		HostedZoneID:         &s.hzId,
	}
	rrs := route53.ResourceRecordSet{
		AliasTarget: &at,
		Name:        &s.dnsName,
		Type:        aws.String("A"),
	}
	change := route53.Change{
		Action:            aws.String("DELETE"),
		ResourceRecordSet: &rrs,
	}
	batch := route53.ChangeBatch{
		Changes: []*route53.Change{&change},
		Comment: aws.String("Kubernetes Update to Service"),
	}
	crrsInput := route53.ChangeResourceRecordSetsInput{
		ChangeBatch:  &batch,
		HostedZoneID: &zoneId,
	}
	glog.Infof("Created dns delete record set: tld=%s, subdomain=%s, zoneId=%s", tld, subdomain, zoneId)

	return &crrsInput, nil
}
Exemple #2
0
func getHostedZone(service *route53.Route53, domain string) (*route53.HostedZone, error) {
	params := &route53.ListHostedZonesByNameInput{
		DNSName:  aws.String(domain),
		MaxItems: aws.String("1"),
	}
	resp, err := service.ListHostedZonesByName(params)
	if err != nil {
		return nil, err
	}

	zone := resp.HostedZones[0]
	return zone, nil
}
Exemple #3
0
func getHostedZoneID(fqdn string, client *route53.Route53) (string, error) {
	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
	if err != nil {
		return "", err
	}

	// .DNSName should not have a trailing dot
	reqParams := &route53.ListHostedZonesByNameInput{
		DNSName: aws.String(acme.UnFqdn(authZone)),
	}
	resp, err := client.ListHostedZonesByName(reqParams)
	if err != nil {
		return "", err
	}

	var hostedZoneID string
	for _, hostedZone := range resp.HostedZones {
		// .Name has a trailing dot
		if !*hostedZone.Config.PrivateZone && *hostedZone.Name == authZone {
			hostedZoneID = *hostedZone.Id
			break
		}
	}

	if len(hostedZoneID) == 0 {
		return "", fmt.Errorf("Zone %s not found in Route 53 for domain %s", authZone, fqdn)
	}

	if strings.HasPrefix(hostedZoneID, "/hostedzone/") {
		hostedZoneID = strings.TrimPrefix(hostedZoneID, "/hostedzone/")
	}

	return hostedZoneID, nil
}
func upsertRecordOnRoute53(ipAddress string, fqdn string, svc *route53.Route53, verbose bool) {
	// Extract the domain from the fully qualified domain name
	r, _ := regexp.Compile("^([^\x2E]*)\x2E(.*)$")
	toks := r.FindStringSubmatch(fqdn)
	domain := toks[2]

	// http://docs.aws.amazon.com/sdk-for-go/api/service/route53/Route53.html#ListHostedZonesByName-instance_method
	resources, err := svc.ListHostedZonesByName(&route53.ListHostedZonesByNameInput{
		DNSName:  aws.String(domain + "."),
		MaxItems: aws.String("1"),
	})

	if err != nil {
		fmt.Println("ERR: err.Error()", err)
		os.Exit(1)
	}
	if len(resources.HostedZones) != 1 {
		fmt.Printf("ERR: Could not find the domain %s\n", domain)
		os.Exit(1)
	}
	if *resources.DNSName != domain+"." {
		fmt.Printf("ERR: Could not find the domain %s - %s \n", domain, *resources.DNSName)
		os.Exit(1)
	}

	zoneIDToks := strings.Split(*resources.HostedZones[0].Id, "/")
	zoneID := zoneIDToks[len(zoneIDToks)-1]

	resp, err := svc.ListResourceRecordSets(&route53.ListResourceRecordSetsInput{
		StartRecordName: aws.String(fqdn),
		StartRecordType: aws.String("A"),
		HostedZoneId:    aws.String(zoneID),
		MaxItems:        aws.String("1"),
	})
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	var foundResource bool
	if len(resp.ResourceRecordSets) != 1 {
		foundResource = false
	} else {
		foundResource = *resp.ResourceRecordSets[0].Name == fqdn+"."
		if foundResource {
			for _, record := range resp.ResourceRecordSets[0].ResourceRecords {
				if *record.Value == ipAddress {
					if verbose {
						fmt.Printf("INFO: %s already registered in route53 as %s\n", ipAddress, fqdn)
					}
					return
				}
			}
		}
	}
	// Make an A-record:
	resourceRecordSet := &route53.ResourceRecordSet{
		Name: aws.String(fqdn + "."),
		Type: aws.String("A"),
		ResourceRecords: []*route53.ResourceRecord{
			&route53.ResourceRecord{
				Value: aws.String(ipAddress),
			},
		},
		TTL: aws.Int64(300),
	}

	// Wrap it as an UPSERT
	upsert := []*route53.Change{&route53.Change{
		Action:            aws.String("UPSERT"),
		ResourceRecordSet: resourceRecordSet,
	}}

	// Put it into a pretty envelope with a stamp for route53#zoneId and change ticket
	params := route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: upsert,
		},
		HostedZoneId: aws.String(zoneID),
	}

	// Post it
	changeResp, err := svc.ChangeResourceRecordSets(&params)

	if err != nil {
		fmt.Println("ERR: ", err.Error(), changeResp)
		os.Exit(1)
	}

	// Done
	if verbose {
		fmt.Printf("INFO: Submitted change for zoneId %s to register %s as %s\n", zoneID, ipAddress, fqdn)
	}
}
func createRoute53Upsert(r53Api *route53.Route53, elbApi *elb.ELB, domain string, hn string) (*route53.ChangeResourceRecordSetsInput, error) {
	domainParts := strings.Split(domain, ".")
	segments := len(domainParts)
	tld := strings.Join(domainParts[segments-2:], ".")
	//	subdomain := strings.Join(domainParts[:segments-2], ".")

	elbName := strings.Split(hn, "-")[0]
	lbInput := &elb.DescribeLoadBalancersInput{
		LoadBalancerNames: []*string{
			&elbName,
		},
	}
	resp, err := elbApi.DescribeLoadBalancers(lbInput)
	if err != nil {
		glog.Warningf("Could not describe load balancer: %v", err)
		return nil, err
	}
	descs := resp.LoadBalancerDescriptions
	if len(descs) < 1 {
		glog.Warningf("No lb found for %s: %v", tld, err)
		return nil, err
	}
	if len(descs) > 1 {
		glog.Warningf("Multiple lbs found for %s: %v", tld, err)
		return nil, err
	}
	hzId := descs[0].CanonicalHostedZoneNameID

	listHostedZoneInput := route53.ListHostedZonesByNameInput{
		DNSName: &tld,
	}
	hzOut, err := r53Api.ListHostedZonesByName(&listHostedZoneInput)
	if err != nil {
		glog.Warningf("No zone found for %s: %v", tld, err)
		return nil, err
	}
	zones := hzOut.HostedZones
	if len(zones) < 1 {
		glog.Warningf("No zone found for %s", tld)
		return nil, err
	}
	// The AWS API may return more than one zone, the first zone should be the relevant one
	tldWithDot := fmt.Sprint(tld, ".")
	if *zones[0].Name != tldWithDot {
		glog.Warningf("Zone found %s does not match tld given %s", *zones[0].Name, tld)
		return nil, err
	}
	zoneId := *zones[0].ID
	zoneParts := strings.Split(zoneId, "/")
	zoneId = zoneParts[len(zoneParts)-1]

	at := route53.AliasTarget{
		DNSName:              &hn,
		EvaluateTargetHealth: aws.Boolean(false),
		HostedZoneID:         hzId,
	}
	rrs := route53.ResourceRecordSet{
		AliasTarget: &at,
		Name:        &domain,
		Type:        aws.String("A"),
	}
	change := route53.Change{
		Action:            aws.String("UPSERT"),
		ResourceRecordSet: &rrs,
	}
	batch := route53.ChangeBatch{
		Changes: []*route53.Change{&change},
		Comment: aws.String("Kubernetes Update to Service"),
	}
	crrsInput := route53.ChangeResourceRecordSetsInput{
		ChangeBatch:  &batch,
		HostedZoneID: &zoneId,
	}
	//glog.Infof("Created dns record set: tld=%s, subdomain=%s, zoneId=%s", tld, subdomain, zoneId)

	return &crrsInput, nil
}