Skip to content

feat(registry): new CRD option #5372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ lint: licensecheck go-lint oas-lint
.PHONY: crd
crd: controller-gen-install
${CONTROLLER_GEN} object crd:crdVersions=v1 paths="./endpoint/..."
${CONTROLLER_GEN} object crd:crdVersions=v1 paths="./apis/..." output:crd:stdout > config/crd/standard/dnsendpoint.yaml
cp -f config/crd/standard/dnsendpoint.yaml charts/external-dns/crds/dnsendpoint.yaml
${CONTROLLER_GEN} object crd:crdVersions=v1 paths="./apis/..." output:crd:stdout > config/crd/standard/v1alpha1.yaml
cp -f config/crd/standard/v1alpha1.yaml charts/external-dns/crds/

#? test: The verify target runs tasks similar to the CI tasks, but without code coverage
.PHONY: test
Expand Down
2 changes: 1 addition & 1 deletion apis/v1alpha1/api.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion apis/v1alpha1/dnsendpoint.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
91 changes: 91 additions & 0 deletions apis/v1alpha1/dnsrecord.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"sigs.k8s.io/external-dns/endpoint"
)

const (
RecordOwnerLabel string = "externaldns.k8s.io/owner"
RecordNameLabel string = "externaldns.k8s.io/record-name"
RecordTypeLabel string = "externaldns.k8s.io/record-type"
RecordIdentifierLabel string = "externaldns.k8s.io/identifier"
RecordResourceLabel string = "externaldns.k8s.io/resource"
)

// DNSRecordSpec defines the desired state of DNSEndpoint
// +kubebuilder:object:generate=true
type DNSRecordSpec struct {
Endpoint endpoint.Endpoint `json:"endpoints,omitempty"`
}

// DNSRecordStatus defines the observed state of DNSRecord
// +kubebuilder:object:generate=true
type DNSRecordStatus struct {
// The generation observed by the external-dns controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// DNSRecord is used to get all records managed by external-dns.
// It can be used as a registry with the status subresource.
// +k8s:openapi-gen=true
// +groupName=externaldns.k8s.io
// +kubebuilder:resource:path=dnsrecords
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +versionName=v1alpha1

type DNSRecord struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec DNSRecordSpec `json:"spec,omitempty"`
Status DNSRecordStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// DNSEndpointList is a list of DNSEndpoint objects
type DNSRecordList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []DNSRecord `json:"items"`
}

func (dr DNSRecord) IsEndpoint(e *endpoint.Endpoint) bool {
spec := dr.Spec.Endpoint

return spec.DNSName == strings.ToLower(e.DNSName) &&
spec.RecordType == e.RecordType &&
spec.SetIdentifier == e.SetIdentifier
}

func (dr DNSRecord) EndpointLabels() endpoint.Labels {
labels := endpoint.Labels{}

labels[endpoint.OwnerLabelKey] = dr.Labels[RecordOwnerLabel]
labels[endpoint.ResourceLabelKey] = dr.Labels[RecordResourceLabel]
return labels
}
2 changes: 1 addition & 1 deletion apis/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
90 changes: 90 additions & 0 deletions apis/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 @@ -101,3 +101,100 @@ spec:
storage: true
subresources:
status: {}
---
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CRDs for the Helm chart should be in separate files and be formatted as described in #5479. The following command would be my suggestion to handle multiple CRDs being generated.

${CONTROLLER_GEN} object crd:crdVersions=v1 paths="./apis/..." output:crd:stdout | yamlfmt - | yq eval '.metadata.annotations |= with_entries(select(.key | test("kubernetes\.io")))' --split-exp '"./charts/external-dns/crds/" + .metadata.name + ".yaml"'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed with a rebase.

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: dnsrecords.externaldns.k8s.io
spec:
group: externaldns.k8s.io
names:
kind: DNSRecord
listKind: DNSRecordList
plural: dnsrecords
singular: dnsrecord
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: DNSRecordSpec defines the desired state of DNSEndpoint
properties:
endpoints:
description: Endpoint is a high-level way of a connection between
a service and an IP
properties:
dnsName:
description: The hostname of the DNS record
type: string
labels:
additionalProperties:
type: string
description: Labels stores labels defined for the Endpoint
type: object
providerSpecific:
description: ProviderSpecific stores provider specific config
items:
description: ProviderSpecificProperty holds the name and value
of a configuration which is specific to individual DNS providers
properties:
name:
type: string
value:
type: string
type: object
type: array
recordTTL:
description: TTL for the record
format: int64
type: integer
recordType:
description: RecordType type of record, e.g. CNAME, A, AAAA, SRV,
TXT etc
type: string
setIdentifier:
description: Identifier to distinguish multiple records with the
same name and type (e.g. Route53 records with routing policies
other than 'simple')
type: string
targets:
description: The targets the DNS record points to
items:
type: string
type: array
type: object
type: object
status:
description: DNSRecordStatus defines the observed state of DNSRecord
properties:
observedGeneration:
description: The generation observed by the external-dns controller.
format: int64
type: integer
type: object
type: object
served: true
storage: true
subresources:
status: {}
Loading
Loading