feat(ansible): make add_host idempotent
Some checks are pending
CI / test (push) Waiting to run
CI / auto-fix (push) Waiting to run
CI / auto-merge (push) Waiting to run

This commit is contained in:
Virgil 2026-04-03 10:43:56 +00:00
parent 8f6bd48cf8
commit 70ec0dbba4
2 changed files with 55 additions and 1 deletions

View file

@ -253,6 +253,27 @@ func TestExecutorExtra_ModuleAddHost_Good_AddsHostAndGroups(t *testing.T) {
assert.Equal(t, []string{"db1"}, GetHosts(e.inventory, "production"))
}
func TestExecutorExtra_ModuleAddHost_Good_IdempotentRepeat(t *testing.T) {
e := NewExecutor("/tmp")
_, err := e.moduleAddHost(map[string]any{
"name": "cache1",
"groups": []any{"caches"},
"role": "redis",
})
require.NoError(t, err)
result, err := e.moduleAddHost(map[string]any{
"name": "cache1",
"groups": []any{"caches"},
"role": "redis",
})
require.NoError(t, err)
assert.False(t, result.Changed)
assert.Equal(t, []string{"cache1"}, GetHosts(e.inventory, "caches"))
}
func TestExecutorExtra_ModuleAddHost_Good_ThroughDispatcher(t *testing.T) {
e := NewExecutor("/tmp")
task := &Task{

View file

@ -12,6 +12,7 @@ import (
"os"
"path"
"path/filepath"
"reflect"
"regexp"
"sort"
"strconv"
@ -1685,14 +1686,19 @@ func (e *Executor) moduleAddHost(args map[string]any) (*TaskResult, error) {
}
host := findInventoryHost(e.inventory.All, name)
changed := false
if host == nil {
host = &Host{}
changed = true
}
if host.Vars == nil {
host.Vars = make(map[string]any)
}
if v := getStringArg(args, "ansible_host", ""); v != "" {
if host.AnsibleHost != v {
changed = true
}
host.AnsibleHost = v
}
switch v := args["ansible_port"].(type) {
@ -1718,22 +1724,40 @@ func (e *Executor) moduleAddHost(args map[string]any) (*TaskResult, error) {
host.AnsiblePort = int(v)
case string:
if port, err := strconv.Atoi(v); err == nil {
if host.AnsiblePort != port {
changed = true
}
host.AnsiblePort = port
}
}
if v := getStringArg(args, "ansible_user", ""); v != "" {
if host.AnsibleUser != v {
changed = true
}
host.AnsibleUser = v
}
if v := getStringArg(args, "ansible_password", ""); v != "" {
if host.AnsiblePassword != v {
changed = true
}
host.AnsiblePassword = v
}
if v := getStringArg(args, "ansible_ssh_private_key_file", ""); v != "" {
if host.AnsibleSSHPrivateKeyFile != v {
changed = true
}
host.AnsibleSSHPrivateKeyFile = v
}
if v := getStringArg(args, "ansible_connection", ""); v != "" {
if host.AnsibleConnection != v {
changed = true
}
host.AnsibleConnection = v
}
if v := getStringArg(args, "ansible_become_password", ""); v != "" {
if host.AnsibleBecomePassword != v {
changed = true
}
host.AnsibleBecomePassword = v
}
@ -1747,12 +1771,18 @@ func (e *Executor) moduleAddHost(args map[string]any) (*TaskResult, error) {
if reserved[key] {
continue
}
if existing, ok := host.Vars[key]; !ok || !reflect.DeepEqual(existing, val) {
changed = true
}
host.Vars[key] = val
}
if e.inventory.All.Hosts == nil {
e.inventory.All.Hosts = make(map[string]*Host)
}
if existing, ok := e.inventory.All.Hosts[name]; !ok || existing != host {
changed = true
}
e.inventory.All.Hosts[name] = host
for _, groupName := range groups {
@ -1764,6 +1794,9 @@ func (e *Executor) moduleAddHost(args map[string]any) (*TaskResult, error) {
if group.Hosts == nil {
group.Hosts = make(map[string]*Host)
}
if existing, ok := group.Hosts[name]; !ok || existing != host {
changed = true
}
group.Hosts[name] = host
}
@ -1777,7 +1810,7 @@ func (e *Executor) moduleAddHost(args map[string]any) (*TaskResult, error) {
data["groups"] = groups
}
return &TaskResult{Changed: true, Msg: msg, Data: data}, nil
return &TaskResult{Changed: changed, Msg: msg, Data: data}, nil
}
func (e *Executor) moduleGroupBy(host string, args map[string]any) (*TaskResult, error) {