Compare commits
No commits in common. "fda3120bd3055d3a7be3f29a33daf494759b4063" and "a428b29771ba67cd2a6c9246233715b593d38738" have entirely different histories.
fda3120bd3
...
a428b29771
14 changed files with 64 additions and 373 deletions
5
PROJECT
5
PROJECT
|
|
@ -29,9 +29,4 @@ resources:
|
|||
kind: TechnitiumAuthority
|
||||
path: git.mayers.cloud/superflo22/split-horizon-operator/api/v1alpha1
|
||||
version: v1alpha1
|
||||
- controller: true
|
||||
domain: mayers.cloud
|
||||
group: dns
|
||||
kind: ExternalDNSWatcher
|
||||
version: v1alpha1
|
||||
version: "3"
|
||||
|
|
|
|||
|
|
@ -1,32 +1,41 @@
|
|||
/*
|
||||
Copyright 2025.
|
||||
|
||||
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 (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// TechnitiumAuthoritySpec defines the desired state of TechnitiumAuthority
|
||||
type TechnitiumAuthoritySpec struct {
|
||||
Zone string `json:"zone"`
|
||||
Primary AuthorityEndpoint `json:"primary"`
|
||||
Secondaries []AuthorityEndpoint `json:"secondaries,omitempty"`
|
||||
DNSAppConfig string `json:"dnsApp.config"`
|
||||
}
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
|
||||
// AuthorityEndpoint defines the API endpoint and credentials
|
||||
type AuthorityEndpoint struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
APIKeySecretRef SecretKeySelector `json:"apiKeySecretRef"`
|
||||
}
|
||||
|
||||
// SecretKeySelector defines the reference to a key inside a Kubernetes Secret
|
||||
type SecretKeySelector struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
// Foo is an example field of TechnitiumAuthority. Edit technitiumauthority_types.go to remove/update
|
||||
Foo string `json:"foo,omitempty"`
|
||||
}
|
||||
|
||||
// TechnitiumAuthorityStatus defines the observed state of TechnitiumAuthority
|
||||
type TechnitiumAuthorityStatus struct {
|
||||
// Add any observed status fields here
|
||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
|||
|
|
@ -1,26 +1,41 @@
|
|||
/*
|
||||
Copyright 2025.
|
||||
|
||||
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 (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// TechnitiumRecordSpec defines the desired state of TechnitiumRecord
|
||||
type TechnitiumRecordSpec struct {
|
||||
AuthorityRef AuthorityReference `json:"authorityRef"`
|
||||
Name string `json:"name"`
|
||||
TTL int `json:"ttl"`
|
||||
ClassPath string `json:"classPath"`
|
||||
RecordData map[string][]string `json:"recordData,omitempty"`
|
||||
}
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
|
||||
// AuthorityReference references a TechnitiumAuthority
|
||||
type AuthorityReference struct {
|
||||
Name string `json:"name"`
|
||||
// Foo is an example field of TechnitiumRecord. Edit technitiumrecord_types.go to remove/update
|
||||
Foo string `json:"foo,omitempty"`
|
||||
}
|
||||
|
||||
// TechnitiumRecordStatus defines the observed state of TechnitiumRecord
|
||||
type TechnitiumRecordStatus struct {
|
||||
// Define observed status fields here
|
||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
|||
|
|
@ -24,58 +24,12 @@ import (
|
|||
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.
|
||||
func (in *TechnitiumAuthority) DeepCopyInto(out *TechnitiumAuthority) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Spec = in.Spec
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
|
|
@ -132,12 +86,6 @@ func (in *TechnitiumAuthorityList) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TechnitiumAuthoritySpec) DeepCopyInto(out *TechnitiumAuthoritySpec) {
|
||||
*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.
|
||||
|
|
@ -170,7 +118,7 @@ func (in *TechnitiumRecord) DeepCopyInto(out *TechnitiumRecord) {
|
|||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Spec = in.Spec
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
|
|
@ -227,23 +175,6 @@ func (in *TechnitiumRecordList) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TechnitiumRecordSpec) DeepCopyInto(out *TechnitiumRecordSpec) {
|
||||
*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.
|
||||
|
|
|
|||
10
cmd/main.go
10
cmd/main.go
|
|
@ -34,7 +34,6 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
||||
|
||||
dnsv1alpha1 "git.mayers.cloud/superflo22/split-horizon-operator/api/v1alpha1"
|
||||
"git.mayers.cloud/superflo22/split-horizon-operator/internal/controller"
|
||||
|
|
@ -50,8 +49,6 @@ func init() {
|
|||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
|
||||
utilruntime.Must(dnsv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(gatewayv1.AddToScheme(scheme))
|
||||
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
|
|
@ -161,13 +158,6 @@ func main() {
|
|||
setupLog.Error(err, "unable to create controller", "controller", "TechnitiumAuthority")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = (&controller.ExternalDNSWatcherReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "ExternalDNSWatcher")
|
||||
os.Exit(1)
|
||||
}
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
|
|
|||
|
|
@ -40,58 +40,10 @@ spec:
|
|||
spec:
|
||||
description: TechnitiumAuthoritySpec defines the desired state of TechnitiumAuthority
|
||||
properties:
|
||||
dnsApp.config:
|
||||
foo:
|
||||
description: Foo is an example field of TechnitiumAuthority. Edit
|
||||
technitiumauthority_types.go to remove/update
|
||||
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
|
||||
status:
|
||||
description: TechnitiumAuthorityStatus defines the observed state of TechnitiumAuthority
|
||||
|
|
|
|||
|
|
@ -39,31 +39,10 @@ spec:
|
|||
spec:
|
||||
description: TechnitiumRecordSpec defines the desired state of TechnitiumRecord
|
||||
properties:
|
||||
authorityRef:
|
||||
description: AuthorityReference references a TechnitiumAuthority
|
||||
properties:
|
||||
name:
|
||||
foo:
|
||||
description: Foo is an example field of TechnitiumRecord. Edit technitiumrecord_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
classPath:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
recordData:
|
||||
additionalProperties:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
ttl:
|
||||
type: integer
|
||||
required:
|
||||
- authorityRef
|
||||
- classPath
|
||||
- name
|
||||
- ttl
|
||||
type: object
|
||||
status:
|
||||
description: TechnitiumRecordStatus defines the observed state of TechnitiumRecord
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ rules:
|
|||
- apiGroups:
|
||||
- dns.mayers.cloud
|
||||
resources:
|
||||
- externaldnswatchers
|
||||
- technitiumauthorities
|
||||
- technitiumrecords
|
||||
verbs:
|
||||
|
|
@ -21,7 +20,6 @@ rules:
|
|||
- apiGroups:
|
||||
- dns.mayers.cloud
|
||||
resources:
|
||||
- externaldnswatchers/finalizers
|
||||
- technitiumauthorities/finalizers
|
||||
- technitiumrecords/finalizers
|
||||
verbs:
|
||||
|
|
@ -29,7 +27,6 @@ rules:
|
|||
- apiGroups:
|
||||
- dns.mayers.cloud
|
||||
resources:
|
||||
- externaldnswatchers/status
|
||||
- technitiumauthorities/status
|
||||
- technitiumrecords/status
|
||||
verbs:
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ spec:
|
|||
classPath: SimpleAddress
|
||||
|
||||
recordData:
|
||||
# These are examples and might be renamed by the user
|
||||
# public:
|
||||
# - 93.184.216.34
|
||||
# vpn:
|
||||
# - 10.0.0.99
|
||||
public:
|
||||
- 93.184.216.34
|
||||
vpn:
|
||||
- 10.0.0.99
|
||||
|
|
@ -2,5 +2,4 @@
|
|||
resources:
|
||||
- dns_v1alpha1_technitiumrecord.yaml
|
||||
- dns_v1alpha1_technitiumauthority.yaml
|
||||
- dns_v1alpha1_externaldnswatcher.yaml
|
||||
# +kubebuilder:scaffold:manifestskustomizesamples
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -10,7 +10,6 @@ require (
|
|||
k8s.io/apimachinery v0.32.3
|
||||
k8s.io/client-go v0.32.3
|
||||
sigs.k8s.io/controller-runtime v0.20.4
|
||||
sigs.k8s.io/gateway-api v1.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -19,8 +19,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
|
|
@ -245,8 +245,6 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.32.0 h1:XotDXzqvJ8Nx5
|
|||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.32.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
|
||||
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
|
||||
sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM=
|
||||
sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
|
|
|
|||
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
Copyright 2025.
|
||||
|
||||
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 controller
|
||||
|
||||
import (
|
||||
"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"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// ExternalDNSWatcherReconciler reconciles a ExternalDNSWatcher object
|
||||
type ExternalDNSWatcherReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
// +kubebuilder:rbac:groups=dns.mayers.cloud,resources=externaldnswatchers,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=dns.mayers.cloud,resources=externaldnswatchers/status,verbs=get;update;patch
|
||||
// +kubebuilder:rbac:groups=dns.mayers.cloud,resources=externaldnswatchers/finalizers,verbs=update
|
||||
|
||||
// Reconcile is part of the main kubernetes reconciliation loop which aims to
|
||||
// move the current state of the cluster closer to the desired state.
|
||||
// TODO(user): Modify the Reconcile function to compare the state specified by
|
||||
// the ExternalDNSWatcher object against the actual cluster state, and then
|
||||
// perform operations to make the cluster state reflect the state specified by
|
||||
// the user.
|
||||
//
|
||||
// For more details, check Reconcile and its Result here:
|
||||
// - 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) {
|
||||
log := log.FromContext(ctx)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *ExternalDNSWatcherReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
// Uncomment the following line adding a pointer to an instance of the controlled resource as an argument
|
||||
Named("external_dns_controller").
|
||||
Watches(
|
||||
&gatewayv1.Gateway{},
|
||||
&handler.EnqueueRequestForObject{},
|
||||
).
|
||||
Watches(
|
||||
&gatewayv1.HTTPRoute{},
|
||||
&handler.EnqueueRequestForObject{},
|
||||
).
|
||||
Complete(r)
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
Copyright 2025.
|
||||
|
||||
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 controller
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
var _ = Describe("ExternalDNSWatcher Controller", func() {
|
||||
Context("When reconciling a resource", func() {
|
||||
|
||||
It("should successfully reconcile the resource", func() {
|
||||
|
||||
// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
|
||||
// Example: If you expect a certain status condition after reconciliation, verify it here.
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Reference in a new issue