Name it and watch with annotations
This commit is contained in:
parent
e5902a49f8
commit
fda3120bd3
5 changed files with 230 additions and 12 deletions
|
|
@ -24,12 +24,58 @@ import (
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *AuthorityEndpoint) DeepCopyInto(out *AuthorityEndpoint) {
|
||||||
|
*out = *in
|
||||||
|
out.APIKeySecretRef = in.APIKeySecretRef
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorityEndpoint.
|
||||||
|
func (in *AuthorityEndpoint) DeepCopy() *AuthorityEndpoint {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(AuthorityEndpoint)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *AuthorityReference) DeepCopyInto(out *AuthorityReference) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorityReference.
|
||||||
|
func (in *AuthorityReference) DeepCopy() *AuthorityReference {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(AuthorityReference)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeySelector.
|
||||||
|
func (in *SecretKeySelector) DeepCopy() *SecretKeySelector {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(SecretKeySelector)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TechnitiumAuthority) DeepCopyInto(out *TechnitiumAuthority) {
|
func (in *TechnitiumAuthority) DeepCopyInto(out *TechnitiumAuthority) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
out.TypeMeta = in.TypeMeta
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
out.Spec = in.Spec
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
out.Status = in.Status
|
out.Status = in.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,6 +132,12 @@ func (in *TechnitiumAuthorityList) DeepCopyObject() runtime.Object {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TechnitiumAuthoritySpec) DeepCopyInto(out *TechnitiumAuthoritySpec) {
|
func (in *TechnitiumAuthoritySpec) DeepCopyInto(out *TechnitiumAuthoritySpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
out.Primary = in.Primary
|
||||||
|
if in.Secondaries != nil {
|
||||||
|
in, out := &in.Secondaries, &out.Secondaries
|
||||||
|
*out = make([]AuthorityEndpoint, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TechnitiumAuthoritySpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TechnitiumAuthoritySpec.
|
||||||
|
|
@ -118,7 +170,7 @@ func (in *TechnitiumRecord) DeepCopyInto(out *TechnitiumRecord) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
out.TypeMeta = in.TypeMeta
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
out.Spec = in.Spec
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
out.Status = in.Status
|
out.Status = in.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,6 +227,23 @@ func (in *TechnitiumRecordList) DeepCopyObject() runtime.Object {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TechnitiumRecordSpec) DeepCopyInto(out *TechnitiumRecordSpec) {
|
func (in *TechnitiumRecordSpec) DeepCopyInto(out *TechnitiumRecordSpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
out.AuthorityRef = in.AuthorityRef
|
||||||
|
if in.RecordData != nil {
|
||||||
|
in, out := &in.RecordData, &out.RecordData
|
||||||
|
*out = make(map[string][]string, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
var outVal []string
|
||||||
|
if val == nil {
|
||||||
|
(*out)[key] = nil
|
||||||
|
} else {
|
||||||
|
inVal := (*in)[key]
|
||||||
|
in, out := &inVal, &outVal
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
(*out)[key] = outVal
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TechnitiumRecordSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TechnitiumRecordSpec.
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,58 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
description: TechnitiumAuthoritySpec defines the desired state of TechnitiumAuthority
|
description: TechnitiumAuthoritySpec defines the desired state of TechnitiumAuthority
|
||||||
properties:
|
properties:
|
||||||
foo:
|
dnsApp.config:
|
||||||
description: Foo is an example field of TechnitiumAuthority. Edit
|
|
||||||
technitiumauthority_types.go to remove/update
|
|
||||||
type: string
|
type: string
|
||||||
|
primary:
|
||||||
|
description: AuthorityEndpoint defines the API endpoint and credentials
|
||||||
|
properties:
|
||||||
|
apiKeySecretRef:
|
||||||
|
description: SecretKeySelector defines the reference to a key
|
||||||
|
inside a Kubernetes Secret
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
endpoint:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apiKeySecretRef
|
||||||
|
- endpoint
|
||||||
|
type: object
|
||||||
|
secondaries:
|
||||||
|
items:
|
||||||
|
description: AuthorityEndpoint defines the API endpoint and credentials
|
||||||
|
properties:
|
||||||
|
apiKeySecretRef:
|
||||||
|
description: SecretKeySelector defines the reference to a key
|
||||||
|
inside a Kubernetes Secret
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
endpoint:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apiKeySecretRef
|
||||||
|
- endpoint
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
zone:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- dnsApp.config
|
||||||
|
- primary
|
||||||
|
- zone
|
||||||
type: object
|
type: object
|
||||||
status:
|
status:
|
||||||
description: TechnitiumAuthorityStatus defines the observed state of TechnitiumAuthority
|
description: TechnitiumAuthorityStatus defines the observed state of TechnitiumAuthority
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,31 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
description: TechnitiumRecordSpec defines the desired state of TechnitiumRecord
|
description: TechnitiumRecordSpec defines the desired state of TechnitiumRecord
|
||||||
properties:
|
properties:
|
||||||
foo:
|
authorityRef:
|
||||||
description: Foo is an example field of TechnitiumRecord. Edit technitiumrecord_types.go
|
description: AuthorityReference references a TechnitiumAuthority
|
||||||
to remove/update
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
classPath:
|
||||||
type: string
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
recordData:
|
||||||
|
additionalProperties:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
ttl:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- authorityRef
|
||||||
|
- classPath
|
||||||
|
- name
|
||||||
|
- ttl
|
||||||
type: object
|
type: object
|
||||||
status:
|
status:
|
||||||
description: TechnitiumRecordStatus defines the observed state of TechnitiumRecord
|
description: TechnitiumRecordStatus defines the observed state of TechnitiumRecord
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- dns.mayers.cloud
|
- dns.mayers.cloud
|
||||||
resources:
|
resources:
|
||||||
|
- externaldnswatchers
|
||||||
- technitiumauthorities
|
- technitiumauthorities
|
||||||
- technitiumrecords
|
- technitiumrecords
|
||||||
verbs:
|
verbs:
|
||||||
|
|
@ -20,6 +21,7 @@ rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- dns.mayers.cloud
|
- dns.mayers.cloud
|
||||||
resources:
|
resources:
|
||||||
|
- externaldnswatchers/finalizers
|
||||||
- technitiumauthorities/finalizers
|
- technitiumauthorities/finalizers
|
||||||
- technitiumrecords/finalizers
|
- technitiumrecords/finalizers
|
||||||
verbs:
|
verbs:
|
||||||
|
|
@ -27,6 +29,7 @@ rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- dns.mayers.cloud
|
- dns.mayers.cloud
|
||||||
resources:
|
resources:
|
||||||
|
- externaldnswatchers/status
|
||||||
- technitiumauthorities/status
|
- technitiumauthorities/status
|
||||||
- technitiumrecords/status
|
- technitiumrecords/status
|
||||||
verbs:
|
verbs:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
dnsv1alpha1 "git.mayers.cloud/superflo22/split-horizon-operator/api/v1alpha1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
@ -46,9 +50,75 @@ type ExternalDNSWatcherReconciler struct {
|
||||||
// For more details, check Reconcile and its Result here:
|
// For more details, check Reconcile and its Result here:
|
||||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/reconcile
|
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/reconcile
|
||||||
func (r *ExternalDNSWatcherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
func (r *ExternalDNSWatcherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||||
_ = log.FromContext(ctx)
|
log := log.FromContext(ctx)
|
||||||
|
|
||||||
// TODO(user): your logic here
|
// Step 1: Fetch the Gateway
|
||||||
|
var gateway gatewayv1.Gateway
|
||||||
|
if err := r.Get(ctx, req.NamespacedName, &gateway); err != nil {
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Check annotation
|
||||||
|
annotations := gateway.GetAnnotations()
|
||||||
|
if annotations["dns.mayers.cloud/enabled"] != "true" {
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
network := annotations["dns.mayers.cloud/network"]
|
||||||
|
authority := annotations["dns.mayers.cloud/authority"]
|
||||||
|
if network == "" || authority == "" {
|
||||||
|
log.Info("Missing required annotations")
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Get Gateway IP (if available)
|
||||||
|
var gatewayIPs []string
|
||||||
|
for _, addr := range gateway.Status.Addresses {
|
||||||
|
if addr.Type == nil || *addr.Type == gatewayv1.IPAddressType {
|
||||||
|
gatewayIPs = append(gatewayIPs, addr.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: List HTTPRoutes that reference this Gateway
|
||||||
|
var routes gatewayv1.HTTPRouteList
|
||||||
|
if err := r.List(ctx, &routes, client.InNamespace(req.Namespace)); err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, route := range routes.Items {
|
||||||
|
for _, parent := range route.Spec.ParentRefs {
|
||||||
|
|
||||||
|
// Check if the parent is a Gateway and matches the current gateway
|
||||||
|
if string(*parent.Kind) == "Gateway" && string(parent.Name) == gateway.Name {
|
||||||
|
// Step 5: Collect hostnames
|
||||||
|
for _, hostname := range route.Spec.Hostnames {
|
||||||
|
record := &dnsv1alpha1.TechnitiumRecord{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: fmt.Sprintf("%s-%s", route.Name, string(hostname)),
|
||||||
|
Namespace: route.Namespace,
|
||||||
|
},
|
||||||
|
Spec: dnsv1alpha1.TechnitiumRecordSpec{
|
||||||
|
AuthorityRef: dnsv1alpha1.AuthorityReference{
|
||||||
|
Name: authority,
|
||||||
|
},
|
||||||
|
Name: string(hostname),
|
||||||
|
TTL: 300,
|
||||||
|
ClassPath: "SimpleAddress",
|
||||||
|
RecordData: map[string][]string{
|
||||||
|
network: gatewayIPs,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.Client.Patch(ctx, record, client.Apply, client.ForceOwnership, client.FieldOwner("external-dns-watcher")); err != nil {
|
||||||
|
log.Error(err, "Failed to apply TechnitiumRecord")
|
||||||
|
} else {
|
||||||
|
log.Info("Reconciled TechnitiumRecord", "name", record.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +127,14 @@ func (r *ExternalDNSWatcherReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||||
func (r *ExternalDNSWatcherReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
func (r *ExternalDNSWatcherReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
return ctrl.NewControllerManagedBy(mgr).
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
// Uncomment the following line adding a pointer to an instance of the controlled resource as an argument
|
// Uncomment the following line adding a pointer to an instance of the controlled resource as an argument
|
||||||
For(&gatewayv1.HTTPRoute{}).
|
Named("external_dns_controller").
|
||||||
For(&gatewayv1.Gateway{}).
|
Watches(
|
||||||
|
&gatewayv1.Gateway{},
|
||||||
|
&handler.EnqueueRequestForObject{},
|
||||||
|
).
|
||||||
|
Watches(
|
||||||
|
&gatewayv1.HTTPRoute{},
|
||||||
|
&handler.EnqueueRequestForObject{},
|
||||||
|
).
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue