Skip to content

Commit a92ea3c

Browse files
committed
Release v0.2.2
1 parent b247808 commit a92ea3c

5 files changed

Lines changed: 111 additions & 6 deletions

File tree

‎deploy/charts/dns-api/Chart.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ apiVersion: v2
22
name: dns-api
33
description: Kubernetes DNS API controller for Route 53 and Cloudflare
44
type: application
5-
version: 0.2.1
6-
appVersion: "0.2.1"
5+
version: 0.2.2
6+
appVersion: "0.2.2"
77
kubeVersion: ">=1.22.0-0"

‎internal/go/providers/route53/controllers/zoneunit/recordset.go‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,12 @@ func route53RecordSetEqual(a, b RecordSetResource) bool {
686686
if (a.Alias == nil) != (b.Alias == nil) {
687687
return false
688688
}
689-
if a.Alias != nil && b.Alias != nil && *a.Alias != *b.Alias {
690-
return false
689+
if a.Alias != nil && b.Alias != nil {
690+
if normalizeRoute53RecordName(a.Alias.DNSName) != normalizeRoute53RecordName(b.Alias.DNSName) ||
691+
normalizeHostedZoneID(a.Alias.HostedZoneID) != normalizeHostedZoneID(b.Alias.HostedZoneID) ||
692+
a.Alias.EvaluateTargetHealth != b.Alias.EvaluateTargetHealth {
693+
return false
694+
}
691695
}
692696
aValues, ok := canonicalRecordSetValues(a.Type, a.Values)
693697
if !ok {

‎internal/go/providers/route53/controllers/zoneunit/zone_test.go‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,60 @@ func TestZoneReconcilerUpsertsRoute53AliasRecordSet(t *testing.T) {
17451745
}
17461746
}
17471747

1748+
func TestZoneReconcilerAdoptsMatchingRoute53AliasRecordSet(t *testing.T) {
1749+
ctx := context.Background()
1750+
scheme := testScheme(t)
1751+
provider := newFakeProvider()
1752+
provider.zones["Z000001"] = HostedZone{
1753+
ID: "Z000001",
1754+
Name: "apps.example.com",
1755+
CallerReference: "dns-api:11111111-2222-3333-4444-555555555555",
1756+
NameServers: []string{"ns-1.awsdns.example", "ns-2.awsdns.example"},
1757+
}
1758+
provider.records[recordKey("Z000001", "alias.apps.example.com.", dnsv1alpha1.RecordTypeA)] = RecordSetResource{
1759+
HostedZoneID: "Z000001",
1760+
Name: "alias.apps.example.com.",
1761+
Type: dnsv1alpha1.RecordTypeA,
1762+
Alias: &route53v1alpha1.Route53AliasTarget{
1763+
DNSName: "target.apps.example.com",
1764+
HostedZoneID: "/hostedzone/Z000001",
1765+
EvaluateTargetHealth: false,
1766+
},
1767+
}
1768+
recordSet := route53AliasARecordSet("app", "alias")
1769+
recordSet.Spec.Adoption = runtime.RawExtension{Raw: []byte(`{"enabled":true}`)}
1770+
objects := route53RecordSetObjects(t, recordSet)
1771+
k8sClient := fake.NewClientBuilder().
1772+
WithScheme(scheme).
1773+
WithObjects(objects...).
1774+
WithStatusSubresource(&dnsv1alpha1.Zone{}, &dnsv1alpha1.RecordSet{}, &dnsv1alpha1.ZoneClass{}, &route53v1alpha1.Route53Identity{}, &dnsv1alpha1.ZoneUnit{}).
1775+
Build()
1776+
reconciler := &ZoneReconciler{Client: k8sClient, Provider: provider}
1777+
1778+
result, err := reconcileRoute53AndProject(t, ctx, k8sClient, reconciler, ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "app", Name: "apps-example-com"}})
1779+
if err != nil {
1780+
t.Fatalf("Reconcile returned error: %v", err)
1781+
}
1782+
if result.Requeue {
1783+
t.Fatalf("Reconcile result = %#v, want no immediate requeue", result)
1784+
}
1785+
if len(provider.upserted) != 0 {
1786+
t.Fatalf("upserted record sets = %d, want 0", len(provider.upserted))
1787+
}
1788+
1789+
var unit dnsv1alpha1.ZoneUnit
1790+
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "app", Name: "apps-example-com"}, &unit); err != nil {
1791+
t.Fatalf("ZoneUnit was not found: %v", err)
1792+
}
1793+
index := slices.IndexFunc(unit.Status.RecordSets, func(status dnsv1alpha1.ZoneUnitRecordSetStatus) bool {
1794+
return status.RecordSetNamespace == recordSet.Namespace && status.RecordSetName == recordSet.Name
1795+
})
1796+
if index < 0 {
1797+
t.Fatalf("ZoneUnit status.recordSets has no entry for %s/%s: %#v", recordSet.Namespace, recordSet.Name, unit.Status.RecordSets)
1798+
}
1799+
assertCondition(t, unit.Status.RecordSets[index].Conditions, string(dnsv1alpha1.ConditionProgrammed), metav1.ConditionTrue, "Programmed")
1800+
}
1801+
17481802
func TestZoneReconcilerRejectsRecordSetWhenCNAMEZoneUnitItemOwnsSameName(t *testing.T) {
17491803
ctx := context.Background()
17501804
scheme := testScheme(t)

‎internal/go/providers/route53/conversion/alias.go‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ func route53CanonicalHostedZone(hostname string) string {
9696
}
9797

9898
func normalizeRoute53AliasDNSName(hostname string) string {
99-
trimmed := strings.TrimSuffix(hostname, ".")
99+
trimmed := strings.TrimSuffix(strings.ToLower(strings.TrimSpace(hostname)), ".")
100+
if route53CanonicalHostedZone(trimmed) != "" && !strings.HasPrefix(trimmed, "dualstack.") {
101+
trimmed = "dualstack." + trimmed
102+
}
100103
return trimmed + "."
101104
}

‎internal/go/providers/route53/conversion/handler_test.go‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,57 @@ func TestHandlerConvertsELBHostnameToAliasAAndAAAA(t *testing.T) {
6565
t.Fatalf("decode options: %v", err)
6666
}
6767
if options.Alias == nil ||
68-
options.Alias.DNSName != "k8s-public-123456.ap-northeast-1.elb.amazonaws.com." ||
68+
options.Alias.DNSName != "dualstack.k8s-public-123456.ap-northeast-1.elb.amazonaws.com." ||
6969
options.Alias.HostedZoneID != "Z14GRHDCWA56QT" ||
7070
options.Alias.EvaluateTargetHealth {
7171
t.Fatalf("alias = %#v", options.Alias)
7272
}
7373
}
7474

