@@ -1613,7 +1613,11 @@ func (s *server) completeTemplateImportJob(ctx context.Context, job database.Pro
16131613 slog .F ("resource_type" , resource .Type ),
16141614 slog .F ("transition" , transition ))
16151615
1616- if err := InsertWorkspaceResource (ctx , db , jobID , transition , resource , telemetrySnapshot ); err != nil {
1616+ if err := InsertWorkspaceResource (ctx , db , jobID , transition , resource , telemetrySnapshot ,
1617+ InsertWorkspaceResourceWithValidationMode (ValidationModeStrict ),
1618+ InsertWorkspaceResourceWithDeploymentValues (s .DeploymentValues ),
1619+ InsertWorkspaceResourceWithLogger (s .Logger ),
1620+ ); err != nil {
16171621 return xerrors .Errorf ("insert resource: %w" , err )
16181622 }
16191623 }
@@ -2014,6 +2018,9 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
20142018 // Ensure that the agent IDs we set previously
20152019 // are written to the database.
20162020 InsertWorkspaceResourceWithAgentIDsFromProto (),
2021+ InsertWorkspaceResourceWithValidationMode (ValidationModeUpgrade ),
2022+ InsertWorkspaceResourceWithDeploymentValues (s .DeploymentValues ),
2023+ InsertWorkspaceResourceWithLogger (s .Logger ),
20172024 )
20182025 if err != nil {
20192026 return xerrors .Errorf ("insert provisioner job: %w" , err )
@@ -2623,8 +2630,23 @@ func InsertWorkspacePresetAndParameters(ctx context.Context, db database.Store,
26232630 return nil
26242631}
26252632
2633+ // ValidationMode determines how agent metadata interval validation is enforced.
2634+ type ValidationMode int
2635+
2636+ const (
2637+ // ValidationModeStrict fails the operation if metadata intervals are below the minimum.
2638+ // Used for template imports.
2639+ ValidationModeStrict ValidationMode = iota
2640+ // ValidationModeUpgrade silently upgrades metadata intervals to meet the minimum.
2641+ // Used for workspace builds.
2642+ ValidationModeUpgrade
2643+ )
2644+
26262645type insertWorkspaceResourceOptions struct {
26272646 useAgentIDsFromProto bool
2647+ validationMode ValidationMode
2648+ deploymentValues * codersdk.DeploymentValues
2649+ logger slog.Logger
26282650}
26292651
26302652// InsertWorkspaceResourceOption represents a functional option for
@@ -2639,6 +2661,27 @@ func InsertWorkspaceResourceWithAgentIDsFromProto() InsertWorkspaceResourceOptio
26392661 }
26402662}
26412663
2664+ // InsertWorkspaceResourceWithValidationMode sets the validation mode for agent metadata intervals.
2665+ func InsertWorkspaceResourceWithValidationMode (mode ValidationMode ) InsertWorkspaceResourceOption {
2666+ return func (opts * insertWorkspaceResourceOptions ) {
2667+ opts .validationMode = mode
2668+ }
2669+ }
2670+
2671+ // InsertWorkspaceResourceWithDeploymentValues sets the deployment values for validation.
2672+ func InsertWorkspaceResourceWithDeploymentValues (dv * codersdk.DeploymentValues ) InsertWorkspaceResourceOption {
2673+ return func (opts * insertWorkspaceResourceOptions ) {
2674+ opts .deploymentValues = dv
2675+ }
2676+ }
2677+
2678+ // InsertWorkspaceResourceWithLogger sets the logger for logging validation actions.
2679+ func InsertWorkspaceResourceWithLogger (logger slog.Logger ) InsertWorkspaceResourceOption {
2680+ return func (opts * insertWorkspaceResourceOptions ) {
2681+ opts .logger = logger
2682+ }
2683+ }
2684+
26422685func InsertWorkspaceResource (ctx context.Context , db database.Store , jobID uuid.UUID , transition database.WorkspaceTransition , protoResource * sdkproto.Resource , snapshot * telemetry.Snapshot , opt ... InsertWorkspaceResourceOption ) error {
26432686 opts := & insertWorkspaceResourceOptions {}
26442687 for _ , o := range opt {
@@ -2776,13 +2819,39 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
27762819 snapshot .WorkspaceAgents = append (snapshot .WorkspaceAgents , telemetry .ConvertWorkspaceAgent (dbAgent ))
27772820
27782821 for _ , md := range prAgent .Metadata {
2822+ interval := md .Interval
2823+
2824+ // Apply minimum interval validation if configured
2825+ if opts .deploymentValues != nil && opts .deploymentValues .AgentMetadataMinInterval .Value () > 0 {
2826+ minInterval := opts .deploymentValues .AgentMetadataMinInterval .Value ()
2827+ minIntervalSeconds := int64 (minInterval .Seconds ())
2828+
2829+ if interval < minIntervalSeconds {
2830+ if opts .validationMode == ValidationModeStrict {
2831+ // Template import - fail the operation
2832+ return xerrors .Errorf (
2833+ "agent %q metadata %q interval %ds is below minimum required %ds" ,
2834+ prAgent .Name , md .Key , interval , minIntervalSeconds ,
2835+ )
2836+ }
2837+ // Workspace build - upgrade silently
2838+ opts .logger .Info (ctx , "upgrading agent metadata interval to meet minimum" ,
2839+ slog .F ("agent" , prAgent .Name ),
2840+ slog .F ("metadata_key" , md .Key ),
2841+ slog .F ("original_interval_seconds" , interval ),
2842+ slog .F ("upgraded_interval_seconds" , minIntervalSeconds ),
2843+ )
2844+ interval = minIntervalSeconds
2845+ }
2846+ }
2847+
27792848 p := database.InsertWorkspaceAgentMetadataParams {
27802849 WorkspaceAgentID : agentID ,
27812850 DisplayName : md .DisplayName ,
27822851 Script : md .Script ,
27832852 Key : md .Key ,
27842853 Timeout : md .Timeout ,
2785- Interval : md . Interval ,
2854+ Interval : interval ,
27862855 // #nosec G115 - Order represents a display order value that's always small and fits in int32
27872856 DisplayOrder : int32 (md .Order ),
27882857 }
0 commit comments