@@ -10,6 +10,7 @@ import (
1010 "github.com/thand-io/agent/internal/config/environment"
1111 "github.com/thand-io/agent/internal/models"
1212 "github.com/thand-io/agent/internal/providers"
13+ sdkConstants "github.com/thand-io/agent/sdk/constants"
1314 providerSdk "github.com/thand-io/agent/sdk/providers"
1415 "go.temporal.io/sdk/workflow"
1516
@@ -190,7 +191,7 @@ func (c *Config) InitializeProviders() error {
190191 if c .IsServer () {
191192 _ = c .GetServices ()
192193 if err := c .SetupTemporal (); err != nil {
193- return fmt .Errorf ("setting up temporal services: %w" , err )
194+ return fmt .Errorf ("failed to set up temporal services: %w" , err )
194195 }
195196 }
196197
@@ -239,25 +240,29 @@ func (c *Config) InitializeProviders() error {
239240 models .ProviderCapabilityRoles ,
240241 models .ProviderCapabilityPermissions ,
241242 models .ProviderCapabilityTenants ,
243+ models .ProviderCapabilityNotifier ,
244+ models .ProviderCapabilityProvisioning ,
242245 ) {
243246
244247 logrus .Infoln ("Provider" , result .key , "supports RBAC/Identities capabilities" )
245248
246- // Register provider workflows and activities with Temporal if available
247- if c .IsServer () {
249+ // If a server or agent register all capabilities depending on their runtime
248250
249- if c .GetServices () != nil && c .GetServices ().HasTemporal () {
251+ if c .GetServices () != nil && c .GetServices ().HasTemporal () {
250252
251- logrus .Infoln ("Registering Temporal workflows/activities for provider" , result .key )
253+ logrus .Infoln ("Registering Temporal workflows/activities for provider" , result .key )
252254
253- temporalService := c .GetServices ().GetTemporal ()
255+ temporalService := c .GetServices ().GetTemporal ()
254256
255- worker := temporalService .GetWorker ()
257+ worker := temporalService .GetWorker ()
256258
257- if worker == nil {
258- logrus .Errorln ("Temporal client is configured but worker is nil, cannot register workflows/activities for provider" , result .key )
259- continue
260- }
259+ if worker == nil {
260+ logrus .Errorln ("Temporal client is configured but worker is nil, cannot register workflows/activities for provider" , result .key )
261+ continue
262+ }
263+
264+ // Only sync jobs can happen on the server
265+ if c .IsServer () {
261266
262267 syncWorkflowName := models .CreateTemporalProviderWorkflowName (
263268 providerResult .GetIdentifier (),
@@ -277,75 +282,146 @@ func (c *Config) InitializeProviders() error {
277282 VersioningBehavior : workflow .VersioningBehaviorPinned ,
278283 },
279284 )
285+ }
286+
287+ logrus .Info ("Registering default activities for provider" , providerResult .GetName ())
288+
289+ // Check the provider capability is either agent or server
290+ providerCapabilities := providerResult .GetCapabilities ()
280291
281- if providerResult .HasCapability (models .ProviderCapabilityProvisioning ) {
282-
283- authWorkflowName := models .CreateTemporalProviderWorkflowName (
284- providerResult .GetIdentifier (),
285- models .TemporalAuthorizeRoleWorkflowName )
286-
287- logrus .WithFields (logrus.Fields {
288- "workflow" : authWorkflowName ,
289- "provider" : providerResult .GetIdentifier (),
290- }).Infoln ("Registering provider authorize role workflow with name" , authWorkflowName )
291-
292- // Register the provider-specific authorize and revoke role workflows.
293- // These are closure-based: they capture the live provider instance so the
294- // child workflow can call provider.AuthorizeRole / RevokeRole with a
295- // full workflow.Context, allowing providers to dispatch activities,
296- // use workflow.Go, etc.
297- worker .RegisterWorkflowWithOptions (
298- models .CreateProviderAuthorizeRoleWorkflow (providerResult ),
299- workflow.RegisterOptions {
300- Name : authWorkflowName ,
301- VersioningBehavior : workflow .VersioningBehaviorPinned ,
302- },
303- )
304-
305- revokeWorkflowName := models .CreateTemporalProviderWorkflowName (
306- providerResult .GetIdentifier (),
307- models .TemporalRevokeRoleWorkflowName )
308-
309- logrus .WithFields (logrus.Fields {
310- "workflow" : revokeWorkflowName ,
311- "provider" : providerResult .GetIdentifier (),
312- }).Infoln ("Registering provider revoke role workflow with name" , revokeWorkflowName )
313-
314- worker .RegisterWorkflowWithOptions (
315- models .CreateProviderRevokeRoleWorkflow (providerResult ),
316- workflow.RegisterOptions {
317- Name : revokeWorkflowName ,
318- VersioningBehavior : workflow .VersioningBehaviorPinned ,
319- },
320- )
292+ // We always register the provider on the server
293+ // so that it can re-set the task queue if needed.
294+ // only register on agent/client if its needed.
295+
296+ // Register the provisioning capability
297+ if providerCapabilities != nil &&
298+ providerCapabilities .Provisioning .Enabled &&
299+ (providerCapabilities .Provisioning .Runtime == c .GetMode () || (providerCapabilities .Provisioning .Runtime == sdkConstants .ModeAgent && c .IsClient ()) || c .IsServer ()) {
300+
301+ authWorkflowName := models .CreateTemporalProviderWorkflowName (
302+ providerResult .GetIdentifier (),
303+ models .TemporalAuthorizeRoleWorkflowName )
304+
305+ logrus .WithFields (logrus.Fields {
306+ "workflow" : authWorkflowName ,
307+ "provider" : providerResult .GetIdentifier (),
308+ }).Infoln ("Registering provider authorize role workflow with name" , authWorkflowName )
309+
310+ // Register the provider-specific authorize and revoke role workflows.
311+ // These are closure-based: they capture the live provider instance so the
312+ // child workflow can call provider.AuthorizeRole / RevokeRole with a
313+ // full workflow.Context, allowing providers to dispatch activities,
314+ // use workflow.Go, etc.
315+ worker .RegisterWorkflowWithOptions (
316+ models .CreateProviderAuthorizeRoleWorkflow (providerResult ),
317+ workflow.RegisterOptions {
318+ Name : authWorkflowName ,
319+ VersioningBehavior : workflow .VersioningBehaviorPinned ,
320+ },
321+ )
322+
323+ revokeWorkflowName := models .CreateTemporalProviderWorkflowName (
324+ providerResult .GetIdentifier (),
325+ models .TemporalRevokeRoleWorkflowName )
326+
327+ logrus .WithFields (logrus.Fields {
328+ "workflow" : revokeWorkflowName ,
329+ "provider" : providerResult .GetIdentifier (),
330+ }).Infoln ("Registering provider revoke role workflow with name" , revokeWorkflowName )
331+
332+ worker .RegisterWorkflowWithOptions (
333+ models .CreateProviderRevokeRoleWorkflow (providerResult ),
334+ workflow.RegisterOptions {
335+ Name : revokeWorkflowName ,
336+ VersioningBehavior : workflow .VersioningBehaviorPinned ,
337+ },
338+ )
339+ } else {
340+ provisioningEnabled := false
341+ provisioningRuntime := sdkConstants .Mode ("" )
342+ if providerCapabilities != nil && providerCapabilities .Provisioning != nil {
343+ provisioningEnabled = providerCapabilities .Provisioning .Enabled
344+ provisioningRuntime = providerCapabilities .Provisioning .Runtime
321345 }
322- // Register all custom provider workflows
323- workflowsRegistry := providerResult .RegisterWorkflows ()
324- if workflowsRegistry != nil {
325- logrus .Infoln ("Registering Temporal workflows for provider" , result .key )
326- worker .RegisterWorkflow (workflowsRegistry )
346+ logrus .WithFields (logrus.Fields {
347+ "provider" : result .key ,
348+ "mode" : c .GetMode (),
349+ "provisioning.enabled" : provisioningEnabled ,
350+ "provisioning.runtime" : provisioningRuntime ,
351+ }).Infoln ("Skipping provisioning workflow registration: provider does not support provisioning in this runtime" )
352+ }
353+
354+ // Register the notification capability
355+ if providerCapabilities != nil &&
356+ providerCapabilities .Notifier .Enabled &&
357+ ((providerCapabilities .Notifier .Runtime == c .GetMode ()) || (providerCapabilities .Notifier .Runtime == sdkConstants .ModeAgent && c .IsClient ()) || c .IsServer ()) {
358+
359+ notifierWorkflowName := models .CreateTemporalProviderWorkflowName (
360+ providerResult .GetIdentifier (),
361+ models .TemporalNotifyWorkflowName )
362+
363+ logrus .WithFields (logrus.Fields {
364+ "workflow" : notifierWorkflowName ,
365+ "provider" : providerResult .GetIdentifier (),
366+ }).Infoln ("Registering provider notify workflow with name" , notifierWorkflowName )
367+
368+ worker .RegisterWorkflowWithOptions (
369+ models .CreateProviderNotifyWorkflow (providerResult ),
370+ workflow.RegisterOptions {
371+ Name : notifierWorkflowName ,
372+ VersioningBehavior : workflow .VersioningBehaviorPinned ,
373+ },
374+ )
375+ } else {
376+ notifierEnabled := false
377+ notifierRuntime := sdkConstants .Mode ("" )
378+ if providerCapabilities != nil && providerCapabilities .Notifier != nil {
379+ notifierEnabled = providerCapabilities .Notifier .Enabled
380+ notifierRuntime = providerCapabilities .Notifier .Runtime
327381 }
382+ logrus .WithFields (logrus.Fields {
383+ "provider" : result .key ,
384+ "mode" : c .GetMode (),
385+ "notifier.enabled" : notifierEnabled ,
386+ "notifier.runtime" : notifierRuntime ,
387+ }).Infoln ("Skipping notify workflow registration: provider does not support notifier in this runtime" )
388+ }
389+
390+ // Register all custom provider workflows
391+ workflowsRegistry := providerResult .RegisterWorkflows (c .GetMode ())
392+ if workflowsRegistry != nil {
393+ logrus .Infoln ("Registering Temporal workflows for provider" , result .key )
394+ worker .RegisterWorkflow (workflowsRegistry )
395+ }
396+
397+ logrus .Infoln ("Finished registering Temporal workflows/activities for provider" , result .key )
398+
399+ // Register default provider activities
400+ err := models .RegisterProviderActivities (temporalService , providerResult , c )
401+ if err != nil {
402+ logrus .WithError (err ).Errorln ("Failed to register default activities for provider:" , result .key )
403+ continue
404+ }
405+
406+ logrus .Infoln ("Registered default activities for provider" , providerResult .GetName ())
328407
329- // Register default provider activities
330- err := models .RegisterProviderActivities (temporalService , providerResult , c )
408+ customActivities := providerResult .RegisterActivities (c .GetMode ())
409+ if customActivities != nil {
410+
411+ logrus .Infoln ("Registering custom Temporal activities for provider" , result .key )
412+
413+ // Now register any custom activities defined by the provider
414+ err = models .RegisterActivities (
415+ temporalService ,
416+ providerResult .GetIdentifier (),
417+ customActivities ,
418+ )
331419 if err != nil {
332- logrus .WithError (err ).Errorln ("Failed to register default activities for provider:" , result .key )
420+ logrus .WithError (err ).Errorln ("Failed to register custom activities for provider:" , result .key )
333421 continue
334422 }
335-
336- customActivities := providerResult .RegisterActivities ()
337- if customActivities != nil {
338- // Now register any custom activities defined by the provider
339- err = models .RegisterActivities (
340- temporalService ,
341- providerResult .GetIdentifier (),
342- customActivities ,
343- )
344- if err != nil {
345- logrus .WithError (err ).Errorln ("Failed to register custom activities for provider:" , result .key )
346- continue
347- }
348- }
423+ } else {
424+ logrus .Infoln ("No custom activities to register for provider" , result .key )
349425 }
350426
351427 logrus .Infoln ("Synchronizing provider" , result .key )
@@ -358,7 +434,7 @@ func (c *Config) InitializeProviders() error {
358434 }
359435 } else {
360436 // Provider doesn't have RBAC/Identity capabilities, no sync needed
361- result . provider .SetReady ()
437+ providerResult .SetReady ()
362438 }
363439
364440 // The provider returned from the goroutine already has the client set
@@ -425,7 +501,8 @@ func (c *Config) initializeSingleProvider(providerKey string, p *models.Provider
425501// getProviderImplementation returns the appropriate provider implementation based on config mode
426502func (c * Config ) getProviderImplementation (providerKey string , providerName string ) (models.Provider , error ) {
427503
428- if c .IsServer () || c .IsAgent () {
504+ // TODO
505+ if c .IsServer () || c .IsAgent () || c .IsClient () {
429506 return providers .CreateInstance (strings .ToLower (providerName ))
430507 }
431508
0 commit comments