Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bundle/manifests/devportal.kuadrant.io_apiproducts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2663,6 +2663,10 @@ spec:
updated.
format: date-time
type: string
maxSizeUsed:
description: maxSizeUsed is the max size limit that was in effect
when this spec was fetched.
type: integer
raw:
description: raw content
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ metadata:
categories: Integration & Delivery
console.openshift.io/plugins: '["kuadrant-console-plugin"]'
containerImage: quay.io/kuadrant/kuadrant-operator:latest
createdAt: "2026-01-16T11:30:09Z"
createdAt: "2026-01-21T11:20:16Z"
description: A Kubernetes Operator to manage the lifecycle of the Kuadrant system
operators.operatorframework.io/builder: operator-sdk-v1.33.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
Expand Down
3 changes: 2 additions & 1 deletion bundle/manifests/kuadrant.io_dnspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ spec:
failureThreshold:
default: 5
description: |-
FailureThreshold is a limit of consecutive failures that must occur for a host to be considered unhealthy
FailureThreshold is the number of consecutive failures that must be exceeded for a host to be considered unhealthy.
When the number of consecutive failures exceeds this threshold, the health check will be marked as unhealthy.
Defaults to 5
type: integer
x-kubernetes-validations:
Expand Down
7 changes: 6 additions & 1 deletion charts/kuadrant-operator/templates/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2998,6 +2998,10 @@ spec:
updated.
format: date-time
type: string
maxSizeUsed:
description: maxSizeUsed is the max size limit that was in effect
when this spec was fetched.
type: integer
raw:
description: raw content
type: string
Expand Down Expand Up @@ -10717,7 +10721,8 @@ spec:
failureThreshold:
default: 5
description: |-
FailureThreshold is a limit of consecutive failures that must occur for a host to be considered unhealthy
FailureThreshold is the number of consecutive failures that must be exceeded for a host to be considered unhealthy.
When the number of consecutive failures exceeds this threshold, the health check will be marked as unhealthy.
Defaults to 5
type: integer
x-kubernetes-validations:
Expand Down
3 changes: 2 additions & 1 deletion config/crd/bases/kuadrant.io_dnspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ spec:
failureThreshold:
default: 5
description: |-
FailureThreshold is a limit of consecutive failures that must occur for a host to be considered unhealthy
FailureThreshold is the number of consecutive failures that must be exceeded for a host to be considered unhealthy.
When the number of consecutive failures exceeds this threshold, the health check will be marked as unhealthy.
Defaults to 5
type: integer
x-kubernetes-validations:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
github.com/google/go-cmp v0.7.0
github.com/kuadrant/authorino v0.22.0
github.com/kuadrant/authorino-operator v0.21.0
github.com/kuadrant/dns-operator v0.0.0-20250826105007-7a0e6d88f7bb
github.com/kuadrant/dns-operator v0.0.0-20251125201831-f74008dc171c
github.com/kuadrant/limitador-operator v0.15.0
github.com/kuadrant/policy-machinery v0.7.1-0.20251119154946-1ca17a075dd2
github.com/martinlindhe/base36 v1.1.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ github.com/kuadrant/authorino-operator v0.21.0 h1:wjb0lAF7ZzP8Rgc7rbJkGf+1PL2StS
github.com/kuadrant/authorino-operator v0.21.0/go.mod h1:elsjAwIFdLDDu9ljq5S28LJIekhtVqeCA7AlaqPTL3U=
github.com/kuadrant/dns-operator v0.0.0-20250826105007-7a0e6d88f7bb h1:YTWt8bn7xi5T7XJ9+MlrMDnWk5d8AVMVWVePvHkvR9k=
github.com/kuadrant/dns-operator v0.0.0-20250826105007-7a0e6d88f7bb/go.mod h1:EF37SlMqbarJieimWDPRv/N5BACbdzLa9nCBJcoeFvs=
github.com/kuadrant/dns-operator v0.0.0-20251125201831-f74008dc171c h1:4FXlQ+zZEtdbc0Wa2E/2fsa0V/myvIcoxoGgVRRHH5Q=
github.com/kuadrant/dns-operator v0.0.0-20251125201831-f74008dc171c/go.mod h1:QgQK9JsmEkmaH+en2u2r1oXlbLcgvB+1qRnzilYKExI=
github.com/kuadrant/limitador-operator v0.15.0 h1:BWgYKV0iasFY3+zKQhLpTdfIlI2pD4MuGr8Hc30ypfg=
github.com/kuadrant/limitador-operator v0.15.0/go.mod h1:58b5gdSemjXUijd2TBPKBwaQskU7rynHGHD7rTqk2OE=
github.com/kuadrant/policy-machinery v0.7.1-0.20251119154946-1ca17a075dd2 h1:82Qf4klsgQ/176P8PoDbno8Jlik/WPg4j2l3pp1nKG8=
Expand Down
27 changes: 23 additions & 4 deletions internal/controller/dnspolicy_dnsrecords.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/env"
externaldns "sigs.k8s.io/external-dns/endpoint"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"

