feat: register crd in kube watcher

This commit is contained in:
Stavros
2026-09-22 22:30:12 +03:00
parent a62ef392e2
commit f98c844f28
5 changed files with 33 additions and 10 deletions
+2 -1
View File
@@ -22,6 +22,7 @@ func NewKubernetesCRDExtractor(i KubernetesCRDInput) *KubernetesCRDExtractor {
func (k *KubernetesCRDExtractor) Extract(app *v1alpha1.Application) ExtractionResult { func (k *KubernetesCRDExtractor) Extract(app *v1alpha1.Application) ExtractionResult {
meta := &ResourceMeta{ meta := &ResourceMeta{
Typ: ResourceTypeCRD,
Name: app.GetName(), Name: app.GetName(),
Namespace: app.GetNamespace(), Namespace: app.GetNamespace(),
} }
@@ -49,7 +50,7 @@ func (k *KubernetesCRDExtractor) Extract(app *v1alpha1.Application) ExtractionRe
return ExtractionResult{ return ExtractionResult{
Meta: meta, Meta: meta,
Apps: &map[string]model.App{ Apps: map[string]model.App{
// Convert the CRD to the internal representation // Convert the CRD to the internal representation
meta.Name: app.Spec.ToInternalApp(), meta.Name: app.Spec.ToInternalApp(),
}, },
@@ -76,6 +76,7 @@ func (k *KubernetesIngressExtractor) getHosts(rules []networking.IngressRule) []
func (k *KubernetesIngressExtractor) Extract(ingress *networking.Ingress) ExtractionResult { func (k *KubernetesIngressExtractor) Extract(ingress *networking.Ingress) ExtractionResult {
meta := &ResourceMeta{ meta := &ResourceMeta{
Typ: ResourceTypeIngress,
Name: ingress.GetName(), Name: ingress.GetName(),
Namespace: ingress.GetNamespace(), Namespace: ingress.GetNamespace(),
} }
@@ -128,6 +129,6 @@ func (k *KubernetesIngressExtractor) Extract(ingress *networking.Ingress) Extrac
return ExtractionResult{ return ExtractionResult{
Meta: meta, Meta: meta,
Apps: &apps, Apps: apps,
} }
} }
+29 -5
View File
@@ -35,13 +35,14 @@ func ensureResourceMeta(meta *ResourceMeta) bool {
} }
type ResourceMeta struct { type ResourceMeta struct {
Typ ResourceType
Name string Name string
Namespace string Namespace string
} }
type ExtractionResult struct { type ExtractionResult struct {
Meta *ResourceMeta Meta *ResourceMeta
Apps *map[string]model.App Apps map[string]model.App
} }
type ResourceType string type ResourceType string
@@ -60,6 +61,13 @@ var supportedResources = []watchedResource{
}, },
typ: ResourceTypeIngress, typ: ResourceTypeIngress,
}, },
{
gvr: schema.GroupVersionResource{
Group: "tinyauth.app",
Version: "v1alpha1",
Resource: "applications",
},
},
} }
type typedItem struct { type typedItem struct {
@@ -89,6 +97,15 @@ func (ti *typedItem) fromUnstructured(typ ResourceType, obj *unstructured.Unstru
typ: ResourceTypeIngress, typ: ResourceTypeIngress,
ingress: typed, ingress: typed,
}, nil }, nil
case ResourceTypeCRD:
typed, err := convertFromUnstructured[v1alpha1.Application](obj)
if err != nil {
return nil, err
}
return &typedItem{
typ: ResourceTypeCRD,
crd: typed,
}, nil
default: default:
return nil, fmt.Errorf("unknown resource type %s", typ) return nil, fmt.Errorf("unknown resource type %s", typ)
} }
@@ -163,7 +180,7 @@ func NewKubernetesService(i KubernetesServiceInput) (*KubernetesService, error)
func (k *KubernetesService) addResource(result ExtractionResult) { func (k *KubernetesService) addResource(result ExtractionResult) {
k.mu.Lock() k.mu.Lock()
defer k.mu.Unlock() defer k.mu.Unlock()
k.apps[*result.Meta] = *result.Apps k.apps[*result.Meta] = result.Apps
} }
func (k *KubernetesService) removeResource(meta ResourceMeta) { func (k *KubernetesService) removeResource(meta ResourceMeta) {
@@ -185,7 +202,7 @@ func (k *KubernetesService) getEntry(locator func(name string, app *model.App) b
} }
} }
func (k *KubernetesService) updateFromItem(res watchedResource, typedItem *typedItem) { func (k *KubernetesService) watchedItemChange(res watchedResource, typedItem *typedItem, event watch.EventType) {
if typedItem == nil { if typedItem == nil {
k.log.App.Warn().Str("res", res.pretty()).Msg("Resource is nil, skipping") k.log.App.Warn().Str("res", res.pretty()).Msg("Resource is nil, skipping")
return return
@@ -214,6 +231,13 @@ func (k *KubernetesService) updateFromItem(res watchedResource, typedItem *typed
result = extractor.Extract(typedItem.crd) result = extractor.Extract(typedItem.crd)
} }
if event == watch.Deleted {
if result.Meta != nil {
k.removeResource(*result.Meta)
}
return
}
if result.Apps == nil { if result.Apps == nil {
k.log.App.Warn().Str("res", res.pretty()).Msg("Failed to extract resource, skipping") k.log.App.Warn().Str("res", res.pretty()).Msg("Failed to extract resource, skipping")
if result.Meta != nil { if result.Meta != nil {
@@ -240,7 +264,7 @@ func (k *KubernetesService) resyncGVR(res watchedResource, ctx context.Context)
k.log.App.Warn().Err(err).Str("res", res.pretty()).Msg("Failed to decode resource, skipping") k.log.App.Warn().Err(err).Str("res", res.pretty()).Msg("Failed to decode resource, skipping")
continue continue
} }
k.updateFromItem(res, newTypedItem) k.watchedItemChange(res, newTypedItem, watch.Modified)
} }
k.log.App.Debug().Str("res", res.pretty()).Int("count", len(list.Items)).Msg("Resync complete") k.log.App.Debug().Str("res", res.pretty()).Int("count", len(list.Items)).Msg("Resync complete")
return nil return nil
@@ -271,7 +295,7 @@ func (k *KubernetesService) runWatcher(res watchedResource, w watch.Interface, r
} }
switch event.Type { switch event.Type {
case watch.Added, watch.Modified, watch.Deleted: case watch.Added, watch.Modified, watch.Deleted:
k.updateFromItem(res, newTypedItem) k.watchedItemChange(res, newTypedItem, event.Type)
} }
case <-resyncTicker.C: case <-resyncTicker.C:
if err := k.resyncGVR(res, ctx); err != nil { if err := k.resyncGVR(res, ctx); err != nil {
@@ -33,8 +33,6 @@ type ApplicationSpec struct {
// AppConfig specifies configuration for the application // AppConfig specifies configuration for the application
type AppConfig struct { type AppConfig struct {
// +required
Name string `json:"name,omitempty"`
// +required // +required
Domain string `json:"domain,omitempty"` Domain string `json:"domain,omitempty"`
} }
-1
View File
@@ -19,7 +19,6 @@ var (
func addKnownTypes(scheme *runtime.Scheme) error { func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion, scheme.AddKnownTypes(SchemeGroupVersion,
&Application{}, &Application{},
&ApplicationSet{},
) )
metav1.AddToGroupVersion(scheme, SchemeGroupVersion) metav1.AddToGroupVersion(scheme, SchemeGroupVersion)