Skip to content

Commit

Permalink
Update loadbalanced routingStrategy CRD validation
Browse files Browse the repository at this point in the history
Update the CRD validations to make the "loadBalancing" field required if
the routingStrategy is "loadbalanced" and make the "defaultWeight" and
"defaultGeo" fields mandatory within the "loadBalancing" section.

Minimum valid specs are now:

Simple:
```
spec:
  targetRef:
    name: prod-web
    group: gateway.networking.k8s.io
    kind: Gateway
  routingStrategy: simple
```

LoadBalanced:
```
spec:
  targetRef:
    name: prod-web
    group: gateway.networking.k8s.io
    kind: Gateway
  routingStrategy: loadbalanced
  loadBalancing:
    geo:
      defaultGeo: foo
    weighted:
      defaultWeight: 100
```
  • Loading branch information
mikenairn committed Apr 25, 2024
1 parent 85e99a8 commit 4d59725
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 192 deletions.
14 changes: 7 additions & 7 deletions api/v1alpha1/dnspolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
)

// DNSPolicySpec defines the desired state of DNSPolicy
// +kubebuilder:validation:XValidation:rule="!(self.routingStrategy == 'loadbalanced' && !has(self.loadBalancing))",message="spec.loadBalancing is a required field when spec.routingStrategy == 'loadbalanced'"
type DNSPolicySpec struct {
// TargetRef identifies an API object to apply policy to.
// +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'",message="Invalid targetRef.group. The only supported value is 'gateway.networking.k8s.io'"
Expand All @@ -63,11 +64,9 @@ type DNSPolicySpec struct {
}

type LoadBalancingSpec struct {
// +optional
Weighted *LoadBalancingWeighted `json:"weighted,omitempty"`
Weighted LoadBalancingWeighted `json:"weighted"`

// +optional
Geo *LoadBalancingGeo `json:"geo,omitempty"`
Geo LoadBalancingGeo `json:"geo"`
}

// +kubebuilder:validation:Minimum=0
Expand All @@ -87,7 +86,6 @@ type LoadBalancingWeighted struct {
// The maximum value accepted is determined by the target dns provider, please refer to the appropriate docs below.
//
// Route53: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html
// +kubebuilder:default=120
DefaultWeight Weight `json:"defaultWeight"`

// custom list of custom weight selectors.
Expand All @@ -111,6 +109,8 @@ type LoadBalancingGeo struct {
// The values accepted are determined by the target dns provider, please refer to the appropriate docs below.
//
// Route53: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-geo.html
// Google: https://cloud.google.com/compute/docs/regions-zones
// +kubebuilder:validation:MinLength=2
DefaultGeo string `json:"defaultGeo"`
}

Expand Down Expand Up @@ -346,15 +346,15 @@ func (p *DNSPolicy) WithLoadBalancingWeighted(lbWeighted LoadBalancingWeighted)
if p.Spec.LoadBalancing == nil {
p.WithLoadBalancing(LoadBalancingSpec{})
}
p.Spec.LoadBalancing.Weighted = &lbWeighted
p.Spec.LoadBalancing.Weighted = lbWeighted
return p
}

func (p *DNSPolicy) WithLoadBalancingGeo(lbGeo LoadBalancingGeo) *DNSPolicy {
if p.Spec.LoadBalancing == nil {
p.Spec.LoadBalancing = &LoadBalancingSpec{}
}
p.Spec.LoadBalancing.Geo = &lbGeo
p.Spec.LoadBalancing.Geo = lbGeo
return p
}

Expand Down
12 changes: 2 additions & 10 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ metadata:
capabilities: Basic Install
categories: Integration & Delivery
containerImage: quay.io/kuadrant/kuadrant-operator:latest
createdAt: "2024-04-22T18:17:29Z"
createdAt: "2024-04-25T14:21:46Z"
operators.operatorframework.io/builder: operator-sdk-v1.32.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
repository: https://github.com/Kuadrant/kuadrant-operator
Expand Down
36 changes: 26 additions & 10 deletions bundle/manifests/kuadrant.io_dnspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,22 @@ spec:
Route53: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-geo.html
Google: https://cloud.google.com/compute/docs/regions-zones
minLength: 2
type: string
required:
- defaultGeo
type: object
weighted:
properties:
custom:
description: custom list of custom weight selectors.
items:
properties:
selector:
description: 'Label selector used by MGC to match resource
storing custom weight attribute values e.g. kuadrant.io/lb-attribute-custom-weight:
AWS'
description: 'Label selector to match resource storing
custom weight attribute values e.g. kuadrant.io/lb-attribute-custom-weight:
AWS.'
properties:
matchExpressions:
description: matchExpressions is a list of label
Expand Down Expand Up @@ -153,14 +158,16 @@ spec:
type: object
x-kubernetes-map-type: atomic
weight:
description: The weight value to apply when the selector
matches.
minimum: 0
type: integer
required:
- selector
- weight
type: object
type: array
defaultWeight:
default: 120
description: |-
defaultWeight is the record weight to use when no other can be determined for a dns target cluster.
Expand All @@ -171,7 +178,12 @@ spec:
Route53: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html
minimum: 0
type: integer
required:
- defaultWeight
type: object
required:
- geo
- weighted
type: object
routingStrategy:
default: loadbalanced
Expand All @@ -183,12 +195,7 @@ spec:
- message: RoutingStrategy is immutable
rule: self == oldSelf
targetRef:
description: |-
PolicyTargetReference identifies an API object to apply a direct or
inherited policy to. This should be used as part of Policy resources
that can target Gateway API resources. For more information on how this
policy attachment model works, and a sample Policy resource, refer to
the policy attachment documentation for Gateway API.
description: TargetRef identifies an API object to apply policy to.
properties:
group:
description: Group is the group of the target resource.
Expand Down Expand Up @@ -221,10 +228,19 @@ spec:
- kind
- name
type: object
x-kubernetes-validations:
- message: Invalid targetRef.group. The only supported value is 'gateway.networking.k8s.io'
rule: self.group == 'gateway.networking.k8s.io'
- message: Invalid targetRef.kind. The only supported values are 'Gateway'
rule: self.kind == 'Gateway'
required:
- routingStrategy
- targetRef
type: object
x-kubernetes-validations:
- message: spec.loadBalancing is a required field when spec.routingStrategy
== 'loadbalanced'
rule: '!(self.routingStrategy == ''loadbalanced'' && !has(self.loadBalancing))'
status:
description: DNSPolicyStatus defines the observed state of DNSPolicy
properties:
Expand Down
12 changes: 6 additions & 6 deletions bundle/manifests/kuadrant.io_tlspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,7 @@ spec:
format: int32
type: integer
targetRef:
description: |-
PolicyTargetReference identifies an API object to apply a direct or
inherited policy to. This should be used as part of Policy resources
that can target Gateway API resources. For more information on how this
policy attachment model works, and a sample Policy resource, refer to
the policy attachment documentation for Gateway API.
description: TargetRef identifies an API object to apply policy to.
properties:
group:
description: Group is the group of the target resource.
Expand Down Expand Up @@ -210,6 +205,11 @@ spec:
- kind
- name
type: object
x-kubernetes-validations:
- message: Invalid targetRef.group. The only supported value is 'gateway.networking.k8s.io'
rule: self.group == 'gateway.networking.k8s.io'
- message: Invalid targetRef.kind. The only supported values are 'Gateway'
rule: self.kind == 'Gateway'
usages:
description: |-
Usages is the set of x509 usages that are requested for the certificate.
Expand Down
10 changes: 9 additions & 1 deletion config/crd/bases/kuadrant.io_dnspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ spec:
Route53: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-geo.html
Google: https://cloud.google.com/compute/docs/regions-zones
minLength: 2
type: string
required:
- defaultGeo
Expand Down Expand Up @@ -165,7 +167,6 @@ spec:
type: object
type: array
defaultWeight:
default: 120
description: |-
defaultWeight is the record weight to use when no other can be determined for a dns target cluster.
Expand All @@ -179,6 +180,9 @@ spec:
required:
- defaultWeight
type: object
required:
- geo
- weighted
type: object
routingStrategy:
default: loadbalanced
Expand Down Expand Up @@ -232,6 +236,10 @@ spec:
- routingStrategy
- targetRef
type: object
x-kubernetes-validations:
- message: spec.loadBalancing is a required field when spec.routingStrategy
== 'loadbalanced'
rule: '!(self.routingStrategy == ''loadbalanced'' && !has(self.loadBalancing))'
status:
description: DNSPolicyStatus defines the observed state of DNSPolicy
properties:
Expand Down
142 changes: 0 additions & 142 deletions controllers/dnspolicy_controller_multi_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,148 +183,6 @@ var _ = Describe("DNSPolicy Multi Cluster", func() {

Context("loadbalanced routing strategy", func() {

Context("weighted", func() {

BeforeEach(func() {
dnsPolicy = v1alpha1.NewDNSPolicy("test-dns-policy", testNamespace).
WithTargetGateway(TestGatewayName).
WithRoutingStrategy(v1alpha1.LoadBalancedRoutingStrategy).
WithLoadBalancingWeightedFor(120, nil)
Expect(k8sClient.Create(ctx, dnsPolicy)).To(Succeed())
})

It("should create dns records", func() {
Eventually(func(g Gomega, ctx context.Context) {
recordList := &kuadrantdnsv1alpha1.DNSRecordList{}
err := k8sClient.List(ctx, recordList, &client.ListOptions{Namespace: testNamespace})
g.Expect(err).NotTo(HaveOccurred())
g.Expect(recordList.Items).To(HaveLen(2))

dnsRecord := &kuadrantdnsv1alpha1.DNSRecord{}
err = k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, dnsRecord)
g.Expect(err).NotTo(HaveOccurred())

wildcardDnsRecord := &kuadrantdnsv1alpha1.DNSRecord{}
err = k8sClient.Get(ctx, client.ObjectKey{Name: wildcardRecordName, Namespace: testNamespace}, wildcardDnsRecord)
g.Expect(err).NotTo(HaveOccurred())

g.Expect(*dnsRecord).To(
MatchFields(IgnoreExtras, Fields{
"ObjectMeta": HaveField("Name", recordName),
"Spec": MatchFields(IgnoreExtras, Fields{
"OwnerID": Equal(&ownerID),
"ManagedZoneRef": HaveField("Name", "mz-example-com"),
"Endpoints": ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"),
"Targets": ConsistOf(TestIPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("default.klb.test.example.com"),
"Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"),
"RecordTTL": Equal(externaldns.TTL(60)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("default.klb.test.example.com"),
"Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"),
"RecordTTL": Equal(externaldns.TTL(60)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"),
"Targets": ConsistOf(TestIPAddressOne),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb.test.example.com"),
"Targets": ConsistOf("default.klb.test.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("default"),
"RecordTTL": Equal(externaldns.TTL(300)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(TestHostOne),
"Targets": ConsistOf("klb.test.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
})),
),
}),
}),
)
g.Expect(*wildcardDnsRecord).To(
MatchFields(IgnoreExtras, Fields{
"ObjectMeta": HaveField("Name", wildcardRecordName),
"Spec": MatchFields(IgnoreExtras, Fields{
"OwnerID": Equal(&ownerID),
"ManagedZoneRef": HaveField("Name", "mz-example-com"),
"Endpoints": ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"),
"Targets": ConsistOf(TestIPAddressTwo),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("default.klb.example.com"),
"Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"),
"RecordTTL": Equal(externaldns.TTL(60)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("default.klb.example.com"),
"Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"),
"RecordTTL": Equal(externaldns.TTL(60)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"),
"Targets": ConsistOf(TestIPAddressOne),
"RecordType": Equal("A"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(60)),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal("klb.example.com"),
"Targets": ConsistOf("default.klb.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal("default"),
"RecordTTL": Equal(externaldns.TTL(300)),
"ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"DNSName": Equal(TestHostWildcard),
"Targets": ConsistOf("klb.example.com"),
"RecordType": Equal("CNAME"),
"SetIdentifier": Equal(""),
"RecordTTL": Equal(externaldns.TTL(300)),
})),
),
}),
}),
)
}, TestTimeoutMedium, TestRetryIntervalMedium, ctx).Should(Succeed())
})

})

Context("geo+weighted", func() {

BeforeEach(func() {
Expand Down
Loading

0 comments on commit 4d59725

Please sign in to comment.