75+
func TestHandlerPreservesExistingELBDualstackAliasPrefix(t *testing.T) {
76+
review := endpointconversionv1alpha1.EndpointRecordSetConversion{
77+
TypeMeta: metav1.TypeMeta{APIVersion: GroupName + "/" + Version, Kind: "EndpointRecordSetConversion"},
78+
Spec: endpointconversionv1alpha1.EndpointRecordSetConversionSpec{
79+
UID: "request-1",
80+
Input: endpointv1alpha1.EndpointRecordSetConversionInput{
81+
Hostname: "api.example.com",
82+
Name: "api",
83+
Zone: endpointv1alpha1.EndpointRecordSetConversionZone{DomainName: "example.com"},
84+
Targets: []endpointv1alpha1.EndpointTarget{{
85+
Type: endpointv1alpha1.EndpointTargetTypeHostname,
86+
Value: "dualstack.k8s-public-123456.ap-northeast-1.elb.amazonaws.com.",
87+
}},
88+
},
89+
},
90+
}
91+
body, err := json.Marshal(review)
92+
if err != nil {
93+
t.Fatalf("marshal review: %v", err)
94+
}
95+
request := httptest.NewRequest(http.MethodPost, "/apis/"+GroupName+"/"+Version+"/"+Resource, bytes.NewReader(body))
96+
response := httptest.NewRecorder()
97+
98+
NewHandler().ServeHTTP(response, request)
99+
100+
if response.Code != http.StatusCreated {
101+
t.Fatalf("status = %d, body = %s", response.Code, response.Body.String())
102+
}
103+
var got endpointconversionv1alpha1.EndpointRecordSetConversion
104+
if err := json.NewDecoder(response.Body).Decode(&got); err != nil {
105+
t.Fatalf("decode response: %v", err)
106+
}
107+
if got.Status.Output == nil || len(got.Status.Output.Fragments) == 0 {
108+
t.Fatalf("fragments = %#v, want output", got.Status.Output)
109+
}
110+
var options route53v1alpha1.Route53RecordSetOptions
111+
if err := json.Unmarshal(got.Status.Output.Fragments[0].Options.Raw, &options); err != nil {
112+
t.Fatalf("decode options: %v", err)
113+
}
114+
if options.Alias == nil || options.Alias.DNSName != "dualstack.k8s-public-123456.ap-northeast-1.elb.amazonaws.com." {
115+
t.Fatalf("alias = %#v", options.Alias)
116+
}
117+
}
118+
75119
func TestHandlerRejectsUnknownHostnameTarget(t *testing.T) {
76120
review := endpointconversionv1alpha1.EndpointRecordSetConversion{
77121
Spec: endpointconversionv1alpha1.EndpointRecordSetConversionSpec{

0 commit comments

Comments
 (0)