Skip to content

Commit

Permalink
GH-110 use CRD validation
Browse files Browse the repository at this point in the history
  • Loading branch information
maksymvavilov committed Jun 7, 2024
1 parent 82a6451 commit 004b467
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 132 deletions.
38 changes: 5 additions & 33 deletions api/v1alpha1/dnsrecord_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ limitations under the License.
package v1alpha1

import (
"fmt"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
externaldns "sigs.k8s.io/external-dns/endpoint"
)
Expand Down Expand Up @@ -53,6 +50,8 @@ type HealthCheckStatusProbe struct {
}

// DNSRecordSpec defines the desired state of DNSRecord
// +kubebuilder:validation:XValidation:rule="has(self.endpoints) ? self.endpoints.all(ep, ep.dnsName.endsWith(self.rootHost.replace(\"*.\",\"\"))) : true",message="All endpoints should be equal to or end with the rootHost"
// +kubebuilder:validation:XValidation:rule="has(self.endpoints) ? self.endpoints.exists(ep, ep.dnsName == self.rootHost) : true",message="No endpoint defining a record for the rootHost"
type DNSRecordSpec struct {
// ownerID is a unique string used to identify the owner of this record.
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="OwnerID is immutable"
Expand All @@ -62,14 +61,16 @@ type DNSRecordSpec struct {

// rootHost is the single root for all endpoints in a DNSRecord.
// it is expected all defined endpoints are children of or equal to this rootHost
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=255
// +kubebuilder:validation:Pattern="^.*\\..*$"
RootHost string `json:"rootHost"`

// managedZone is a reference to a ManagedZone instance to which this record will publish its endpoints.
ManagedZoneRef *ManagedZoneReference `json:"managedZone"`

// endpoints is a list of endpoints that will be published into the dns provider.
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=250
// +optional
Endpoints []*externaldns.Endpoint `json:"endpoints,omitempty"`

Expand Down Expand Up @@ -161,35 +162,6 @@ const (

const WildcardPrefix = "*."

func (s *DNSRecord) Validate() error {
root := s.Spec.RootHost
if len(strings.Split(root, ".")) <= 1 {
return fmt.Errorf("invalid domain format no tld discovered")
}
if len(s.Spec.Endpoints) == 0 {
return fmt.Errorf("no endpoints defined for DNSRecord. Nothing to do")
}

root, _ = strings.CutPrefix(root, WildcardPrefix)

rootEndpointFound := false
for _, ep := range s.Spec.Endpoints {
if !strings.HasSuffix(ep.DNSName, root) {
return fmt.Errorf("invalid endpoint discovered %s all endpoints should be equal to or end with the rootHost %s", ep.DNSName, root)
}
if !rootEndpointFound {
//check original root
if ep.DNSName == s.Spec.RootHost {
rootEndpointFound = true
}
}
}
if !rootEndpointFound {
return fmt.Errorf("invalid endpoint set. rootHost is set but found no endpoint defining a record for the rootHost %s", root)
}
return nil
}

func init() {
SchemeBuilder.Register(&DNSRecord{}, &DNSRecordList{})
}
89 changes: 0 additions & 89 deletions api/v1alpha1/dnsrecord_types_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion bundle/manifests/dns-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ metadata:
capabilities: Basic Install
categories: Integration & Delivery
containerImage: quay.io/kuadrant/dns-operator:latest
createdAt: "2024-05-10T10:23:31Z"
createdAt: "2024-06-07T11:00:59Z"
description: A Kubernetes Operator to manage the lifecycle of DNS resources
operators.operatorframework.io/builder: operator-sdk-v1.33.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
Expand Down
11 changes: 10 additions & 1 deletion bundle/manifests/kuadrant.io_dnsrecords.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ spec:
type: string
type: array
type: object
maxItems: 250
minItems: 1
type: array
healthCheck:
Expand Down Expand Up @@ -132,13 +133,21 @@ spec:
description: |-
rootHost is the single root for all endpoints in a DNSRecord.
it is expected all defined endpoints are children of or equal to this rootHost
minLength: 1
maxLength: 255
pattern: ^.*\..*$
type: string
required:
- managedZone
- ownerID
- rootHost
type: object
x-kubernetes-validations:
- message: All endpoints should be equal to or end with the rootHost
rule: 'has(self.endpoints) ? self.endpoints.all(ep, ep.dnsName.endsWith(self.rootHost.replace("*.","")))
: true'
- message: No endpoint defining a record for the rootHost
rule: 'has(self.endpoints) ? self.endpoints.exists(ep, ep.dnsName ==
self.rootHost) : true'
status:
description: DNSRecordStatus defines the observed state of DNSRecord
properties:
Expand Down
11 changes: 10 additions & 1 deletion config/crd/bases/kuadrant.io_dnsrecords.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ spec:
type: string
type: array
type: object
maxItems: 250
minItems: 1
type: array
healthCheck:
Expand Down Expand Up @@ -132,13 +133,21 @@ spec:
description: |-
rootHost is the single root for all endpoints in a DNSRecord.
it is expected all defined endpoints are children of or equal to this rootHost
minLength: 1
maxLength: 255
pattern: ^.*\..*$
type: string
required:
- managedZone
- ownerID
- rootHost
type: object
x-kubernetes-validations:
- message: All endpoints should be equal to or end with the rootHost
rule: 'has(self.endpoints) ? self.endpoints.all(ep, ep.dnsName.endsWith(self.rootHost.replace("*.","")))
: true'
- message: No endpoint defining a record for the rootHost
rule: 'has(self.endpoints) ? self.endpoints.exists(ep, ep.dnsName ==
self.rootHost) : true'
status:
description: DNSRecordStatus defines the observed state of DNSRecord
properties:
Expand Down
7 changes: 0 additions & 7 deletions internal/controller/dnsrecord_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,6 @@ func (r *DNSRecordReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}

var reason, message string
err = dnsRecord.Validate()
if err != nil {
reason = "ValidationError"
message = fmt.Sprintf("validation of DNSRecord failed: %v", err)
setDNSRecordCondition(dnsRecord, string(v1alpha1.ConditionTypeReady), metav1.ConditionFalse, reason, message)
return r.updateStatus(ctx, previous, dnsRecord, false, err)
}

// Publish the record
hadChanges, err := r.publishRecord(ctx, dnsRecord)
Expand Down

0 comments on commit 004b467

Please sign in to comment.