diff --git a/executor.go b/executor.go index b1d3903..a98da1e 100644 --- a/executor.go +++ b/executor.go @@ -612,6 +612,19 @@ func (e *Executor) runTaskOnHost(ctx context.Context, host string, hosts []strin } start := time.Now() + e.mu.Lock() + oldInventoryHostname, hadInventoryHostname := e.vars["inventory_hostname"] + e.vars["inventory_hostname"] = host + e.mu.Unlock() + defer func() { + e.mu.Lock() + if hadInventoryHostname { + e.vars["inventory_hostname"] = oldInventoryHostname + } else { + delete(e.vars, "inventory_hostname") + } + e.mu.Unlock() + }() if e.OnTaskStart != nil { e.OnTaskStart(host, task) diff --git a/executor_test.go b/executor_test.go index 3f80a59..661ace7 100644 --- a/executor_test.go +++ b/executor_test.go @@ -274,6 +274,27 @@ func TestExecutor_RunTaskOnHost_Good_DelegateToUsesDelegatedClient(t *testing.T) assert.Equal(t, 1, mock.commandCount()) } +func TestExecutor_RunTaskOnHost_Good_DelegateToTemplatesInventoryHostname(t *testing.T) { + e := NewExecutor("/tmp") + mock := NewMockSSHClient() + e.clients["host1-delegate"] = mock + mock.expectCommand(`echo templated`, "templated", "", 0) + + task := &Task{ + Name: "Templated delegate", + Module: "shell", + Args: map[string]any{"_raw_params": "echo templated"}, + Delegate: "{{ inventory_hostname }}-delegate", + } + + err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) + require.NoError(t, err) + + assert.True(t, mock.hasExecuted(`echo templated`)) + _, leaked := e.vars["inventory_hostname"] + assert.False(t, leaked) +} + func TestExecutor_RunTaskOnHost_Good_ActionAliasExecutesCommand(t *testing.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo action-alias`, "action-alias", "", 0)