Skip to content

template: add RunOnFirstRender option to change_script#27819

Open
VedantMadane wants to merge 1 commit intohashicorp:mainfrom
VedantMadane:template-change-script-first-render
Open

template: add RunOnFirstRender option to change_script#27819
VedantMadane wants to merge 1 commit intohashicorp:mainfrom
VedantMadane:template-change-script-first-render

Conversation

@VedantMadane
Copy link
Copy Markdown

@VedantMadane VedantMadane commented Apr 12, 2026

Description

Add a run_on_first_render option to the change_script template configuration block. When set to true, the configured script will also fire after the initial template render, not only on subsequent re-renders.

Currently, change_mode = "script" only triggers when a template is re-rendered after the initial render. This means initialization logic that depends on the first template content being available has no built-in hook. The new run_on_first_render flag fills that gap.

When enabled, the template manager collects scripts that should fire on first render, then launches a goroutine that polls for the task to reach the running state (since Exec requires a running task driver handle). Once running, the scripts are executed concurrently, following the same processScript path used for re-render scripts.

Example usage in a job spec:

template {
  data        = "{{ key \"config/myapp\" }}"
  destination = "local/config.json"
  change_mode = "script"

  change_script {
    command              = "/usr/local/bin/reload-config.sh"
    timeout              = "10s"
    fail_on_error        = true
    run_on_first_render  = true
  }
}

Testing & Reproduction steps

The change adds the RunOnFirstRender field across the full config stack:

  • nomad/structs.ChangeScript (internal struct)
  • api.ChangeScript (API struct with mapstructure/HCL tags)
  • Conversion in command/agent/job_endpoint.go
  • Normalization in jobspec2/parse_job.go
  • Core logic in client/allocrunner/taskrunner/template/template.go

Updated tests:

  • TestChangeScript_Equal covers the new field in equality checks
  • diff_test.go expectations updated for the new field in plan diffs
  • job_endpoint_test.go expectations updated for API conversion

Links

Fixes #27429

Implementation follows the design direction given by @tgross in the issue discussion: modify handleFirstRender / Run() to trigger scripts on first render, polling IsRunning() until the task driver handle is available.

Contributor Checklist

  • Changelog Entry Will add via make cl if requested.
  • Testing Updated struct equality, diff, and conversion tests for the new field. Integration test for the polling behavior can be added as a follow-up.
  • Documentation Ready to update docs in web-unified-docs if the approach is accepted. The nomad-docs team can advise on placement.

Changes to Security Controls

No changes to security controls. The new field is a boolean configuration option that controls when an already-configured script executes.

@VedantMadane VedantMadane requested review from a team as code owners April 12, 2026 11:11
@hashicorp-cla-app
Copy link
Copy Markdown

hashicorp-cla-app Bot commented Apr 12, 2026

CLA assistant check
All committers have signed the CLA.

@VedantMadane
Copy link
Copy Markdown
Author

I have signed the CLA.

@tehut
Copy link
Copy Markdown
Contributor

tehut commented Apr 14, 2026

@VedantMadane Thanks for pulling this issue and signing the CLA! I'm taking a look and hope to have some feedback for you tomorrow.

@tehut tehut moved this from Needs Triage to In Progress in Nomad - Community Issues Triage Apr 14, 2026
Comment thread client/allocrunner/taskrunner/template/template.go Outdated
Comment thread client/allocrunner/taskrunner/template/template.go
Add a RunOnFirstRender field to the ChangeScript configuration that
allows template change_script to fire after the initial template
render, not only on subsequent re-renders.

When enabled, the template manager waits for the task to reach
the running state after unblocking, then executes the configured
scripts. This is useful for initialization tasks that need to run
once the first template content is available.

Replace the runFirstRenderScripts polling goroutine with a
RunFirstRenderScripts public method that is called from the
template hook Poststart handler. The task runner framework
guarantees Poststart fires once the task reaches running state,
so the polling loop is unnecessary.

Also adds TestTaskTemplateManager_FirstRenderScript covering the
new code path.

Fixes hashicorp#27429
@VedantMadane VedantMadane force-pushed the template-change-script-first-render branch from 5a7b326 to ba098ed Compare April 16, 2026 07:06
Copy link
Copy Markdown
Contributor

@tehut tehut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VedantMadane This looks great. It was neat to see the template execute at task start up.

Image

Since this PR will close out an open issue, would you mind submitting a changelog entry?

https://github.com/hashicorp/nomad/blob/main/contributing/CHANGELOG.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

option to run template.change_script on first render

3 participants