Merge pull request #1378 from justinsb/fix_1374

Fix double initialization of DNSZone
This commit is contained in:
Kris Nova 2017-01-07 08:56:47 -05:00 committed by GitHub
commit 7e34812659
3 changed files with 55 additions and 43 deletions

View File

@ -19,6 +19,7 @@ package model
import ( import (
"k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks" "k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"strings"
) )
// DNSModelBuilder builds DNS related model objects // DNSModelBuilder builds DNS related model objects
@ -29,16 +30,29 @@ type DNSModelBuilder struct {
var _ fi.ModelBuilder = &DNSModelBuilder{} var _ fi.ModelBuilder = &DNSModelBuilder{}
func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error { func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
if b.UsePrivateDNS() { // Add a HostedZone if we are going to publish a dns record that depends on it
// This is only exposed as a feature flag currently if b.UsePrivateDNS() || b.UsesBastionDns() {
// UsePrivateDNS is only exposed as a feature flag currently
// TODO: We may still need a public zone to publish an ELB // TODO: We may still need a public zone to publish an ELB
// Check to see if we are using a bastion DNS record that points to the hosted zone
// If we are, we need to make sure we include the hosted zone as a task
// Configuration for a DNS zone, attached to our VPC // Configuration for a DNS zone, attached to our VPC
dnsZone := &awstasks.DNSZone{ dnsZone := &awstasks.DNSZone{
Name: s(b.Cluster.Spec.DNSZone), Name: s("private-" + b.Cluster.Spec.DNSZone),
Private: fi.Bool(true), Private: fi.Bool(true),
PrivateVPC: b.LinkToVPC(), PrivateVPC: b.LinkToVPC(),
} }
if !strings.Contains(b.Cluster.Spec.DNSZone, ".") {
// Looks like a hosted zone ID
dnsZone.ZoneID = s(b.Cluster.Spec.DNSZone)
} else {
// Looks like a normal ddns name
dnsZone.DNSName = s(b.Cluster.Spec.DNSZone)
}
c.AddTask(dnsZone) c.AddTask(dnsZone)
} else if b.UseLoadBalancerForAPI() { } else if b.UseLoadBalancerForAPI() {
// This will point our DNS to the load balancer, and put the pieces // This will point our DNS to the load balancer, and put the pieces
@ -49,6 +63,15 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
Name: s(b.Cluster.Spec.DNSZone), Name: s(b.Cluster.Spec.DNSZone),
Private: fi.Bool(false), Private: fi.Bool(false),
} }
if !strings.Contains(b.Cluster.Spec.DNSZone, ".") {
// Looks like a hosted zone ID
dnsZone.ZoneID = s(b.Cluster.Spec.DNSZone)
} else {
// Looks like a normal ddns name
dnsZone.DNSName = s(b.Cluster.Spec.DNSZone)
}
c.AddTask(dnsZone) c.AddTask(dnsZone)
} }
@ -65,16 +88,5 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(dnsName) c.AddTask(dnsName)
} }
// Check and see if we are using a bastion DNS record that points to the hosted zone
// If we are, we need to make sure we include the hosted zone as a task
if b.UsesBastionDns() {
dnsZone := &awstasks.DNSZone{
Name: s(b.Cluster.Spec.DNSZone),
Private: fi.Bool(true),
PrivateVPC: b.LinkToVPC(),
}
c.AddTask(dnsZone)
}
return nil return nil
} }

View File

@ -54,7 +54,7 @@ func (e *DNSName) Find(c *fi.Context) (*DNSName, error) {
} }
request := &route53.ListResourceRecordSetsInput{ request := &route53.ListResourceRecordSetsInput{
HostedZoneId: e.Zone.ID, HostedZoneId: e.Zone.ZoneID,
// TODO: Start at correct name? // TODO: Start at correct name?
} }
@ -153,7 +153,7 @@ func (_ *DNSName) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *DNSName) error
changeBatch.Changes = []*route53.Change{change} changeBatch.Changes = []*route53.Change{change}
request := &route53.ChangeResourceRecordSetsInput{} request := &route53.ChangeResourceRecordSetsInput{}
request.HostedZoneId = e.Zone.ID request.HostedZoneId = e.Zone.ZoneID
request.ChangeBatch = changeBatch request.ChangeBatch = changeBatch
glog.V(2).Infof("Updating DNS record %q", *e.Name) glog.V(2).Infof("Updating DNS record %q", *e.Name)

View File