Expand All @@ -19,11 +20,27 @@ const (
LabelListenerReference = "kuadrant.io/listener-name"
)

func dnsPolicyDefaultTTL() (int, error) {
ttl, err := env.GetInt("DNS_DEFAULT_TTL", builder.DefaultTTL)
if err != nil {
return ttl, fmt.Errorf("DNS_DEFAULT_TTL env value could not be parsed as int, default %d will be used: %w", builder.DefaultTTL, err)
}
return ttl, nil
}

func dnsPolicyDefaultCnameTTL() (int, error) {
ttl, err := env.GetInt("DNS_DEFAULT_LB_TTL", builder.DefaultLoadBalancedTTL)
if err != nil {
return ttl, fmt.Errorf("DNS_DEFAULT_LB_TTL env value could not be parsed as int, default %d will be used: %w", builder.DefaultLoadBalancedTTL, err)
}
return ttl, nil
}

func dnsRecordName(gatewayName, listenerName string) string {
return fmt.Sprintf("%s-%s", gatewayName, listenerName)
}

func desiredDNSRecord(gateway *gatewayapiv1.Gateway, clusterID string, dnsPolicy *kuadrantv1.DNSPolicy, targetListener gatewayapiv1.Listener) (*kuadrantdnsv1alpha1.DNSRecord, error) {
func desiredDNSRecord(gateway *gatewayapiv1.Gateway, clusterID string, dnsPolicy *kuadrantv1.DNSPolicy, targetListener gatewayapiv1.Listener, defaultTTL int, defaultLoadBalancedTTL int) (*kuadrantdnsv1alpha1.DNSRecord, error) {
rootHost := string(*targetListener.Hostname)
var healthCheckSpec *kuadrantdnsv1alpha1.HealthCheckSpec

Expand Down Expand Up @@ -65,7 +82,7 @@ func desiredDNSRecord(gateway *gatewayapiv1.Gateway, clusterID string, dnsPolicy

dnsRecord.Labels[LabelListenerReference] = string(targetListener.Name)

endpoints, err := buildEndpoints(clusterID, string(*targetListener.Hostname), gateway, dnsPolicy)
endpoints, err := buildEndpoints(clusterID, string(*targetListener.Hostname), gateway, dnsPolicy, defaultTTL, defaultLoadBalancedTTL)
if err != nil {
return nil, fmt.Errorf("failed to generate dns record for a gateway %s in %s ns: %w", gateway.Name, gateway.Namespace, err)
}
Expand Down Expand Up @@ -127,14 +144,16 @@ func (g *GatewayWrapper) RemoveExcludedStatusAddresses(p *kuadrantv1.DNSPolicy)
return nil
}

func buildEndpoints(clusterID, hostname string, gateway *gatewayapiv1.Gateway, policy *kuadrantv1.DNSPolicy) ([]*externaldns.Endpoint, error) {
func buildEndpoints(clusterID, hostname string, gateway *gatewayapiv1.Gateway, policy *kuadrantv1.DNSPolicy, defaultTTL int, defaultLoadBalancedTTL int) ([]*externaldns.Endpoint, error) {
gw := gateway.DeepCopy()
gatewayWrapper := NewGatewayWrapper(gw)
// modify the status addresses based on any that need to be excluded
if err := gatewayWrapper.RemoveExcludedStatusAddresses(policy); err != nil {
return nil, fmt.Errorf("failed to reconcile gateway dns records error: %w ", err)
}
endpointBuilder := builder.NewEndpointsBuilder(gatewayWrapper, hostname)
endpointBuilder := builder.NewEndpointsBuilder(gatewayWrapper, hostname).
SetDefaultTTL(defaultTTL).
SetDefaultLoadBalancedTTL(defaultLoadBalancedTTL)

if policy.Spec.LoadBalancing != nil {
endpointBuilder.WithLoadBalancingFor(
Expand Down
11 changes: 10 additions & 1 deletion internal/controller/effective_dnspolicies_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func (r *EffectiveDNSPoliciesReconciler) reconcile(ctx context.Context, _ []cont
return fmt.Errorf("failed to generate cluster ID: %w", err)
}

defaultTTL, err := dnsPolicyDefaultTTL()
if err != nil {
logger.Error(err, err.Error())
}
defaultLoadBalancedTTL, err := dnsPolicyDefaultCnameTTL()
if err != nil {
logger.Error(err, err.Error())
}

for _, policy := range policies {
_, span := tracer.Start(ctx, "policy.DNSPolicy.effective")
span.SetAttributes(
Expand Down Expand Up @@ -133,7 +142,7 @@ func (r *EffectiveDNSPoliciesReconciler) reconcile(ctx context.Context, _ []cont
gatewayHasAttachedRoutes = true
}

desiredRecord, err := desiredDNSRecord(gateway.Gateway, clusterID, policy, *listener.Listener)
desiredRecord, err := desiredDNSRecord(gateway.Gateway, clusterID, policy, *listener.Listener, defaultTTL, defaultLoadBalancedTTL)
if err != nil {
lLogger.Error(err, "failed to build desired dns record")
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"

kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1"
kuadrantdnsbuilder "github.com/kuadrant/dns-operator/pkg/builder"

kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1"
"github.com/kuadrant/kuadrant-operator/internal/utils"
Expand Down Expand Up @@ -185,7 +186,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ContainElements(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
))
g.Expect(dnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand All @@ -200,7 +201,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ContainElements(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
))
g.Expect(wildcardDnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand Down Expand Up @@ -245,38 +246,38 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ConsistOf(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("ie.klb.test." + domain),
"Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb.test." + domain),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb.test." + domain),
"Targets": ConsistOf("ie.klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("IE"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb.test." + domain),
"Targets": ConsistOf("ie.klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("default"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(tests.HostOne(domain)),
"Targets": ConsistOf("klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
})),
))
g.Expect(dnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand All @@ -291,38 +292,38 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ConsistOf(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("ie.klb." + domain),
"Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb." + domain),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb." + domain),
"Targets": ConsistOf("ie.klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("default"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb." + domain),
"Targets": ConsistOf("ie.klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("IE"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(tests.HostWildcard(domain)),
"Targets": ConsistOf("klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
})),
))
g.Expect(wildcardDnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand Down Expand Up @@ -365,30 +366,30 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ConsistOf(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("ie.klb.test." + domain),
"Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb.test." + domain),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb.test." + domain),
"Targets": ConsistOf("ie.klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("IE"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(tests.HostOne(domain)),
"Targets": ConsistOf("klb.test." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
})),
))
g.Expect(dnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand All @@ -403,30 +404,30 @@ var _ = Describe("DNSPolicy Single Cluster", func() {
"Targets": ConsistOf(tests.IPAddressOne, tests.IPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("ie.klb." + domain),
"Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb." + domain),
"RecordTTL": Equal(externaldns.TTL(60)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb." + domain),
"Targets": ConsistOf("ie.klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("IE"),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(tests.HostWildcard(domain)),
"Targets": ConsistOf("klb." + domain),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
"RecordTTL": Equal(externaldns.TTL(kuadrantdnsbuilder.DefaultLoadBalancedTTL)),
})),
))
g.Expect(wildcardDnsRecord.Status.OwnerID).ToNot(BeEmpty())
Expand Down
Loading
Loading