@@ -20,26 +20,29 @@ import (
2020 "k8s.io/client-go/rest"
2121
2222 "github.com/home-operations/gatus-sidecar/internal/config"
23- "github.com/home-operations/gatus-sidecar/internal/generator "
23+ "github.com/home-operations/gatus-sidecar/internal/endpoint "
2424 "github.com/home-operations/gatus-sidecar/internal/handler"
25+ "github.com/home-operations/gatus-sidecar/internal/state"
2526)
2627
2728// Controller is a generic Kubernetes resource controller
2829type Controller struct {
29- gvr schema.GroupVersionResource
30- handler handler.ResourceHandler
31- convert func (* unstructured.Unstructured ) (metav1.Object , error )
30+ gvr schema.GroupVersionResource
31+ handler handler.ResourceHandler
32+ convert func (* unstructured.Unstructured ) (metav1.Object , error )
33+ stateManager * state.Manager
3234}
3335
3436// NewIngressController creates a controller for Ingress resources
35- func NewIngressController (resourceHandler handler.ResourceHandler ) * Controller {
37+ func NewIngressController (resourceHandler handler.ResourceHandler , stateManager * state. Manager ) * Controller {
3638 return & Controller {
3739 gvr : schema.GroupVersionResource {
3840 Group : "networking.k8s.io" ,
3941 Version : "v1" ,
4042 Resource : "ingresses" ,
4143 },
42- handler : resourceHandler ,
44+ handler : resourceHandler ,
45+ stateManager : stateManager ,
4346 convert : func (u * unstructured.Unstructured ) (metav1.Object , error ) {
4447 ingress := & networkingv1.Ingress {}
4548 if err := runtime .DefaultUnstructuredConverter .FromUnstructured (u .Object , ingress ); err != nil {
@@ -51,10 +54,11 @@ func NewIngressController(resourceHandler handler.ResourceHandler) *Controller {
5154}
5255
5356// NewHTTPRouteController creates a controller for HTTPRoute resources
54- func NewHTTPRouteController (resourceHandler handler.ResourceHandler ) * Controller {
57+ func NewHTTPRouteController (resourceHandler handler.ResourceHandler , stateManager * state. Manager ) * Controller {
5558 return & Controller {
56- gvr : gatewayv1 .SchemeGroupVersion .WithResource ("httproutes" ),
57- handler : resourceHandler ,
59+ gvr : gatewayv1 .SchemeGroupVersion .WithResource ("httproutes" ),
60+ handler : resourceHandler ,
61+ stateManager : stateManager ,
5862 convert : func (u * unstructured.Unstructured ) (metav1.Object , error ) {
5963 route := & gatewayv1.HTTPRoute {}
6064 if err := runtime .DefaultUnstructuredConverter .FromUnstructured (u .Object , route ); err != nil {
@@ -133,21 +137,21 @@ func (c *Controller) handleEvent(cfg *config.Config, obj metav1.Object, eventTyp
133137 }
134138
135139 name := obj .GetName ()
136- filename := fmt .Sprintf ("%s-%s.yaml" , obj .GetName (), obj .GetNamespace ())
140+ namespace := obj .GetNamespace ()
141+ resource := fmt .Sprintf ("%s-%s" , name , namespace )
137142
138143 if eventType == watch .Deleted {
139- if err := generator .Delete (cfg .OutputDir , filename ); err != nil {
140- slog .Error ("failed to delete file for resource" , c .handler .GetResourceName (), obj .GetName (), "error" , err )
141- } else {
142- slog .Info ("deleted file for resource" , c .handler .GetResourceName (), obj .GetName ())
144+ changed := c .stateManager .Remove (resource )
145+ if changed {
146+ slog .Info ("removed endpoint from state" , "resource" , c .handler .GetResourceName (), "name" , name )
143147 }
144148 return
145149 }
146150
147151 // Get the URL from the resource
148152 url := c .handler .ExtractURL (obj )
149153 if url == "" {
150- slog .Warn ("resource has no hosts/hostnames" , c .handler .GetResourceName (), obj . GetName () )
154+ slog .Warn ("resource has no hosts/hostnames" , "resource" , c .handler .GetResourceName (), "name" , name )
151155 return
152156 }
153157
@@ -161,24 +165,29 @@ func (c *Controller) handleEvent(cfg *config.Config, obj metav1.Object, eventTyp
161165 if annotations != nil {
162166 if templateStr , ok := annotations [cfg .TemplateAnnotation ]; ok && templateStr != "" {
163167 if err := yaml .Unmarshal ([]byte (templateStr ), & templateData ); err != nil {
164- slog .Error ("failed to unmarshal template for resource" , c .handler .GetResourceName (), obj . GetName () , "error" , err )
168+ slog .Error ("failed to unmarshal template for resource" , "resource" , c .handler .GetResourceName (), "name" , name , "error" , err )
165169 return
166170 }
167171 }
168172 }
169173
170- data := map [string ]any {
171- "name" : name ,
172- "url" : url ,
173- "interval" : interval ,
174- "client" : map [string ]any {"dns-resolver" : dnsResolver },
175- "conditions" : []string {condition },
174+ // Create endpoint state with defaults
175+ endpoint := & endpoint.Endpoint {
176+ Name : name ,
177+ URL : url ,
178+ Interval : interval ,
179+ Client : map [string ]any {"dns-resolver" : dnsResolver },
180+ Conditions : []string {condition },
176181 }
177182
178- // Write with optional template data
179- if err := generator .Write (data , cfg .OutputDir , filename , templateData ); err != nil {
180- slog .Error ("write file for resource" , c .handler .GetResourceName (), obj .GetName (), "error" , err )
181- } else {
182- slog .Info ("wrote file for resource" , c .handler .GetResourceName (), obj .GetName ())
183+ // Apply template overrides if present
184+ if templateData != nil {
185+ endpoint .ApplyTemplate (templateData )
186+ }
187+
188+ // Update state
189+ changed := c .stateManager .AddOrUpdate (resource , endpoint )
190+ if changed {
191+ slog .Info ("updated endpoint in state" , "resource" , c .handler .GetResourceName (), "name" , name )
183192 }
184193}
0 commit comments