@@ -47,6 +47,12 @@ func (c *Controller) GetResource() string {
4747}
4848
4949func (c * Controller ) Run (ctx context.Context , cfg * config.Config ) error {
50+ // Initial listing to populate state
51+ if err := c .initialList (ctx , cfg ); err != nil {
52+ return fmt .Errorf ("initial list failed for %s: %w" , c .gvr .Resource , err )
53+ }
54+
55+ // Watch loop
5056 for {
5157 if err := c .watchLoop (ctx , cfg ); err != nil {
5258 slog .Error ("watch loop error" , "error" , err )
@@ -59,6 +65,27 @@ func (c *Controller) Run(ctx context.Context, cfg *config.Config) error {
5965 }
6066}
6167
68+ func (c * Controller ) initialList (ctx context.Context , cfg * config.Config ) error {
69+ list , err := c .dynamicClient .Resource (c .gvr ).Namespace (cfg .Namespace ).List (ctx , c .options )
70+ if err != nil {
71+ return fmt .Errorf ("list %s: %w" , c .gvr .Resource , err )
72+ }
73+
74+ for i , item := range list .Items {
75+ obj , err := c .convert (& item )
76+ if err != nil {
77+ slog .Error ("failed to convert resource" , "resource" , c .gvr .Resource , "error" , err )
78+ continue
79+ }
80+
81+ // Skip write for all but last to reduce I/O
82+ isNotLast := i != len (list .Items )- 1
83+ c .handleEvent (ctx , cfg , obj , watch .Added , isNotLast )
84+ }
85+
86+ return nil
87+ }
88+
6289func (c * Controller ) watchLoop (ctx context.Context , cfg * config.Config ) error {
6390 w , err := c .dynamicClient .Resource (c .gvr ).Namespace (cfg .Namespace ).Watch (ctx , c .options )
6491 if err != nil {
@@ -86,7 +113,7 @@ func (c *Controller) processEvent(ctx context.Context, cfg *config.Config, evt w
86113 return
87114 }
88115
89- c .handleEvent (ctx , cfg , obj , evt .Type )
116+ c .handleEvent (ctx , cfg , obj , evt .Type , false )
90117}
91118
92119func (c * Controller ) convertEvent (evt watch.Event ) (metav1.Object , error ) {
@@ -98,12 +125,12 @@ func (c *Controller) convertEvent(evt watch.Event) (metav1.Object, error) {
98125 return c .convert (unstructuredObj )
99126}
100127
101- func (c * Controller ) handleEvent (ctx context.Context , cfg * config.Config , obj metav1.Object , eventType watch.EventType ) {
128+ func (c * Controller ) handleEvent (ctx context.Context , cfg * config.Config , obj metav1.Object , eventType watch.EventType , skipWrite bool ) {
102129 name := obj .GetName ()
103130 namespace := obj .GetNamespace ()
104131 annotations := obj .GetAnnotations ()
105132 resource := c .gvr .Resource
106- key := fmt .Sprintf ("%s:%s: %s" , name , namespace , resource )
133+ key := fmt .Sprintf ("%s.%s. %s" , name , namespace , resource )
107134
108135 // Early returns for deletion or non-processable resources
109136 if ! c .handler .ShouldProcess (obj , cfg ) || eventType == watch .Deleted {
@@ -145,8 +172,8 @@ func (c *Controller) handleEvent(ctx context.Context, cfg *config.Config, obj me
145172 }
146173
147174 // Update state
148- if changed := c .stateManager .AddOrUpdate (key , endpoint ); changed {
149- slog .Info ("updated endpoint in state" , "resource" , resource , "name" , name , "namespace" , namespace )
175+ if changed := c .stateManager .AddOrUpdate (key , endpoint , skipWrite ); changed {
176+ slog .Info ("updated endpoint in state" , "resource" , resource , "name" , name , "namespace" , namespace , "skipWrite" , skipWrite )
150177 }
151178}
152179
0 commit comments