@ -33,8 +33,9 @@ import (
//go:generate fitask -type=DNSZone //go:generate fitask -type=DNSZone
type DNSZone struct { type DNSZone struct {
Name *string Name *string
ID *string DNSName *string
ZoneID *string
Private *bool Private *bool
PrivateVPC *VPC PrivateVPC *VPC
@ -60,7 +61,10 @@ func (e *DNSZone) Find(c *fi.Context) (*DNSZone, error) {
actual := &DNSZone{} actual := &DNSZone{}
actual.Name = e.Name actual.Name = e.Name
actual.ID = z.HostedZone.Id if z.HostedZone.Name != nil {
actual.DNSName = fi.String(strings.TrimSuffix(*z.HostedZone.Name, "."))
}
actual.ZoneID = z.HostedZone.Id
actual.Private = z.HostedZone.Config.PrivateZone actual.Private = z.HostedZone.Config.PrivateZone
// If the zone is private, but we don't want it to be, that will be an error // If the zone is private, but we don't want it to be, that will be an error
@ -77,8 +81,11 @@ func (e *DNSZone) Find(c *fi.Context) (*DNSZone, error) {
} }
} }
if e.ID == nil { if e.ZoneID == nil {
e.ID = actual.ID e.ZoneID = actual.ZoneID
}
if e.DNSName == nil {
e.DNSName = actual.DNSName
} }
return actual, nil return actual, nil
@ -86,24 +93,15 @@ func (e *DNSZone) Find(c *fi.Context) (*DNSZone, error) {
func (e *DNSZone) findExisting(cloud awsup.AWSCloud) (*route53.GetHostedZoneOutput, error) { func (e *DNSZone) findExisting(cloud awsup.AWSCloud) (*route53.GetHostedZoneOutput, error) {
findID := "" findID := ""
if e.ID != nil { if e.ZoneID != nil {
findID = *e.ID
} else if e.Name != nil && !strings.Contains(*e.Name, ".") {
// Looks like a hosted zone ID
findID = *e.Name
}
if findID != "" {
request := &route53.GetHostedZoneInput{ request := &route53.GetHostedZoneInput{
Id: aws.String(findID), Id: e.ZoneID,
} }
response, err := cloud.Route53().GetHostedZone(request) response, err := cloud.Route53().GetHostedZone(request)
if err != nil { if err != nil {
if awsup.AWSErrorCode(err) == "NoSuchHostedZone" { if awsup.AWSErrorCode(err) == "NoSuchHostedZone" {
if e.ID != nil { return nil, nil
return nil, nil
}
// Otherwise continue ... maybe the name was not an id after all...
} else { } else {
return nil, fmt.Errorf("error fetching DNS HostedZone %q: %v", findID, err) return nil, fmt.Errorf("error fetching DNS HostedZone %q: %v", findID, err)
} }
@ -112,7 +110,7 @@ func (e *DNSZone) findExisting(cloud awsup.AWSCloud) (*route53.GetHostedZoneOutp
} }
} }
findName := fi.StringValue(e.Name) findName := fi.StringValue(e.DNSName)
if findName == "" { if findName == "" {
return nil, nil return nil, nil
} }
@ -165,10 +163,10 @@ func (s *DNSZone) CheckChanges(a, e, changes *DNSZone) error {
} }
func (_ *DNSZone) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *DNSZone) error { func (_ *DNSZone) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *DNSZone) error {
name := aws.StringValue(e.Name) name := aws.StringValue(e.DNSName)
if a == nil { if a == nil {
request := &route53.CreateHostedZoneInput{} request := &route53.CreateHostedZoneInput{}
request.Name = e.Name request.Name = e.DNSName
nonce := rand.Int63() nonce := rand.Int63()
request.CallerReference = aws.String(strconv.FormatInt(nonce, 10)) request.CallerReference = aws.String(strconv.FormatInt(nonce, 10))
@ -186,11 +184,11 @@ func (_ *DNSZone) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *DNSZone) error
return fmt.Errorf("error creating DNS HostedZone %q: %v", name, err) return fmt.Errorf("error creating DNS HostedZone %q: %v", name, err)
} }
e.ID = response.HostedZone.Id e.ZoneID = response.HostedZone.Id
} else { } else {
if changes.PrivateVPC != nil { if changes.PrivateVPC != nil {
request := &route53.AssociateVPCWithHostedZoneInput{ request := &route53.AssociateVPCWithHostedZoneInput{
HostedZoneId: a.ID, HostedZoneId: a.ZoneID,
VPC: &route53.VPC{ VPC: &route53.VPC{
VPCId: e.PrivateVPC.ID, VPCId: e.PrivateVPC.ID,
VPCRegion: aws.String(t.Cloud.Region()), VPCRegion: aws.String(t.Cloud.Region()),
@ -227,10 +225,12 @@ type terraformRoute53Zone struct {
func (_ *DNSZone) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *DNSZone) error { func (_ *DNSZone) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *DNSZone) error {
cloud := t.Cloud.(awsup.AWSCloud) cloud := t.Cloud.(awsup.AWSCloud)
dnsName := fi.StringValue(e.DNSName)
// As a special case, we check for an existing zone // As a special case, we check for an existing zone
// It is really painful to have TF create a new one... // It is really painful to have TF create a new one...
// (you have to reconfigure the DNS NS records) // (you have to reconfigure the DNS NS records)
glog.Infof("Check for existing route53 zone to re-use with name %q", *e.Name) glog.Infof("Check for existing route53 zone to re-use with name %q", dnsName)
z, err := e.findExisting(cloud) z, err := e.findExisting(cloud)
if err != nil { if err != nil {
return err return err
@ -239,7 +239,7 @@ func (_ *DNSZone) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *D
if z != nil { if z != nil {
glog.Infof("Existing zone %q found; will configure TF to reuse", aws.StringValue(z.HostedZone.Name)) glog.Infof("Existing zone %q found; will configure TF to reuse", aws.StringValue(z.HostedZone.Name))
e.ID = z.HostedZone.Id e.ZoneID = z.HostedZone.Id
} }
if z == nil { if z == nil {
@ -271,9 +271,9 @@ func (_ *DNSZone) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *D
} }
func (e *DNSZone) TerraformLink() *terraform.Literal { func (e *DNSZone) TerraformLink() *terraform.Literal {
if e.ID != nil { if e.ZoneID != nil {
glog.V(4).Infof("reusing existing route53 zone with id %q", *e.ID) glog.V(4).Infof("reusing existing route53 zone with id %q", *e.ZoneID)
return terraform.LiteralFromStringValue(*e.ID) return terraform.LiteralFromStringValue(*e.ZoneID)
} }
return terraform.LiteralSelfLink("aws_route53_zone", *e.Name) return terraform.LiteralSelfLink("aws_route53_zone", *e.Name)