fix(ansible): preserve YAML module order
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
585123d817
commit
f0878a202c
2 changed files with 52 additions and 22 deletions
59
parser.go
59
parser.go
|
|
@ -287,7 +287,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error {
|
|||
*t = Task(raw)
|
||||
t.raw = m
|
||||
|
||||
// Find the module key
|
||||
// Find the module key in YAML order so the first recognised module wins.
|
||||
knownKeys := map[string]bool{
|
||||
"name": true, "register": true, "when": true, "loop": true,
|
||||
"loop_control": true, "vars": true, "environment": true,
|
||||
|
|
@ -301,28 +301,43 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error {
|
|||
"with_items": true, "with_dict": true, "with_file": true,
|
||||
}
|
||||
|
||||
for key, val := range m {
|
||||
if knownKeys[key] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if this is a module
|
||||
if isModule(key) {
|
||||
t.Module = key
|
||||
t.Args = make(map[string]any)
|
||||
|
||||
switch v := val.(type) {
|
||||
case string:
|
||||
// Free-form args (e.g., shell: echo hello)
|
||||
t.Args["_raw_params"] = v
|
||||
case map[string]any:
|
||||
t.Args = v
|
||||
case nil:
|
||||
// Module with no args
|
||||
default:
|
||||
t.Args["_raw_params"] = v
|
||||
if node.Kind == yaml.MappingNode {
|
||||
for i := 0; i+1 < len(node.Content); i += 2 {
|
||||
keyNode := node.Content[i]
|
||||
valueNode := node.Content[i+1]
|
||||
key := keyNode.Value
|
||||
if knownKeys[key] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if this is a module.
|
||||
if isModule(key) {
|
||||
t.Module = key
|
||||
t.Args = make(map[string]any)
|
||||
|
||||
switch valueNode.Kind {
|
||||
case yaml.MappingNode:
|
||||
var args map[string]any
|
||||
if err := valueNode.Decode(&args); err == nil {
|
||||
t.Args = args
|
||||
}
|
||||
case yaml.SequenceNode:
|
||||
var args any
|
||||
if err := valueNode.Decode(&args); err == nil {
|
||||
t.Args["_raw_params"] = args
|
||||
}
|
||||
case yaml.ScalarNode:
|
||||
if valueNode.Tag != "!!null" {
|
||||
t.Args["_raw_params"] = valueNode.Value
|
||||
}
|
||||
default:
|
||||
var args any
|
||||
if err := valueNode.Decode(&args); err == nil && args != nil {
|
||||
t.Args["_raw_params"] = args
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,21 @@ with_items:
|
|||
assert.Len(t, items, 2)
|
||||
}
|
||||
|
||||
func TestTypes_Task_UnmarshalYAML_Good_FirstRecognisedModuleWins(t *testing.T) {
|
||||
input := `
|
||||
name: Multiple modules
|
||||
shell: echo first
|
||||
debug:
|
||||
msg: "second"
|
||||
`
|
||||
var task Task
|
||||
err := yaml.Unmarshal([]byte(input), &task)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "shell", task.Module)
|
||||
assert.Equal(t, "echo first", task.Args["_raw_params"])
|
||||
}
|
||||
|
||||
func TestTypes_Task_UnmarshalYAML_Good_WithNotify(t *testing.T) {
|
||||
input := `
|
||||
name: Install package
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue